├── LICENSE.txt ├── README.md ├── bitset2.hpp ├── detail ├── array2array.hpp ├── array2u_long_t.hpp ├── array_access.hpp ├── array_add.hpp ├── array_complement2.hpp ├── array_funcs.hpp ├── array_ops.hpp ├── bit_chars.hpp ├── bitset2_impl.hpp ├── count_bits.hpp ├── h_types.hpp ├── hash.hpp ├── hex_params.hpp ├── index_lsb_set.hpp ├── index_msb_set.hpp ├── reverse_bits.hpp ├── select_base_t.hpp └── ullong2array.hpp └── tests ├── bench01.cpp ├── counter128.cpp ├── example01.cpp ├── gen_randoms.hpp ├── gray_code.cpp ├── mk.sh ├── test_array2array.cpp ├── test_bitset2_01.cpp ├── test_bitset2_02.cpp ├── test_nonconst_constexpr01.cpp ├── test_ullong2array.cpp └── tests01.cpp /LICENSE.txt: -------------------------------------------------------------------------------- 1 | Boost Software License - Version 1.0 - August 17th, 2003 2 | 3 | Permission is hereby granted, free of charge, to any person or organization 4 | obtaining a copy of the software and accompanying documentation covered by 5 | this license (the "Software") to use, reproduce, display, distribute, 6 | execute, and transmit the Software, and to prepare derivative works of the 7 | Software, and to permit third-parties to whom the Software is furnished to 8 | do so, all subject to the following: 9 | 10 | The copyright notices in the Software and this entire statement, including 11 | the above license grant, this restriction and the following disclaimer, 12 | must be included in all copies of the Software, in whole or in part, and 13 | all derivative works of the Software, unless such copies or derivative 14 | works are solely in the form of machine-executable object code generated by 15 | a source language processor. 16 | 17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT 20 | SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE 21 | FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, 22 | ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 23 | DEALINGS IN THE SOFTWARE. 24 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # bitset2: bitset improved 2 | 3 | |Note| 4 | |----| 5 | |This version of bitset2 is for C++17. For C++14 checkout the corresponding [branch](https://github.com/ClaasBontus/bitset2/tree/cpp14).| 6 | 7 | **Bitset2::bitset2** is a header-only library. It provides the same functionality as [std::bitset](http://en.cppreference.com/w/cpp/utility/bitset) with the 8 | following extensions/changes. 9 | 10 | 11 | Focus was set on having as many functions 12 | implemented as [constexpr](http://en.cppreference.com/w/cpp/language/constexpr) 13 | as possible. Moreover a second template parameter (with appropriate default) 14 | allows control of the underlying data structure (see below). 15 | * Copy and move constructors are specified as constexpr. 16 | * Additional constexpr constructor `bitset2( std::array const & )`, where `T` needs not necessarily be equal to `base_t`. `T` has to be an unsigned integral type. 17 | * Additional constexpr constructor `bitset2( unsigned __int128 )` if supported by compiler. 18 | * Conversion from and to `std::bitset`. 19 | * Operators implemented as constexpr are `~`, `==`, `!=`, `|`, `&`, `^`, `<<` (shift left), `>>` (shift right), `[]` (bit access). 20 | * Non-const operators implemented as constexpr are `<<=`, `>>=`, `|=`, `&=`, `^=` 21 | * Functions implemented as constexpr are `test`, `none`, `any`, `all`, `count`, `to_ulong`, `to_ullong`. 22 | * Non-const functions implemented as constexpr are `set`, `reset`, and `flip`. 23 | * Additional constexpr operator `+` for adding two bitset2 objects. 24 | * Additional constexpr operators `++`, `--`, `+=`. 25 | * Additional constexpr operators `<`, `>`, `<=`, `>=`. 26 | * Additional constexpr functions `rotate_left` and `rotate_right` for binary rotations. 27 | * Additional constexpr member functions `rotate_left` and `rotate_right`. 28 | * Additional member function `to_hex_string()` (see below). 29 | * Additional constexpr member function `to_u128()` (if supported by the compiler) returning an `unsigned __int128` value. Throws `std::overflow_error` if the value doesn't fit into 128 bits. 30 | * Additional constexpr member function `test_set( size_t bit, bool value= true )`, which sets or clears the specified bit and returns its previous state. Throws `out_of_range` if bit >= N. 31 | * Additional constexpr function `difference`, which computes the set difference (`bs1 & ~bs2`) of two bitset2 objects. 32 | * Additional constexpr member function `difference`. 33 | * Additional constexpr member functions `find_first()`, `find_last`, and `find_next(size_t)` return the index of the first, last, or next bit set respectively. Returning `npos` if all (remaining) bits are false. 34 | * Additional constexpr member functions `find_first_zero()`, `find_last_zero`, and `find_next_zero(size_t)` return the index of the first, last, or next bit unset respectively. Returning `npos` if all (remaining) bits are true. 35 | * Additional constexpr member function `has_single_bit` returning true if exactly one bit is set. 36 | * Additional constexpr function `complement2(bs)` computing the [two's complement](https://en.wikipedia.org/wiki/Two%27s_complement) (~bs +1). 37 | * Additional constexpr member function `complement2`. 38 | * Additional constexpr function `reverse`, which returns its argument with bits reversed. 39 | * Additional constexpr member function `reverse`. 40 | * Additional constexpr function `midpoint(bs1,bs2,bool round_down=false)` returns half the sum of bs1 and bs2 without overflow. Like [std::midpoint](https://en.cppreference.com/w/cpp/numeric/midpoint) rounds towards `bs1` if `round_down==false`. 41 | * Additional constexpr function `convert_to` for converting an *m*-bit bitset2 into an *n*-bit bitset2. 42 | * Additional constexpr function `convert_to` for converting an *m*-bit bitset2 into an *n*-bit bitset2 with `base_t=T`. 43 | * Constexpr member function `data()` gives read access to the underlying `array`. Here element with an index zero is the least significant word. 44 | * Additional constexpr functions `zip_fold_and` and `zip_fold_or`. See below for details. 45 | 46 | ## Examples 47 | ```.cpp 48 | #include 49 | #include 50 | #include 51 | #include "bitset2.hpp" 52 | 53 | template 54 | using BS2= Bitset2::bitset2; 55 | 56 | int main() 57 | { 58 | using bs_128= BS2<128>; 59 | using base_t_128= bs_128::base_t; 60 | constexpr std::array 61 | ar1{{ ~(base_t_128(0)), base_t_128(0xFEDCBA) }}; 62 | constexpr bs_128 b1{ ar1 }; 63 | constexpr auto b1_add= b1 + b1; 64 | constexpr auto b1_shft= b1 << 1; // binary shift 65 | static_assert( b1_add == b1_shft, "" ); 66 | 67 | std::cout << b1.to_hex_string() // 0000000000fedcbaffffffffffffffff 68 | << "\n" 69 | << b1_add.to_hex_string() // 0000000001fdb975fffffffffffffffe 70 | << "\n"; 71 | 72 | BS2<12> b2; 73 | for( size_t c= 0; c < 12; c += 2 ) b2[c]= true; 74 | auto b3= ~b2; 75 | std::cout << b2 << "\n"; // 010101010101 76 | std::cout << b2.flip() << "\n"; // 101010101010 77 | assert( b2 == b3 ); 78 | 79 | BS2<7> const b4{ "1110000" }; 80 | auto const b5= Bitset2::rotate_left( b4, 3 ); 81 | std::cout << b4 << "\n" // 1110000 82 | << b5 << "\n"; // 0000111 83 | 84 | BS2<7> b6{ "1010010" }; 85 | b6.reverse(); 86 | std::cout << b6 << "\n"; // 0100101 87 | } 88 | ``` 89 | 90 | The following example illustrates how 91 | [non-const constexpr](https://stackoverflow.com/q/43592862/3876684) 92 | operators and functions are useful for writing constexpr functions. 93 | It converts between [Gray](https://en.wikipedia.org/wiki/Gray_code) 94 | and binary encoding. 95 | 96 | ```.cpp 97 | template 98 | constexpr 99 | Bitset2::bitset2 100 | binary_to_gray( Bitset2::bitset2 const &bs ) 101 | { return bs ^ (bs >> 1); } 102 | 103 | template 104 | constexpr 105 | Bitset2::bitset2 106 | gray_to_binary( Bitset2::bitset2 bs ) 107 | { 108 | Bitset2::bitset2 mask= bs >> 1; 109 | for( ; !mask.none(); mask >>= 1 ) bs ^= mask; 110 | return bs; 111 | } // gray_to_binary 112 | 113 | int main() 114 | { 115 | using ULLONG= unsigned long long; 116 | constexpr std::array arr_01a{{ 0xFEFDFCFBFAF9F8F7ull, 1ull }}; 117 | constexpr Bitset2::bitset2<129> bs_01a{ arr_01a }; 118 | constexpr auto gray_01a= binary_to_gray( bs_01a ); 119 | constexpr auto bin_01a= gray_to_binary( gray_01a ); 120 | 121 | static_assert( bs_01a == bin_01a, "" ); 122 | } 123 | ``` 124 | 125 | ## Template parameters and underlying data type 126 | `bitset2` is declared as 127 | ```.cpp 128 | template< size_t N, class T > 129 | class bitset2; 130 | ``` 131 | `N` is the number of bits and `T` has to be an unsigned 132 | [integral type](http://en.cppreference.com/w/cpp/types/is_integral). 133 | `T` can be `unsigned __int128` if supported by the compiler. Data 134 | represented by `bitset2` objects are stored in elements of type 135 | `std::array`. 136 | 137 | `T` defaults 138 | to `uint8_t`, `uint16_t`, or `uint32_t` if `N` bits fit into these integers 139 | (and the type is supported by the system). 140 | `T` defaults to `unsigned long long` otherwise. The following aliases and 141 | constants are public within `bitset2`: 142 | * `using base_t= T;` 143 | * `size_t n_array;` Number of words in the underlying array 144 | * `using array_t= std::array;` Underlying data type 145 | 146 | ## to_hex_string 147 | The function `to_hex_string` takes - as an optional argument - an element of type 148 | `hex_params`, which is defined as 149 | ```.cpp 150 | template< class CharT = char, 151 | class Traits = std::char_traits, 152 | class Allocator = std::allocator > 153 | struct hex_params 154 | { 155 | using str_t= std::basic_string; 156 | 157 | CharT zeroCh= CharT( '0' ); 158 | CharT aCh= CharT( 'a' ); 159 | bool leadingZeroes= true; 160 | bool nonEmpty= true; 161 | str_t prefix; 162 | }; 163 | ``` 164 | It allows for fine-tuning the outcome of the function. In the following 165 | examples, the output is shown in the comments. 166 | ```.cpp 167 | bitset2<16> b16_a( "0000101000011111" ); 168 | bitset2<16> b16_b; 169 | std::cout 170 | << b16_a.to_hex_string() << '\n' // 0a1f 171 | << b16_a.to_hex_string( hex_params<>{'0', 'A', false, true, "0x"}) // 0xA1F 172 | << '\n' 173 | << b16_a.to_hex_string( {.aCh='A', .leadingZeroes=false, .prefix="0x"} ) // Same with C++-20 174 | << '\n' 175 | << b16_b.to_hex_string() << '\n' // 0000 176 | << b16_b.to_hex_string( hex_params<>{'0', 'a', false, false, "0X"}) // 0X 177 | << '\n' 178 | << b16_b.to_hex_string( {.leadingZeroes=false, .nonEmpty=false, .prefix="0X"} ) // Same with C++-20 179 | << '\n'; 180 | ``` 181 | 182 | ## zip\_fold\_* 183 | Functions `zip_fold_and(bs1,bs2,f)` and `zip_fold_or(bs1,bs2,f)` expect two 184 | variables of type `bitset2` and a functional object `f`. 185 | The latter must accept two variables of type `base_t` and return a `bool`. 186 | `zip_fold_*` are mapped over the underlying 187 | `std::array`s. They will 188 | [short-circuit](http://en.cppreference.com/w/cpp/language/operator_logical) 189 | if possible, which can result in performance advantages. 190 | `zip_fold_and` returns `true` if `f` 191 | returns `true` for each pair of `base_t`s, while `zip_fold_or` returns `true` 192 | if `f` returns `true` for at least one pair of `base_t`s. 193 | In other words `zip_fold_and` and `zip_fold_or` are similar to 194 | [`std::inner_product(...,BinOp1 op1,BinOp2 op2)`](http://en.cppreference.com/w/cpp/algorithm/inner_product) 195 | with `op1` set to `&&` and `||`, resp. 196 | 197 | For instance `is_subset_of` as proposed in [p0125r0](http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/p0125r0.html) 198 | can be implemented as follows. 199 | ```.cpp 200 | template 201 | constexpr 202 | bool 203 | is_subset_of( Bitset2::bitset2 const &bs1, 204 | Bitset2::bitset2 const &bs2 ) noexcept 205 | { 206 | using base_t= T; 207 | return Bitset2::zip_fold_and( bs1, bs2, 208 | []( base_t v1, base_t v2 ) noexcept 209 | // Any bit unset in v2 must not be set in v1 210 | { return (v1 & ~v2) == 0; } ); 211 | } 212 | 213 | constexpr Bitset2::bitset2<7> b7_a( 0b1000101ull ); 214 | constexpr Bitset2::bitset2<7> b7_b( 0b1010101ull ); 215 | static_assert( is_subset_of( b7_a, b7_b), "" ); 216 | ``` 217 | 218 | Similarly, an `unequal` function can be defined as 219 | ```.cpp 220 | template 221 | bool 222 | unequal( Bitset2::bitset2 const &bs1, Bitset2::bitset2 const &bs2 ) 223 | { 224 | using base_t= T; 225 | return Bitset2::zip_fold_or( bs1, bs2, 226 | []( base_t v1, base_t v2 ) noexcept 227 | { return v1 != v2; } ); 228 | } 229 | ``` 230 | 231 | ## Trivia 232 | The following code shows a counter based on a 128-bit integer. If the 233 | counter gets incremented once at each nanosecond, you have to wait for 234 | overflow for *only* [1.078 * 1022 years](http://www.wolframalpha.com/input/?i=2%5E128+nanoseconds). 235 | ```.cpp 236 | Bitset2::bitset2<128> c; 237 | for( ;; ++c ) {} 238 | ``` 239 | 240 | ## Caveats 241 | * bitset2 requires a C++17 compliant compiler. 242 | * Tested with GCC 12 and Clang 15. 243 | -------------------------------------------------------------------------------- /bitset2.hpp: -------------------------------------------------------------------------------- 1 | // BITSET2 2 | // 3 | // Copyright Claas Bontus 4 | // 5 | // Use, modification and distribution is subject to the 6 | // Boost Software License, Version 1.0. (See accompanying 7 | // file LICENSE.txt or copy at 8 | // http://www.boost.org/LICENSE_1_0.txt) 9 | // 10 | // Project home: https://github.com/ClaasBontus/bitset2 11 | // 12 | 13 | 14 | #ifndef BITSET2_CB_HPP 15 | #define BITSET2_CB_HPP 16 | 17 | 18 | #include "detail/hex_params.hpp" 19 | #include "detail/select_base_t.hpp" 20 | #include "detail/hash.hpp" 21 | #include "detail/array_access.hpp" 22 | #include "detail/array_funcs.hpp" 23 | #include "detail/array_add.hpp" 24 | #include "detail/array_ops.hpp" 25 | #include "detail/array_complement2.hpp" 26 | #include "detail/array2array.hpp" 27 | #include "detail/bitset2_impl.hpp" 28 | 29 | #include 30 | #include 31 | #include 32 | #include 33 | #include 34 | #include 35 | #include 36 | #include 37 | #include 38 | 39 | 40 | 41 | namespace Bitset2 42 | { 43 | 44 | 45 | 46 | template, 48 | class Enabled=void> class bitset2; 49 | 50 | template 51 | class bitset2::value>::type> 53 | : public detail::bitset2_impl 54 | { 55 | enum : size_t { base_t_n_bits= detail::bitset2_impl::base_t_n_bits }; 56 | public: 57 | using array_t= typename detail::bitset2_impl::array_t; 58 | using ULLONG_t= typename detail::bitset2_impl::ULLONG_t; 59 | using LRGST_t= typename detail::bitset2_impl::LRGST_t; 60 | using base_t= T; 61 | using detail::bitset2_impl::n_array; 62 | 63 | enum : size_t { npos= detail::h_types::npos }; 64 | 65 | class reference 66 | { 67 | friend class bitset2; 68 | reference() noexcept {} 69 | 70 | constexpr 71 | reference( bitset2 *ptr, size_t bit ) noexcept 72 | : m_ptr( ptr ) 73 | , m_bit( bit ) 74 | {} 75 | 76 | bitset2 *m_ptr= nullptr; 77 | size_t m_bit; 78 | public: 79 | constexpr 80 | reference& operator=( bool x ) noexcept 81 | { 82 | m_ptr->set_noexcept( m_bit, x ); 83 | return *this; 84 | } 85 | 86 | constexpr 87 | reference& operator=( reference const & r ) noexcept 88 | { 89 | m_ptr->set_noexcept( m_bit, bool( r ) ); 90 | return *this; 91 | } 92 | 93 | constexpr 94 | reference& flip() noexcept 95 | { 96 | m_ptr->flip_noexcept( m_bit ); 97 | return *this; 98 | } 99 | 100 | constexpr 101 | operator bool() const noexcept 102 | { return m_ptr->test_noexcept(m_bit); } 103 | 104 | constexpr 105 | bool operator~() const noexcept 106 | { return !bool(*this); } 107 | }; // class reference 108 | 109 | 110 | /* ------------------------------------------------------------- */ 111 | constexpr 112 | bitset2() noexcept 113 | : detail::bitset2_impl() 114 | {} 115 | 116 | constexpr 117 | bitset2( bitset2 const & ) noexcept= default; 118 | 119 | constexpr 120 | bitset2( bitset2 && ) noexcept= default; 121 | 122 | constexpr 123 | bitset2 & 124 | operator=( bitset2 const & ) noexcept= default; 125 | 126 | constexpr 127 | bitset2 & 128 | operator=( bitset2 && ) noexcept= default; 129 | 130 | explicit 131 | bitset2( const std::bitset &bs ) noexcept 132 | : detail::bitset2_impl( bs ) 133 | {} 134 | 135 | explicit 136 | constexpr 137 | bitset2( LRGST_t v ) noexcept 138 | : detail::bitset2_impl( v ) 139 | {} 140 | 141 | template 142 | explicit 143 | constexpr 144 | bitset2( std::array const & value ) noexcept 145 | : detail::bitset2_impl( value ) 146 | {} 147 | 148 | template< class CharT, class Traits, class Alloc > 149 | explicit 150 | bitset2( std::basic_string const 151 | & str, 152 | typename std::basic_string::size_type 153 | pos = 0, 154 | typename std::basic_string::size_type 155 | n = std::basic_string::npos, 156 | CharT zero= CharT('0'), 157 | CharT one= CharT('1') ) 158 | : detail::bitset2_impl( str, pos, n, zero, one ) 159 | {} 160 | 161 | 162 | template< class CharT > 163 | explicit 164 | bitset2( const CharT *str, 165 | typename std::basic_string::size_type 166 | n= std::basic_string::npos, 167 | CharT zero= CharT('0'), 168 | CharT one= CharT('1') ) 169 | : detail::bitset2_impl( n == std::basic_string::npos 170 | ? std::basic_string( str ) 171 | : std::basic_string( str, n ), 172 | 0, n, zero, one ) 173 | {} 174 | /* ------------------------------------------------------------- */ 175 | 176 | 177 | //**************************************************** 178 | 179 | /// Bitwise NOT 180 | constexpr 181 | bitset2 182 | operator~() const noexcept 183 | { return bitset2(detail::array_ops( 0 ).flip(this->data())); } 184 | 185 | constexpr 186 | bool 187 | operator[]( size_t bit ) const noexcept 188 | { return detail::bitset2_impl::operator[]( bit ); } 189 | 190 | constexpr 191 | reference 192 | operator[]( size_t bit ) noexcept 193 | { return reference( this, bit ); } 194 | 195 | constexpr 196 | bitset2 & 197 | operator<<=( size_t n_shift ) noexcept 198 | { 199 | detail::array_ops( n_shift ).shift_left_assgn( this->get_data() ); 200 | return *this; 201 | } 202 | 203 | /// Shift left 204 | friend 205 | constexpr 206 | bitset2 207 | operator<<( bitset2 const & bs, size_t n_shift ) noexcept 208 | { 209 | return 210 | Bitset2::bitset2( Bitset2::detail::array_ops( n_shift ) 211 | .shift_left( bs.data() ) ); 212 | } 213 | 214 | /// Stream output 215 | template 216 | friend 217 | std::basic_ostream & 218 | operator<<( std::basic_ostream & os, bitset2 const & x ) 219 | { 220 | for( size_t ct= N; ct > 0; ) 221 | { 222 | --ct; 223 | os << ( x[ct] ? "1" : "0" ); 224 | } 225 | return os; 226 | } 227 | 228 | constexpr 229 | bitset2 & 230 | operator>>=( size_t n_shift ) noexcept 231 | { 232 | detail::array_ops( n_shift ).shift_right_assgn( this->get_data() ); 233 | return *this; 234 | } 235 | 236 | /// Shift right 237 | friend 238 | constexpr 239 | bitset2 240 | operator>>( bitset2 const & bs, size_t n_shift ) noexcept 241 | { 242 | return 243 | Bitset2::bitset2( Bitset2::detail::array_ops( n_shift ) 244 | .shift_right( bs.data() ) ); 245 | } 246 | 247 | /// Stream input 248 | template 249 | friend 250 | std::basic_istream & 251 | operator>>( std::basic_istream & is, bitset2 & x ) 252 | { 253 | std::bitset bs; 254 | is >> bs; 255 | x= Bitset2::bitset2( bs ); 256 | return is; 257 | } 258 | 259 | constexpr 260 | bitset2 & 261 | rotate_left( size_t n_rot ) noexcept 262 | { 263 | this->get_data()= detail::array_ops(n_rot).rotate_left( this->data() ); 264 | return *this; 265 | } 266 | 267 | constexpr 268 | bitset2 & 269 | rotate_right( size_t n_rot ) noexcept 270 | { 271 | this->get_data()= detail::array_ops( N - ( n_rot % N ) ) 272 | .rotate_left( this->data() ); 273 | return *this; 274 | } 275 | 276 | constexpr 277 | bitset2 & 278 | reverse() noexcept 279 | { 280 | this->get_data()= detail::array_ops( 0 ).reverse( this->data() ); 281 | return *this; 282 | } 283 | 284 | /// Computes two's complement 285 | constexpr 286 | bitset2 & 287 | complement2() noexcept 288 | { 289 | detail::array_complement2().comp2_assgn( this->get_data() ); 290 | return *this; 291 | } 292 | 293 | constexpr 294 | bitset2 & 295 | operator+=( bitset2 const &bs2 ) noexcept 296 | { 297 | detail::array_add().add_assgn(this->get_data(), bs2.data()); 298 | return *this; 299 | } 300 | 301 | friend 302 | constexpr 303 | bitset2 304 | operator+( bitset2 const & bs1, bitset2 const & bs2 ) noexcept 305 | { 306 | return 307 | Bitset2::bitset2( 308 | detail::array_add().add( bs1.data(), bs2.data() ) ); 309 | } 310 | 311 | constexpr 312 | bitset2 & 313 | operator++() noexcept 314 | { 315 | detail::array_ops(0).increment( this->get_data() ); 316 | return *this; 317 | } 318 | 319 | constexpr 320 | bitset2 321 | operator++(int) noexcept 322 | { 323 | bitset2 tmp( *this ); 324 | operator++(); 325 | return tmp; 326 | } 327 | 328 | constexpr 329 | bitset2 & 330 | operator--() noexcept 331 | { 332 | detail::array_ops(0).decrement( this->get_data() ); 333 | return *this; 334 | } 335 | 336 | constexpr 337 | bitset2 338 | operator--(int) noexcept 339 | { 340 | bitset2 tmp( *this ); 341 | operator--(); 342 | return tmp; 343 | } 344 | 345 | constexpr 346 | bitset2 & 347 | operator|=( bitset2 const & v2 ) noexcept 348 | { 349 | detail::array_funcs() 350 | .bitwise_or_assgn(this->get_data(), v2.data() ); 351 | return *this; 352 | } 353 | 354 | friend 355 | constexpr 356 | bitset2 357 | operator|( bitset2 const & bs1, bitset2 const & bs2 ) noexcept 358 | { 359 | return 360 | Bitset2::bitset2( 361 | detail::array_funcs() 362 | .bitwise_or(bs1.data(), bs2.data()) ); 363 | } 364 | 365 | constexpr 366 | bitset2 & 367 | operator&=( bitset2 const & v2 ) noexcept 368 | { 369 | detail::array_funcs() 370 | .bitwise_and_assgn( this->get_data(), v2.data() ); 371 | return *this; 372 | } 373 | 374 | friend 375 | constexpr 376 | bitset2 377 | operator&( bitset2 const & bs1, bitset2 const & bs2 ) noexcept 378 | { 379 | return 380 | Bitset2::bitset2( 381 | detail::array_funcs() 382 | .bitwise_and( bs1.data(), bs2.data() ) ); 383 | } 384 | 385 | constexpr 386 | bitset2 & 387 | operator^=( bitset2 const & v2 ) noexcept 388 | { 389 | detail::array_funcs() 390 | .bitwise_xor_assgn( this->get_data(), v2.data() ); 391 | return *this; 392 | } 393 | 394 | friend 395 | constexpr 396 | bitset2 397 | operator^( bitset2 const & bs1, bitset2 const & bs2 ) noexcept 398 | { 399 | return 400 | Bitset2::bitset2( 401 | detail::array_funcs() 402 | .bitwise_xor( bs1.data(), bs2.data() ) ); 403 | } 404 | 405 | /// Computes the set difference, i.e. *this &= ~v2 406 | constexpr 407 | bitset2 & 408 | difference( bitset2 const & v2 ) noexcept 409 | { 410 | detail::array_funcs() 411 | .bitwise_setdiff_assgn( this->get_data(), v2.data() ); 412 | return *this; 413 | } 414 | 415 | constexpr 416 | bitset2 & 417 | set() noexcept 418 | { detail::bitset2_impl::set(); return *this; } 419 | 420 | constexpr 421 | bitset2 & 422 | set( size_t bit, bool value= true ) 423 | { detail::bitset2_impl::set( bit, value ); return *this; } 424 | 425 | constexpr 426 | bitset2 & 427 | reset() noexcept 428 | { detail::bitset2_impl::reset(); return *this; } 429 | 430 | constexpr 431 | bitset2 & 432 | reset( size_t bit ) 433 | { 434 | if( bit >= N ) throw std::out_of_range( "bitset2: reset out of range" ); 435 | return set( bit, false ); 436 | } 437 | 438 | /// \brief Sets the specified bit if value==true, 439 | /// clears it otherwise. Returns the previous state of the bit. 440 | constexpr 441 | bool 442 | test_set( size_t bit, bool value= true ) 443 | { return detail::bitset2_impl::test_set( bit, value ); } 444 | 445 | constexpr 446 | bitset2 & 447 | flip() noexcept 448 | { detail::bitset2_impl::flip(); return *this; } 449 | 450 | constexpr 451 | bitset2 & 452 | flip( size_t bit ) 453 | { detail::bitset2_impl::flip( bit ); return *this; } 454 | 455 | constexpr std::size_t size() const noexcept { return N; } 456 | 457 | template, 459 | class Allocator = std::allocator > 460 | std::basic_string 461 | to_string( CharT zero = CharT('0'), CharT one = CharT('1') ) const 462 | { 463 | std::basic_string ret_val; 464 | ret_val.reserve( N ); 465 | for( size_t ct= N; ct > 0; ) 466 | { 467 | --ct; 468 | ret_val += this->operator[]( ct ) ? one : zero; 469 | } 470 | return ret_val; 471 | } // to_string 472 | 473 | template, 475 | class Allocator = std::allocator, 476 | typename std::enable_if::type* = nullptr > 477 | std::basic_string 478 | to_hex_string( hex_params const ¶ms= 479 | hex_params{} ) const 480 | { 481 | using arr_acc= detail::array_access; 482 | arr_acc a_a; 483 | constexpr auto div_four= arr_acc::div_four; 484 | constexpr auto mod_four= arr_acc::mod_four; 485 | constexpr auto n_char= div_four + ( mod_four > 0 ); 486 | 487 | auto const zeroCh= params.zeroCh; 488 | auto const aCh= params.aCh; 489 | 490 | std::basic_string ret_val; 491 | ret_val.reserve( n_char + params.prefix.size() ); 492 | ret_val= params.prefix; 493 | size_t ct= n_char; 494 | if( !params.leadingZeroes ) 495 | { 496 | for( ; ct > 0; --ct ) 497 | { 498 | auto const val= a_a.get_four_bits( this->data(), 4 * ct - 1 ); 499 | if( val != 0 ) break; 500 | } 501 | } 502 | if( ct == 0 && params.nonEmpty ) ret_val += zeroCh; 503 | for( ; ct > 0; --ct ) 504 | { 505 | auto const val= a_a.get_four_bits( this->data(), 4 * ct - 1 ); 506 | CharT const c= 507 | ( val < 10 ) ? ( zeroCh + val ) : ( aCh + ( val - 10 ) ); 508 | ret_val += c; 509 | } 510 | return ret_val; 511 | } // to_hex_string 512 | 513 | }; // class bitset2 514 | 515 | 516 | 517 | template 518 | constexpr 519 | bitset2 520 | rotate_left( bitset2 const & bs, size_t n_rot ) noexcept 521 | { 522 | return 523 | bitset2( detail::array_ops( n_rot ).rotate_left( bs.data() ) ); 524 | } 525 | 526 | 527 | template 528 | constexpr 529 | bitset2 530 | rotate_right( bitset2 const & bs, size_t n_rot ) noexcept 531 | { 532 | return 533 | bitset2( detail::array_ops( N - ( n_rot % N ) ). 534 | rotate_left( bs.data() ) ); 535 | } 536 | 537 | 538 | /// Computes the set difference, i.e. bs1 & ~bs2 539 | template 540 | constexpr 541 | bitset2 542 | difference( bitset2 const & bs1, bitset2 const & bs2 ) noexcept 543 | { 544 | return 545 | bitset2( detail::array_funcs::n_array,T>() 546 | .bitwise_setdiff( bs1.data(), bs2.data() ) ); 547 | } 548 | 549 | 550 | /// Returns bs with bits reversed 551 | template 552 | constexpr 553 | bitset2 554 | reverse( bitset2 const & bs ) noexcept 555 | { return bitset2( detail::array_ops( 0 ).reverse( bs.data() ) ); } 556 | 557 | 558 | /// Computes the two's complement 559 | template 560 | constexpr 561 | bitset2 562 | complement2( bitset2 const & bs ) noexcept 563 | { return bitset2( detail::array_complement2().comp2(bs.data()) ); } 564 | 565 | 566 | /// Half the sum of bs1 and bs2. No overflow occurs. 567 | template 568 | constexpr 569 | bitset2 570 | midpoint( bitset2 const & bs1, bitset2 const & bs2, 571 | bool round_down = false ) noexcept 572 | { 573 | return bitset2( detail::array_add().midpoint(bs1.data(), bs2.data(), 574 | round_down) ); 575 | } 576 | 577 | 578 | 579 | /// Converts an M-bit bitset2 to an N-bit bitset2. 580 | template 581 | constexpr 582 | bitset2 583 | convert_to( bitset2 const & bs ) noexcept 584 | { 585 | using a2a= 586 | detail::array2array::n_array,bitset2::n_array,T1,T2>; 587 | return 588 | bitset2(a2a()(detail::bit_chars::hgh_bit_pattern, bs.data())); 589 | } 590 | 591 | 592 | /// Converts an M-bit bitset2 to an N-bit bitset2. 593 | template 594 | constexpr 595 | bitset2 596 | convert_to( bitset2 const & bs ) noexcept 597 | { return bitset2( bs.data() ); } 598 | 599 | 600 | /// \brief Returns true if f returns true for each pair 601 | /// of base_t=T values in bs1 and bs2. f should be a binary function 602 | /// taking two base_t values and returning bool. 603 | /// zip_fold_and does short circuit if possible. 604 | template 605 | constexpr 606 | bool 607 | zip_fold_and( bitset2 const & bs1, bitset2 const & bs2, 608 | F f ) noexcept(noexcept( f( T(0), T(0) ) )) 609 | { 610 | return 611 | detail::array_funcs::n_array,T>().zip_fold_and(bs1.data(), 612 | bs2.data(), f); 613 | } 614 | 615 | 616 | /// \brief Returns true if f returns true for at least one pair 617 | /// of base_t=T values in bs1 and bs2. f should be a binary function 618 | /// taking two base_t values and returning bool. 619 | /// zip_fold_or does short circuit if possible. 620 | template 621 | constexpr 622 | bool 623 | zip_fold_or( bitset2 const & bs1, bitset2 const & bs2, 624 | F f ) noexcept(noexcept( f( T(0), T(0) ) )) 625 | { 626 | return 627 | detail::array_funcs::n_array,T>().zip_fold_or( bs1.data(), 628 | bs2.data(), f ); 629 | } 630 | 631 | 632 | 633 | } // namespace Bitset2 634 | 635 | 636 | namespace std 637 | { 638 | template 639 | struct hash > 640 | { 641 | private: 642 | enum : size_t 643 | { n_array= Bitset2::detail::bitset2_impl::n_array }; 644 | 645 | Bitset2::detail::hash_impl m_func; 646 | 647 | public: 648 | using argument_type= Bitset2::bitset2; 649 | using result_type= 650 | typename Bitset2::detail::hash_impl::result_type; 651 | 652 | result_type operator()( argument_type const& bs ) const 653 | { return m_func( bs.data() ); } 654 | }; // struct hash 655 | 656 | } // namespace std 657 | 658 | 659 | #endif // BITSET2_CB_HPP 660 | -------------------------------------------------------------------------------- /detail/array2array.hpp: -------------------------------------------------------------------------------- 1 | // BITSET2 2 | // 3 | // Copyright Claas Bontus 4 | // 5 | // Use, modification and distribution is subject to the 6 | // Boost Software License, Version 1.0. (See accompanying 7 | // file LICENSE.txt or copy at 8 | // http://www.boost.org/LICENSE_1_0.txt) 9 | // 10 | // Project home: https://github.com/ClaasBontus/bitset2 11 | // 12 | 13 | #ifndef BITSET2_ARRAY2ARRAY_CB_HPP 14 | #define BITSET2_ARRAY2ARRAY_CB_HPP 15 | 16 | 17 | #include "h_types.hpp" 18 | 19 | 20 | namespace Bitset2 21 | { 22 | namespace detail 23 | { 24 | 25 | 26 | /// \brief Convert std::array to std::array 27 | template 28 | struct array2array 29 | { 30 | using h_t_trgt= h_types; 31 | using h_t_src= h_types; 32 | using trgt_array_t= typename h_t_trgt::template array_t; 33 | using src_array_t= typename h_t_src:: template array_t; 34 | 35 | enum : size_t 36 | { trgt_base_n_bits= h_t_trgt::base_t_n_bits 37 | , src_base_n_bits= h_t_src:: base_t_n_bits 38 | }; 39 | 40 | enum : bool 41 | { small_to_large= ( src_base_n_bits < trgt_base_n_bits ) }; 42 | 43 | enum : size_t 44 | { ts_div= small_to_large ? trgt_base_n_bits / src_base_n_bits 45 | : src_base_n_bits / trgt_base_n_bits }; 46 | 47 | enum : Tsrc 48 | { h_all_set= Tsrc( Ttrgt(~Ttrgt(0)) ) }; 49 | 50 | /// Applies pttrn to most significant entry in result 51 | constexpr 52 | trgt_array_t 53 | operator()( Ttrgt pttrn, src_array_t const &src ) const noexcept 54 | { 55 | static_assert( ( small_to_large && trgt_base_n_bits % src_base_n_bits == 0) 56 | || (!small_to_large && src_base_n_bits % trgt_base_n_bits == 0), 57 | "Conversion between arrays of these types not supported" ); 58 | return small_to_large 59 | ? conv_small_to_large( pttrn, src, std::make_index_sequence() ) 60 | : conv_large_to_small( pttrn, src, std::make_index_sequence() ); 61 | } 62 | 63 | 64 | template 65 | constexpr 66 | trgt_array_t 67 | conv_small_to_large( Ttrgt pttrn, 68 | src_array_t const &src, 69 | std::index_sequence ) const noexcept 70 | { 71 | return {{ get_from_smaller( S1, src, S1 * ts_div )..., 72 | Ttrgt( get_from_smaller( trgt_n-1, src, (trgt_n-1) * ts_div ) 73 | & pttrn ) }}; 74 | } 75 | 76 | template 77 | constexpr 78 | trgt_array_t 79 | conv_large_to_small( Ttrgt pttrn, 80 | src_array_t const &src, 81 | std::index_sequence ) const noexcept 82 | { 83 | return 84 | {{ get_from_larger( S1 / ts_div, S1 % ts_div, src )..., 85 | Ttrgt( get_from_larger((trgt_n-1) / ts_div, (trgt_n-1) % ts_div, src) 86 | & pttrn ) }}; 87 | } 88 | 89 | constexpr 90 | Ttrgt 91 | get_from_smaller( size_t trgt_idx, 92 | src_array_t const &src, 93 | size_t src_idx, 94 | size_t src_ct= 0, 95 | Ttrgt so_far= Ttrgt(0) ) const noexcept 96 | { 97 | return ( src_ct >= ts_div || src_idx >= src_n ) 98 | ? so_far 99 | : get_from_smaller( trgt_idx, src, src_idx + 1, src_ct + 1, 100 | so_far | Ttrgt( Ttrgt(src[src_idx]) 101 | << (src_base_n_bits * src_ct) ) ); 102 | } 103 | 104 | constexpr 105 | Ttrgt 106 | get_from_larger( size_t div_val, 107 | size_t mod_val, 108 | src_array_t const &src ) const noexcept 109 | { 110 | return ( div_val >= src_n ) ? Ttrgt(0) 111 | : Ttrgt(Tsrc( src[div_val] >> (mod_val*trgt_base_n_bits) ) & h_all_set ); 112 | } 113 | }; // struct array2array 114 | 115 | 116 | 117 | } // namespace detail 118 | } // namespace Bitset2 119 | 120 | 121 | 122 | #endif // BITSET2_ARRAY2ARRAY_CB_HPP 123 | -------------------------------------------------------------------------------- /detail/array2u_long_t.hpp: -------------------------------------------------------------------------------- 1 | // BITSET2 2 | // 3 | // Copyright Claas Bontus 4 | // 5 | // Use, modification and distribution is subject to the 6 | // Boost Software License, Version 1.0. (See accompanying 7 | // file LICENSE.txt or copy at 8 | // http://www.boost.org/LICENSE_1_0.txt) 9 | // 10 | // Project home: https://github.com/ClaasBontus/bitset2 11 | // 12 | 13 | 14 | #ifndef BITSET2_ARRAY2U_LONG_T_CB_HPP 15 | #define BITSET2_ARRAY2U_LONG_T_CB_HPP 16 | 17 | #include "bit_chars.hpp" 18 | 19 | 20 | namespace Bitset2 21 | { 22 | namespace detail 23 | { 24 | 25 | /// \brief Takes a std::array 'arr' and returns a variable 'x' of type Tlong. 26 | /// Bits in 'x' are set if corresponding bits in 'arr' are set. 27 | template 28 | struct array2u_long_t 29 | { 30 | using base_t= T; 31 | using b_c= bit_chars; 32 | 33 | enum : size_t 34 | { n_bits= N 35 | , base_t_n_bits= b_c::base_t_n_bits 36 | , long_t_n_bits= sizeof( Tlong ) * CHAR_BIT 37 | , n_array= b_c::n_array 38 | , div_val= long_t_n_bits / base_t_n_bits 39 | , mod_val= long_t_n_bits % base_t_n_bits 40 | , use_vals= ce_min( div_val + (mod_val!=0), n_array ) 41 | , bit_diff= mod_val == 0 ? 0 : ( base_t_n_bits - mod_val ) 42 | }; 43 | 44 | enum : base_t 45 | { allset= base_t( ~base_t(0) ) 46 | , h_pttrn= use_vals < n_array ? allset : ce_right_shift( allset, bit_diff ) 47 | , i_pttrn= base_t( ~h_pttrn ) 48 | }; 49 | 50 | using array_t= typename h_types::template array_t; 51 | 52 | constexpr 53 | Tlong 54 | operator()( array_t const & arr ) const noexcept 55 | { 56 | return 57 | base_t_n_bits >= long_t_n_bits ? Tlong( arr[0] ) 58 | : combine( Tlong(0), arr, 0 ); 59 | } 60 | 61 | /// \brief Returns true if arr cannot be converted to Tlong. 62 | constexpr 63 | bool 64 | check_overflow( array_t const & arr ) const noexcept 65 | { return N <= long_t_n_bits ? false : check_impl( arr, use_vals - 1 ); } 66 | 67 | 68 | 69 | constexpr 70 | Tlong 71 | combine( Tlong v, array_t const & arr, size_t idx ) const noexcept 72 | { 73 | return ( idx >= use_vals ) ? v 74 | : idx + 1 == use_vals 75 | ? Tlong( v + take_v( arr, idx, h_pttrn ) ) 76 | : combine( Tlong( v + take_v( arr, idx ) ), arr, idx + 1 ); 77 | } 78 | 79 | constexpr 80 | Tlong 81 | take_v( array_t const & arr, size_t idx, base_t pttrn= allset ) const noexcept 82 | { return ce_left_shift( Tlong( arr[idx] & pttrn ), idx * base_t_n_bits ); } 83 | 84 | constexpr 85 | bool 86 | check_impl( array_t const & arr, size_t idx ) const noexcept 87 | { 88 | return idx >= n_array ? false 89 | : ( ( take_check( arr, idx ) != base_t(0) ) 90 | || check_impl( arr, idx + 1 ) ); 91 | } 92 | 93 | constexpr 94 | base_t 95 | take_check( array_t const & arr, size_t idx ) const noexcept 96 | { return arr[idx] & ( idx + 1 == use_vals ? i_pttrn : allset ); } 97 | 98 | }; // struct array2u_long_t 99 | 100 | 101 | } // namespace detail 102 | } // namespace Bitset2 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | #endif // BITSET2_ARRAY2U_LONG_T_CB_HPP 111 | -------------------------------------------------------------------------------- /detail/array_access.hpp: -------------------------------------------------------------------------------- 1 | // BITSET2 2 | // 3 | // Copyright Claas Bontus 4 | // 5 | // Use, modification and distribution is subject to the 6 | // Boost Software License, Version 1.0. (See accompanying 7 | // file LICENSE.txt or copy at 8 | // http://www.boost.org/LICENSE_1_0.txt) 9 | // 10 | // Project home: https://github.com/ClaasBontus/bitset2 11 | // 12 | 13 | #ifndef BITSET2_ARRAY_ACCESS_CB_HPP 14 | #define BITSET2_ARRAY_ACCESS_CB_HPP 15 | 16 | #include "bit_chars.hpp" 17 | 18 | 19 | namespace Bitset2 20 | { 21 | namespace detail 22 | { 23 | 24 | /// \brief array_access is used for getting bunches of 4 bits, which is 25 | /// needed when creating hex-strings 26 | template 27 | struct array_access 28 | { 29 | using base_t= T; 30 | using b_chars= bit_chars; 31 | enum : size_t { base_t_n_bits= b_chars::base_t_n_bits 32 | , n_array= b_chars::n_array 33 | }; 34 | enum : size_t { div_four= N / 4 35 | , mod_four= N % 4 36 | }; 37 | using array_t= typename h_types::template array_t; 38 | 39 | constexpr 40 | base_t 41 | get_four_bits( array_t const &arr, size_t offset ) const noexcept 42 | { 43 | return 44 | get_four_bits_impl( arr, 45 | offset / base_t_n_bits, offset % base_t_n_bits ); 46 | } 47 | 48 | constexpr 49 | base_t 50 | get_four_bits_impl( array_t const &arr, 51 | size_t idx, size_t bit_idx ) const noexcept 52 | { 53 | return ( bit_idx >= 3 ) 54 | ? h1_get_four_bits( arr[idx], bit_idx ) 55 | : h2_get_four_bits( arr, idx, bit_idx ); 56 | } 57 | 58 | constexpr 59 | base_t 60 | h1_get_four_bits( base_t v, size_t bit_idx ) const noexcept 61 | { return ( v >> ( bit_idx - 3 ) ) & base_t(0xF); } 62 | 63 | constexpr 64 | base_t 65 | h2_get_four_bits( array_t const &arr, 66 | size_t idx, size_t bit_idx ) const noexcept 67 | { 68 | return 69 | (( arr[idx] & ( ( base_t(1) << (bit_idx+1) ) - 1 ) ) << ( 3 - bit_idx )) 70 | + ( ( idx == 0 ) ? base_t(0) 71 | : ( arr[idx-1] >> (base_t_n_bits - (3 - bit_idx)) ) ); 72 | } 73 | }; // struct array_access 74 | 75 | 76 | } // namespace detail 77 | } // namespace Bitset2 78 | 79 | 80 | 81 | 82 | #endif // BITSET2_ARRAY_ACCESS_CB_HPP 83 | -------------------------------------------------------------------------------- /detail/array_add.hpp: -------------------------------------------------------------------------------- 1 | // BITSET2 2 | // 3 | // Copyright Claas Bontus 4 | // 5 | // Use, modification and distribution is subject to the 6 | // Boost Software License, Version 1.0. (See accompanying 7 | // file LICENSE.txt or copy at 8 | // http://www.boost.org/LICENSE_1_0.txt) 9 | // 10 | // Project home: https://github.com/ClaasBontus/bitset2 11 | // 12 | 13 | #ifndef BITSET2_ARRAY_ADD_CB_HPP 14 | #define BITSET2_ARRAY_ADD_CB_HPP 15 | 16 | 17 | #include "bit_chars.hpp" 18 | #include "array_funcs.hpp" 19 | #include "array_ops.hpp" 20 | 21 | 22 | namespace Bitset2 23 | { 24 | namespace detail 25 | { 26 | 27 | /// Allows to add two std::array's in a constexpr 28 | template 29 | struct array_add 30 | { 31 | using base_t= T; 32 | using b_chars= bit_chars; 33 | enum : base_t 34 | { hgh_bit_pattern= b_chars::hgh_bit_pattern 35 | , all_one= b_chars::all_one 36 | }; 37 | enum : size_t { n_array= b_chars::n_array }; 38 | using array_t= typename h_types::template array_t; 39 | 40 | constexpr 41 | array_t 42 | add( array_t arr1, array_t const &arr2 ) const noexcept 43 | { 44 | add_assgn( arr1, arr2 ); 45 | return arr1; 46 | } 47 | 48 | constexpr 49 | void 50 | add_assgn( array_t &arr1, array_t const &arr2, 51 | base_t carry= base_t(0) ) const noexcept 52 | { 53 | for( size_t c= 0; c < n_array; ++c ) 54 | { 55 | auto const sm1= base_t( arr2[c] + carry ); 56 | auto const sm= base_t( arr1[c] + sm1 ); 57 | carry= sm < arr1[c] || sm1 < arr2[c]; 58 | arr1[c]= sm; 59 | } 60 | arr1[n_array-1] &= hgh_bit_pattern; 61 | } // add_assgn 62 | 63 | constexpr 64 | array_t 65 | midpoint( array_t const &arr1, array_t const &arr2, 66 | bool round_down ) const noexcept 67 | { 68 | // https://devblogs.microsoft.com/oldnewthing/20220207-00/?p=106223 69 | T val0_1 = arr1[0]; 70 | T val0_2 = arr2[0]; 71 | T carry = val0_1 & val0_2 & 1; 72 | if( !round_down && carry == 0 ) carry = val0_1 & 1; 73 | array_t ret_val = array_ops(1).shift_right( arr1 ); 74 | array_t bs2_h = array_ops(1).shift_right( arr2 ); 75 | add_assgn( ret_val, bs2_h, carry ); 76 | return ret_val; 77 | } // midpoint 78 | }; // struct array_add 79 | 80 | } // namespace detail 81 | } // namespace Bitset2 82 | 83 | 84 | 85 | 86 | #endif // BITSET2_ARRAY_ADD_CB_HPP 87 | -------------------------------------------------------------------------------- /detail/array_complement2.hpp: -------------------------------------------------------------------------------- 1 | // BITSET2 2 | // 3 | // Copyright Claas Bontus 4 | // 5 | // Use, modification and distribution is subject to the 6 | // Boost Software License, Version 1.0. (See accompanying 7 | // file LICENSE.txt or copy at 8 | // http://www.boost.org/LICENSE_1_0.txt) 9 | // 10 | // Project home: https://github.com/ClaasBontus/bitset2 11 | // 12 | 13 | #ifndef BITSET2_ARRAY_COMPLEMENT2_CB_HPP 14 | #define BITSET2_ARRAY_COMPLEMENT2_CB_HPP 15 | 16 | 17 | #include "bit_chars.hpp" 18 | #include "array_funcs.hpp" 19 | 20 | 21 | namespace Bitset2 22 | { 23 | namespace detail 24 | { 25 | 26 | /// Computes the two's complement of the number encoded in the array 27 | template 28 | struct array_complement2 29 | { 30 | using base_t= T; 31 | using b_chars= bit_chars; 32 | enum : base_t { hgh_bit_pattern= b_chars::hgh_bit_pattern }; 33 | enum : size_t { n_array= b_chars::n_array }; 34 | using array_t= typename h_types::template array_t; 35 | 36 | 37 | constexpr 38 | array_t 39 | comp2( array_t arr ) const noexcept 40 | { 41 | comp2_assgn( arr ); 42 | return arr; 43 | } 44 | 45 | constexpr 46 | void 47 | comp2_assgn( array_t &arr ) const noexcept 48 | { 49 | base_t carry= base_t(1); 50 | for( size_t c= 0; c < n_array; ++c ) 51 | { 52 | auto const sm= base_t( base_t(~arr[c]) + carry ); 53 | carry= base_t( (carry == base_t(1)) && ( sm == 0 ) ); 54 | arr[c]= sm; 55 | } // for c 56 | arr[n_array-1] &= hgh_bit_pattern; 57 | } // comp2_assgn 58 | 59 | }; // struct array_complement2 60 | 61 | 62 | } // namespace detail 63 | } // namespace Bitset2 64 | 65 | 66 | 67 | #endif // BITSET2_ARRAY_COMPLEMENT2_CB_HPP 68 | -------------------------------------------------------------------------------- /detail/array_funcs.hpp: -------------------------------------------------------------------------------- 1 | // BITSET2 2 | // 3 | // Copyright Claas Bontus 4 | // 5 | // Use, modification and distribution is subject to the 6 | // Boost Software License, Version 1.0. (See accompanying 7 | // file LICENSE.txt or copy at 8 | // http://www.boost.org/LICENSE_1_0.txt) 9 | // 10 | // Project home: https://github.com/ClaasBontus/bitset2 11 | // 12 | 13 | #ifndef BITSET2_ARRAY_FUNCS_CB_HPP 14 | #define BITSET2_ARRAY_FUNCS_CB_HPP 15 | 16 | 17 | #include "h_types.hpp" 18 | #include "count_bits.hpp" 19 | #include "index_lsb_set.hpp" 20 | #include "index_msb_set.hpp" 21 | #include 22 | 23 | #if __cplusplus >= 202002L 24 | # include 25 | # ifdef __cpp_lib_int_pow2 26 | # define CMPLRPOW2 27 | # endif 28 | #endif 29 | 30 | namespace Bitset2 31 | { 32 | namespace detail 33 | { 34 | #ifdef CMPLRPOW2 35 | template 36 | constexpr 37 | bool loc_test_single_bit( T val ) 38 | { return std::has_single_bit( val ); } 39 | 40 | # ifdef __SIZEOF_INT128__ 41 | template<> 42 | constexpr 43 | bool loc_test_single_bit( unsigned __int128 val ) 44 | { return (val & (val - 1)) == 0; } 45 | # endif 46 | #else 47 | template 48 | constexpr 49 | bool loc_test_single_bit( T val ) 50 | { return (val & T(val - T(1))) == T(0); } 51 | #endif 52 | 53 | template 54 | struct array_funcs 55 | { 56 | using base_t= T; 57 | using array_t= typename h_types::template array_t; 58 | using array_p1_t= typename h_types::template array_t; 59 | 60 | enum : size_t { base_t_n_bits= h_types::base_t_n_bits 61 | , npos= h_types::npos }; 62 | 63 | /// Binary operator type 64 | enum class op_type { or_op, and_op, xor_op, sdiff_op }; 65 | 66 | constexpr 67 | array_t 68 | bitwise_or( array_t const &arr1, array_t const &arr2 ) const noexcept 69 | { 70 | return bitwise_op_impl( op_type::or_op, arr1, arr2, 71 | std::make_index_sequence() ); 72 | } 73 | 74 | /// Used for |= operator. Separate implementation for better performance. 75 | constexpr 76 | void 77 | bitwise_or_assgn( array_t &arr1, array_t const &arr2 ) const noexcept 78 | { return bitwise_op_assgn_impl( op_type::or_op, arr1, arr2 ); } 79 | 80 | constexpr 81 | array_t 82 | bitwise_and( array_t const &arr1, array_t const &arr2 ) const noexcept 83 | { 84 | return bitwise_op_impl( op_type::and_op, arr1, arr2, 85 | std::make_index_sequence() ); 86 | } 87 | 88 | /// Used for &= operator. Separate implementation for better performance. 89 | constexpr 90 | void 91 | bitwise_and_assgn( array_t &arr1, array_t const &arr2 ) const noexcept 92 | { return bitwise_op_assgn_impl( op_type::and_op, arr1, arr2 ); } 93 | 94 | constexpr 95 | array_t 96 | bitwise_xor( array_t const &arr1, array_t const &arr2 ) const noexcept 97 | { 98 | return bitwise_op_impl( op_type::xor_op, arr1, arr2, 99 | std::make_index_sequence() ); 100 | } 101 | 102 | /// Used for ^= operator. Separate implementation for better performance. 103 | constexpr 104 | void 105 | bitwise_xor_assgn( array_t &arr1, array_t const &arr2 ) const noexcept 106 | { return bitwise_op_assgn_impl( op_type::xor_op, arr1, arr2 ); } 107 | 108 | /// Computes the set difference, i.e. arr1 & ~arr2 109 | constexpr 110 | array_t 111 | bitwise_setdiff( array_t const &arr1, array_t const &arr2 ) const noexcept 112 | { 113 | return bitwise_op_impl( op_type::sdiff_op, arr1, arr2, 114 | std::make_index_sequence() ); 115 | } 116 | 117 | /// \brief Computes the set difference, i.e. arr1 & ~arr2. 118 | /// Separate implementation for better performance. 119 | constexpr 120 | void 121 | bitwise_setdiff_assgn( array_t &arr1, array_t const &arr2 ) const noexcept 122 | { return bitwise_op_assgn_impl( op_type::sdiff_op, arr1, arr2 ); } 123 | 124 | 125 | constexpr 126 | bool 127 | none( array_t const &arr ) const noexcept 128 | { return none_impl( n_array - 1, arr ); } 129 | 130 | 131 | constexpr 132 | size_t 133 | count( array_t const &arr ) const noexcept 134 | { 135 | size_t ct = 0; 136 | for( size_t i= 0; i < n_array; ++i ) ct += count_bits(arr[i]); 137 | return ct; 138 | } 139 | 140 | 141 | constexpr 142 | bool 143 | has_single_bit( array_t const &arr ) const noexcept 144 | { 145 | size_t ct = 0; 146 | for( size_t i= 0; i < n_array; ++i ) 147 | { 148 | base_t x = arr[i]; 149 | if( x == T(0) ) continue; 150 | if( loc_test_single_bit(x) ) ++ct; 151 | else return false; 152 | if( ct > 1 ) return false; 153 | } 154 | return ct == 1; 155 | } // has_single_bit 156 | 157 | 158 | constexpr 159 | bool 160 | equal( array_t const &arr1, array_t const &arr2 ) const noexcept 161 | { return equal_impl( arr1, arr2, 0 ); } 162 | 163 | 164 | constexpr 165 | bool 166 | less_than( array_t const &arr1, array_t const &arr2 ) const noexcept 167 | { return less_than_impl( arr1, arr2, n_array - 1 ); } 168 | 169 | 170 | /// \brief Returns true if f returns true for each pair 171 | /// of elements in arr1 and arr2 172 | template 173 | constexpr 174 | bool 175 | zip_fold_and( array_t const &arr1, array_t const &arr2, 176 | F &f ) const noexcept(noexcept( f( base_t(0), base_t(0) ) )) 177 | { return zip_fold_and_impl( arr1, arr2, f, 0 ); } 178 | 179 | 180 | /// \brief Returns true if f returns true for at least one pair 181 | /// of elements in arr1 and arr2 182 | template 183 | constexpr 184 | bool 185 | zip_fold_or( array_t const &arr1, array_t const &arr2, 186 | F &f ) const noexcept(noexcept( f( base_t(0), base_t(0) ) )) 187 | { return zip_fold_or_impl( arr1, arr2, f, 0 ); } 188 | 189 | 190 | /// Prepend v1 in front of arr 191 | constexpr 192 | array_p1_t 193 | prepend( base_t const v1, array_t const &arr ) const noexcept 194 | { return prepend_impl( v1, arr, std::make_index_sequence()); } 195 | 196 | 197 | /// Append v1 to arr 198 | constexpr 199 | array_p1_t 200 | append( array_t const &arr, base_t const v1 ) const noexcept 201 | { return append_impl( arr, v1, std::make_index_sequence()); } 202 | 203 | 204 | /// Copy each element in arr but apply pttrn to most significant entry 205 | template 206 | constexpr 207 | array_t 208 | copy_and_map( base_t const pttrn, 209 | typename 210 | h_types::template array_t const &arr ) const noexcept 211 | { 212 | return 213 | n_array == 0 ? array_t{} 214 | : copy_and_map_impl( 215 | pttrn, 216 | arr, 217 | gen_empty_array(), 218 | n >= n_array, 219 | std::make_index_sequence(), 220 | std::make_index_sequence() ); 221 | } // copy_and_map 222 | 223 | 224 | //** _impl functions 225 | 226 | template 227 | constexpr 228 | array_t 229 | copy_and_map_impl( base_t const pttrn, 230 | typename 231 | h_types::template array_t const &arr, 232 | array_t const &zeroes, 233 | bool const take_all, 234 | std::index_sequence, 235 | std::index_sequence ) const noexcept 236 | { 237 | return {{ arr[S1]..., zeroes[S2]..., 238 | base_t(( take_all ? arr[n_array-1] : base_t(0) ) & pttrn) }}; 239 | } 240 | 241 | 242 | 243 | constexpr 244 | bool 245 | none_impl( size_t idx, array_t const &arr ) const noexcept 246 | { 247 | return ( arr[idx] == base_t(0) ) 248 | && ( ( idx == 0 ) ? true : none_impl( idx - 1, arr ) ); 249 | } 250 | 251 | 252 | template 253 | constexpr 254 | array_p1_t 255 | append_impl( array_t const &arr, base_t const v1, 256 | std::index_sequence ) const noexcept 257 | { return {{ arr[S]..., v1 }}; } 258 | 259 | 260 | template 261 | constexpr 262 | array_p1_t 263 | prepend_impl( base_t const v1, array_t const &arr, 264 | std::index_sequence ) const noexcept 265 | { return {{ v1, arr[S]... }}; } 266 | 267 | 268 | constexpr 269 | bool 270 | equal_impl( array_t const &arr1, array_t const &arr2, 271 | size_t ct ) const noexcept 272 | { 273 | return ( ct == n_array ) ? true 274 | : ( arr1[ct] == arr2[ct] ) && equal_impl( arr1, arr2, ct + 1 ); 275 | } 276 | 277 | 278 | constexpr 279 | bool 280 | less_than_impl( array_t const &arr1, array_t const &arr2, 281 | size_t ct ) const noexcept 282 | { 283 | return 284 | ( arr1[ct] < arr2[ct] ) 285 | || ( arr1[ct] == arr2[ct] 286 | && ( ct == 0 ? false : less_than_impl( arr1, arr2, ct-1 ) ) ); 287 | } 288 | 289 | 290 | template 291 | constexpr 292 | bool 293 | zip_fold_and_impl( array_t const &arr1, array_t const &arr2, 294 | F &f, 295 | size_t ct ) 296 | const noexcept(noexcept( f(base_t(0), base_t(0)))) 297 | { 298 | return ( ct == n_array ) ? true 299 | : ( f( arr1[ct], arr2[ct] ) 300 | && zip_fold_and_impl( arr1, arr2, f, ct + 1 ) ); 301 | } 302 | 303 | 304 | template 305 | constexpr 306 | bool 307 | zip_fold_or_impl( array_t const &arr1, array_t const &arr2, 308 | F &f, 309 | size_t ct ) 310 | const noexcept(noexcept( f(base_t(0), base_t(0)))) 311 | { 312 | return ( ct == n_array ) ? false 313 | : ( f( arr1[ct], arr2[ct] ) 314 | || zip_fold_or_impl( arr1, arr2, f, ct + 1 ) ); 315 | } 316 | 317 | 318 | constexpr 319 | void 320 | bitwise_op_assgn_impl( op_type opt, 321 | array_t &arr1, array_t const &arr2 ) const noexcept 322 | { 323 | for( size_t c= 0; c < n_array; ++c ) 324 | { 325 | if( opt == op_type::or_op ) arr1[c] |= arr2[c]; 326 | else if( opt == op_type::and_op ) arr1[c] &= arr2[c]; 327 | else if( opt == op_type::xor_op ) arr1[c] ^= arr2[c]; 328 | else arr1[c] &= ~arr2[c]; 329 | } 330 | } // bitwise_op_assgn_impl 331 | 332 | 333 | template 334 | constexpr 335 | array_t 336 | bitwise_op_impl( op_type opt, 337 | array_t const &arr1, array_t const &arr2, 338 | std::index_sequence ) const noexcept 339 | { return {{ h_bitwise_op( S, opt, arr1, arr2 )... }}; } 340 | 341 | constexpr 342 | base_t 343 | h_bitwise_op( size_t idx, op_type opt, 344 | array_t const &arr1, array_t const &arr2 ) const noexcept 345 | { 346 | switch( opt ) 347 | { 348 | case op_type::or_op: return arr1[idx] | arr2[idx]; 349 | case op_type::and_op: return arr1[idx] & arr2[idx]; 350 | case op_type::xor_op: return arr1[idx] ^ arr2[idx]; 351 | default: return arr1[idx] & base_t(~arr2[idx]); // set difference 352 | } // switch 353 | } // h_bitwise_op 354 | 355 | 356 | constexpr 357 | size_t 358 | idx_lsb_set( array_t const &arr, base_t v, size_t idx, base_t hgh_bit_pttrn ) const noexcept 359 | { 360 | bool const complement = hgh_bit_pttrn != base_t(2); 361 | if( complement && idx + 1 == n_array ) v &= hgh_bit_pttrn; 362 | while( idx < n_array ) 363 | { 364 | if( v != 0 ) return idx * base_t_n_bits + index_lsb_set()( v ); 365 | if(++idx < n_array) 366 | { 367 | v = arr[idx]; 368 | if( complement ) { 369 | v = ~v; 370 | if( idx + 1 == n_array ) v &= hgh_bit_pttrn; 371 | } 372 | } 373 | } 374 | return npos; 375 | } // idx_lsb_set 376 | 377 | 378 | constexpr 379 | size_t 380 | idx_msb_set( array_t const &arr, base_t hgh_bit_pttrn ) const noexcept 381 | { 382 | bool const complement = hgh_bit_pttrn != base_t(2); 383 | index_msb_set msb_hlpr; 384 | for( size_t i = n_array; i-- > 0; ) 385 | { 386 | base_t val = complement ? ~(arr[i]) : arr[i]; 387 | if( complement && i + 1 == n_array ) val &= hgh_bit_pttrn; 388 | size_t idx = msb_hlpr( val ); 389 | if( idx != npos ) return i * base_t_n_bits + idx; 390 | } 391 | return npos; 392 | } // idx_msb_set 393 | 394 | }; // struct array_funcs 395 | 396 | } // namespace detail 397 | 398 | } // namespace Bitset2 399 | 400 | 401 | 402 | #undef CMPLRPOW2 403 | 404 | #endif // BITSET2_ARRAY_FUNCS_CB_HPP 405 | -------------------------------------------------------------------------------- /detail/array_ops.hpp: -------------------------------------------------------------------------------- 1 | // BITSET2 2 | // 3 | // Copyright Claas Bontus 4 | // 5 | // Use, modification and distribution is subject to the 6 | // Boost Software License, Version 1.0. (See accompanying 7 | // file LICENSE.txt or copy at 8 | // http://www.boost.org/LICENSE_1_0.txt) 9 | // 10 | // Project home: https://github.com/ClaasBontus/bitset2 11 | // 12 | 13 | #ifndef BITSET2_ARRAY_OPS_CB_HPP 14 | #define BITSET2_ARRAY_OPS_CB_HPP 15 | 16 | #include "bit_chars.hpp" 17 | #include "reverse_bits.hpp" 18 | #include "array_funcs.hpp" 19 | 20 | 21 | namespace Bitset2 22 | { 23 | namespace detail 24 | { 25 | 26 | template 27 | struct array_ops 28 | { 29 | using base_t= T; 30 | using this_t= array_ops; 31 | using b_chars= bit_chars; 32 | enum : size_t { base_t_n_bits= b_chars::base_t_n_bits 33 | , n_words= b_chars::n_words 34 | , n_array= b_chars::n_array 35 | , mod_val= b_chars::mod_val 36 | , n_m_mod= mod_val == 0 ? 0 : base_t_n_bits-mod_val 37 | }; 38 | enum : base_t 39 | { hgh_bit_pattern= b_chars::hgh_bit_pattern 40 | , all_one= b_chars::all_one }; 41 | using array_t= typename h_types::template array_t; 42 | using zero_array_t= typename h_types::template array_t<0>; 43 | 44 | constexpr 45 | array_ops( size_t n_shift ) noexcept 46 | : m_n_shift( n_shift ) 47 | , m_n_shift_mod( n_shift % N ) 48 | , m_shft_div( n_shift / base_t_n_bits ) 49 | , m_shft_mod( n_shift % base_t_n_bits ) 50 | , m_rot_div( m_n_shift_mod / base_t_n_bits ) 51 | , m_rot_mod( m_n_shift_mod % base_t_n_bits ) 52 | , m_shft_leftright_shift( base_t_n_bits-m_shft_mod ) 53 | , m_shft_left_pattern( ce_left_shift( T(~T(0)), m_shft_leftright_shift )) 54 | , m_shft_right_pattern( ce_right_shift( T(~T(0)), m_shft_leftright_shift )) 55 | {} 56 | 57 | constexpr 58 | array_t 59 | shift_left( array_t arr ) const noexcept 60 | { 61 | shift_left_assgn( arr ); 62 | return arr; 63 | } 64 | 65 | constexpr 66 | array_t 67 | shift_right( array_t arr ) const noexcept 68 | { 69 | shift_right_assgn( arr ); 70 | return arr; 71 | } 72 | 73 | /// Used for <<= operator. 74 | constexpr 75 | void 76 | shift_left_assgn( array_t &arr ) const noexcept 77 | { 78 | if( m_n_shift == 0 ) return; 79 | 80 | for( size_t c= n_words; c > 0; ) 81 | { 82 | --c; 83 | if( c >= m_shft_div ) 84 | { 85 | auto const c2= c - m_shft_div; 86 | base_t const v1= arr[c2] << m_shft_mod; 87 | base_t const v2= 88 | c2 == 0 ? base_t(0) 89 | : ce_right_shift( base_t(arr[c2-1] & m_shft_left_pattern), 90 | m_shft_leftright_shift ); 91 | arr[c]= base_t( v1 | v2 ); 92 | } 93 | else arr[c]= base_t(0); 94 | } // for c 95 | arr[n_array-1] &= hgh_bit_pattern; 96 | } // shift_left_assgn 97 | 98 | /// Used for >>= operator. 99 | constexpr 100 | void 101 | shift_right_assgn( array_t &arr ) const noexcept 102 | { 103 | if( m_n_shift == 0 ) return; 104 | 105 | for( size_t c= 0; c < n_words; ++c ) 106 | { 107 | auto const c2= c + m_shft_div; 108 | if( c2 < n_words ) 109 | { 110 | base_t const v1= arr[c2] >> m_shft_mod; 111 | base_t const v2= 112 | ( c2 + 1 >= n_words ) ? base_t(0) 113 | : ce_left_shift( base_t( arr[c2+1] & m_shft_right_pattern ), 114 | m_shft_leftright_shift ); 115 | arr[c]= v1 | v2; 116 | } 117 | else arr[c]= base_t(0); 118 | } // for c 119 | arr[n_array-1] &= hgh_bit_pattern; 120 | } // shift_right_assgn 121 | 122 | 123 | constexpr 124 | array_t 125 | rotate_left( array_t const &arr ) const noexcept 126 | { 127 | if( m_n_shift_mod == 0 ) return arr; 128 | 129 | return 130 | ( n_array == 1 ) 131 | ? array_t{{ base_t(( base_t( arr[0] << m_n_shift_mod ) 132 | | ( ce_right_shift( arr[0], N - m_n_shift_mod ) ) 133 | ) & hgh_bit_pattern ) }} 134 | : rotate_left_impl( arr ); 135 | } // rotate_left 136 | 137 | constexpr 138 | array_t 139 | flip( array_t const &arr ) const noexcept 140 | { return flip_impl( arr, std::make_index_sequence() ); } 141 | 142 | constexpr 143 | bool 144 | all( array_t const &arr ) const noexcept 145 | { return ( N > 0 ) && all_impl( n_words - 1, arr ); } 146 | 147 | 148 | /// Used for ++ operator. 149 | constexpr 150 | void 151 | increment( array_t &arr ) const noexcept 152 | { 153 | if( N == 0 ) return; 154 | 155 | size_t c= 0; 156 | for( ; c + 1 < n_words; ++c ) 157 | { 158 | if( ( ++arr[c] ) != base_t(0) ) return; 159 | } 160 | ++arr[c]; 161 | arr[c] &= hgh_bit_pattern; 162 | } // increment 163 | 164 | 165 | /// Used for -- operator. 166 | constexpr 167 | void 168 | decrement( array_t &arr ) const noexcept 169 | { 170 | if( N == 0 ) return; 171 | 172 | size_t c= 0; 173 | for( ; c + 1 < n_words; ++c ) 174 | { 175 | if( ( arr[c]-- ) != base_t(0) ) return; 176 | } 177 | --arr[c]; 178 | arr[c] &= hgh_bit_pattern; 179 | } // decrement 180 | 181 | /// Reverse bits 182 | constexpr 183 | array_t 184 | reverse( array_t const &arr ) const noexcept 185 | { 186 | return n_array == 1 187 | ? array_t{{ base_t( reverse_bits()(arr[0]) >> n_m_mod ) }} 188 | : reverse_impl( arr, std::make_index_sequence() ); 189 | } // reverse 190 | 191 | 192 | //**************************************************** 193 | 194 | 195 | constexpr 196 | bool 197 | all_impl( size_t idx, array_t const &arr ) const noexcept 198 | { 199 | return h_all( idx, arr ) 200 | && ( ( idx == 0 ) ? true : all_impl( idx - 1, arr ) ); 201 | } 202 | 203 | constexpr 204 | bool 205 | h_all( size_t idx, array_t const &arr ) const noexcept 206 | { 207 | return ( idx + 1 == n_words ) ? ( arr[idx] == hgh_bit_pattern ) 208 | : ( arr[idx] == all_one ); 209 | } 210 | 211 | 212 | constexpr 213 | array_t 214 | rotate_left_impl( array_t const & arr ) const noexcept 215 | { 216 | size_t const rot_r_div = (N - m_n_shift_mod) / base_t_n_bits; 217 | size_t const rot_r_mod = (N - m_n_shift_mod) % base_t_n_bits; 218 | size_t const bits_last = (mod_val == 0) ? base_t_n_bits : mod_val; 219 | array_t arr_r{}; 220 | size_t c = 0; 221 | 222 | size_t const h1 = (bits_last < rot_r_mod) ? 2 : 1; 223 | for( ; c + h1 + rot_r_div < n_words; ++c ) 224 | { 225 | size_t i1 = c + rot_r_div; 226 | size_t i2 = i1 + 1; 227 | base_t v1 = ce_right_shift( arr[i1], rot_r_mod ); 228 | base_t v2 = ce_left_shift( arr[i2], base_t_n_bits - rot_r_mod ); 229 | arr_r[c] = base_t( v1 | v2 ); 230 | } // for c 231 | 232 | if( c < n_words && bits_last < rot_r_mod ) 233 | { 234 | base_t v1 = ce_right_shift( arr[n_words-2], rot_r_mod ); 235 | base_t v2 = ce_left_shift( arr[n_words-1], base_t_n_bits - rot_r_mod ); 236 | base_t v3 = ce_left_shift( arr[0], base_t_n_bits - rot_r_mod + bits_last ); 237 | arr_r[c++] = base_t( v1 | v2 | v3 ); 238 | } 239 | 240 | if( c < n_words && bits_last > rot_r_mod ) 241 | { 242 | base_t v1 = ce_right_shift( arr[n_words-1], rot_r_mod ); 243 | base_t v2 = ce_left_shift( arr[0], bits_last - rot_r_mod ); 244 | arr_r[c++] = base_t( v1 | v2 ); 245 | } 246 | 247 | for( ; c < n_words; ++c ) 248 | { 249 | size_t i1 = c - m_rot_div; 250 | size_t i2 = i1 - 1; 251 | base_t v1 = ce_left_shift( arr[i1], m_rot_mod ); 252 | base_t v2 = ce_right_shift( arr[i2], base_t_n_bits - m_rot_mod ); 253 | arr_r[c] = base_t( v1 | v2 ); 254 | } // for c 255 | 256 | arr_r[n_array-1] &= hgh_bit_pattern; 257 | return arr_r; 258 | } // rotate_left_impl 259 | 260 | 261 | template 262 | constexpr 263 | array_t 264 | flip_impl( array_t const &arr, std::index_sequence ) const noexcept 265 | { return {{ h_flip( S, arr )... }}; } 266 | 267 | constexpr 268 | base_t 269 | h_flip( size_t idx, array_t const &arr ) const noexcept 270 | { 271 | return ( idx >= n_words ) ? base_t(0) 272 | : ( ~arr[idx] ) 273 | & ( (idx+1 == n_words) ? hgh_bit_pattern : all_one ); 274 | } 275 | 276 | 277 | template 278 | constexpr 279 | array_t 280 | reverse_impl( array_t const &arr, std::index_sequence ) const noexcept 281 | { return {{ h_reverse( S, arr )... }}; } 282 | 283 | constexpr 284 | base_t 285 | h_reverse( size_t idx, array_t const &arr ) const noexcept 286 | { 287 | return idx + 1 == n_words 288 | ? base_t( reverse_bits()( arr[0] ) >> n_m_mod ) 289 | : reverse_bits()( h2_reverse( idx, arr ) ); 290 | } 291 | 292 | constexpr 293 | base_t 294 | h2_reverse( size_t idx, array_t const &arr ) const noexcept 295 | { 296 | return mod_val == 0 ? arr[n_words-idx-1] 297 | : base_t( ( arr[n_words-idx-1] << n_m_mod ) 298 | | ( arr[n_words-idx-2] >> mod_val ) ); 299 | } 300 | 301 | 302 | size_t const m_n_shift; 303 | size_t const m_n_shift_mod; 304 | size_t const m_shft_div; 305 | size_t const m_shft_mod; 306 | size_t const m_rot_div; 307 | size_t const m_rot_mod; 308 | size_t const m_shft_leftright_shift; 309 | base_t const m_shft_left_pattern; 310 | base_t const m_shft_right_pattern; 311 | 312 | }; // struct array_ops 313 | 314 | } // namespace detail 315 | } // namespace Bitset2 316 | 317 | 318 | 319 | 320 | #endif // BITSET2_ARRAY_OPS_CB_HPP 321 | -------------------------------------------------------------------------------- /detail/bit_chars.hpp: -------------------------------------------------------------------------------- 1 | // BITSET2 2 | // 3 | // Copyright Claas Bontus 4 | // 5 | // Use, modification and distribution is subject to the 6 | // Boost Software License, Version 1.0. (See accompanying 7 | // file LICENSE.txt or copy at 8 | // http://www.boost.org/LICENSE_1_0.txt) 9 | // 10 | // Project home: https://github.com/ClaasBontus/bitset2 11 | // 12 | 13 | #ifndef BITSET2_BIT_CHARS_CB_HPP 14 | #define BITSET2_BIT_CHARS_CB_HPP 15 | 16 | #include "h_types.hpp" 17 | 18 | 19 | namespace Bitset2 20 | { 21 | namespace detail 22 | { 23 | 24 | template 25 | struct bit_chars 26 | { 27 | using h_t= h_types; 28 | using ULONG_t= typename h_t::ULONG_t; 29 | using ULLONG_t= typename h_t::ULLONG_t; 30 | using LRGST_t= typename h_t::LRGST_t; 31 | using base_t= T; 32 | // 33 | enum : size_t 34 | { n_bits= N 35 | , ulong_n_bits= h_t::ulong_n_bits ///< #bits in ULONG_t 36 | , ullong_n_bits= h_t::ullong_n_bits ///< #bits in ULLONG_t 37 | , lrgst_n_bist= h_t::lrgst_n_bist ///< #bits in LRGST_t 38 | , base_t_n_bits= h_t::base_t_n_bits ///< #bits in T 39 | , div_val= n_bits / base_t_n_bits 40 | , mod_val= n_bits % base_t_n_bits 41 | , n_words= mod_val ? div_val + 1 : div_val ///< #words required 42 | , n_array= ( n_words == 0 ) ? 1 : n_words ///< #words used 43 | }; 44 | enum : ULONG_t 45 | { ulong_max= ULONG_MAX }; 46 | enum : base_t 47 | { all_one= base_t(~base_t(0)) 48 | , low_bit_pattern= ///< Mask for idx==0 49 | n_bits == 0 ? base_t(0) 50 | : ( div_val > 0 || mod_val == 0 ) 51 | ? all_one 52 | : ce_right_shift( all_one, base_t_n_bits - mod_val ) 53 | , hgh_bit_pattern= ///< Mask for idx+1==n_words 54 | n_bits == 0 ? base_t(0) 55 | : mod_val == 0 56 | ? all_one 57 | : ce_right_shift( all_one, base_t_n_bits - mod_val ) 58 | }; 59 | }; // struct bit_chars 60 | 61 | } // namespace detail 62 | } // namespace Bitset2 63 | 64 | 65 | 66 | 67 | #endif // BITSET2_BIT_CHARS_CB_HPP 68 | -------------------------------------------------------------------------------- /detail/bitset2_impl.hpp: -------------------------------------------------------------------------------- 1 | // BITSET2 2 | // 3 | // Copyright Claas Bontus 4 | // 5 | // Use, modification and distribution is subject to the 6 | // Boost Software License, Version 1.0. (See accompanying 7 | // file LICENSE.txt or copy at 8 | // http://www.boost.org/LICENSE_1_0.txt) 9 | // 10 | // Project home: https://github.com/ClaasBontus/bitset2 11 | // 12 | 13 | #ifndef BITSET2_IMPL_CB_HPP 14 | #define BITSET2_IMPL_CB_HPP 15 | 16 | #include "bit_chars.hpp" 17 | #include "array_add.hpp" 18 | #include "ullong2array.hpp" 19 | #include "array2u_long_t.hpp" 20 | #include 21 | #include 22 | 23 | 24 | namespace Bitset2 25 | { 26 | namespace detail 27 | { 28 | 29 | template 30 | class bitset2_impl 31 | { 32 | using b_chars= bit_chars; 33 | using h_t= h_types; 34 | 35 | public: 36 | enum : size_t { n_array= b_chars::n_array 37 | , npos= h_t::npos }; 38 | using base_t= T; 39 | using ULONG_t= typename b_chars::ULONG_t; 40 | using ULLONG_t= typename b_chars::ULLONG_t; 41 | using LRGST_t= typename b_chars::LRGST_t; 42 | using array_t= typename h_types::template array_t; 43 | 44 | protected: 45 | enum : size_t 46 | { n_words= b_chars::n_words 47 | , ulong_n_bits= b_chars::ulong_n_bits 48 | , ullong_n_bits= b_chars::ullong_n_bits 49 | , base_t_n_bits= b_chars::base_t_n_bits 50 | }; 51 | enum : ULONG_t 52 | { ulong_max= b_chars::ulong_max }; 53 | enum : base_t 54 | { low_bit_pattern= b_chars::low_bit_pattern 55 | , hgh_bit_pattern= b_chars::hgh_bit_pattern 56 | , all_one= b_chars::all_one 57 | }; 58 | 59 | template 60 | using a2a= detail::array2array; 61 | 62 | 63 | /* ----------------------------------------------------------------------- */ 64 | constexpr 65 | bitset2_impl() noexcept 66 | {} 67 | 68 | constexpr 69 | bitset2_impl( bitset2_impl const & ) noexcept= default; 70 | 71 | constexpr 72 | bitset2_impl( bitset2_impl && ) noexcept= default; 73 | 74 | constexpr 75 | bitset2_impl & 76 | operator=( bitset2_impl const & ) noexcept= default; 77 | 78 | constexpr 79 | bitset2_impl & 80 | operator=( bitset2_impl && ) noexcept= default; 81 | 82 | explicit 83 | constexpr 84 | bitset2_impl( LRGST_t v ) noexcept 85 | : m_value( lrgst2array()( v ) ) 86 | {} 87 | 88 | template 89 | explicit 90 | constexpr 91 | bitset2_impl( std::array const & value ) noexcept 92 | : m_value( a2a()( hgh_bit_pattern, value ) ) 93 | {} 94 | 95 | explicit 96 | bitset2_impl( const std::bitset &bs ) noexcept 97 | { 98 | if( N == 0 ) return; 99 | if( ullong_n_bits >= base_t_n_bits && n_words == 1 ) 100 | { 101 | m_value[0]= bs.to_ullong(); 102 | return; 103 | } 104 | 105 | size_t offset= 0; 106 | for( size_t ct= 0; ct < n_words; ++ct ) 107 | { 108 | base_t val= base_t(0); 109 | auto const bit_limit= 110 | ( ct < n_words - 1 ) ? base_t_n_bits : N - offset; 111 | for( size_t bit_ct= 0; bit_ct < bit_limit; ++bit_ct ) 112 | { 113 | auto const test_bit= offset + bit_limit - bit_ct - 1; 114 | val <<= 1; 115 | if( bs.test( test_bit ) ) val |= base_t(1); 116 | } // for bit_ct 117 | m_value[ct]= val; 118 | offset += base_t_n_bits; 119 | } // for ct 120 | } // bitset2_impl( const std::bitset &bs ) 121 | 122 | 123 | template< class CharT, class Traits, class Alloc > 124 | explicit 125 | bitset2_impl( std::basic_string const &str, 126 | typename 127 | std::basic_string::size_type pos, 128 | typename 129 | std::basic_string::size_type n, 130 | CharT zero, 131 | CharT one ) 132 | { 133 | auto const str_sz= str.size(); 134 | if( pos > str_sz ) 135 | throw std::out_of_range( "bitset2: String submitted to " 136 | "constructor smaller than pos" ); 137 | auto const n_bits= std::min( N, std::min( n, str_sz - pos ) ); 138 | 139 | for( size_t bit_ct= 0; bit_ct < n_bits; ++bit_ct ) 140 | { 141 | auto const chr= str[bit_ct+pos]; 142 | if( Traits::eq( one, chr ) ) set( n_bits - bit_ct - 1 ); 143 | else if( !Traits::eq( zero, chr ) ) 144 | throw std::invalid_argument( "bitset2: Invalid argument in " 145 | "string submitted to constructor" ); 146 | } // for bit_ct 147 | } 148 | /* ----------------------------------------------------------------------- */ 149 | 150 | 151 | //********************************************************** 152 | 153 | 154 | constexpr 155 | array_t & 156 | get_data() noexcept 157 | { return m_value; } 158 | 159 | constexpr 160 | bool 161 | operator[]( size_t bit ) const noexcept 162 | { return test_noexcept( bit ); } 163 | 164 | constexpr 165 | bool 166 | test_noexcept( size_t bit ) const noexcept 167 | { return m_value[bit / base_t_n_bits] & ( T(1) << ( bit % base_t_n_bits ) ); } 168 | 169 | constexpr 170 | bitset2_impl & 171 | set( size_t bit, bool value= true ) 172 | { 173 | if( bit >= N ) 174 | throw std::out_of_range( "bitset2: Setting of bit out of range" ); 175 | set_noexcept( bit, value ); 176 | return *this; 177 | } // set 178 | 179 | constexpr 180 | bitset2_impl & 181 | set() noexcept 182 | { 183 | if( N > 0 ) 184 | { 185 | size_t c= 0; 186 | for( ; c < n_words - 1; ++c ) m_value[c]= ~base_t(0); 187 | m_value[c]= hgh_bit_pattern; 188 | } 189 | return *this; 190 | } // set 191 | 192 | constexpr 193 | bitset2_impl & 194 | reset() noexcept 195 | { 196 | for( size_t c= 0; c < n_array; ++c ) m_value[c]= base_t(0); 197 | return *this; 198 | } 199 | 200 | constexpr 201 | bool 202 | test_set( size_t bit, bool value= true ) 203 | { 204 | if( bit >= N ) 205 | throw std::out_of_range( "bitset2: test_set out of range" ); 206 | return test_set_noexcept( bit, value ); 207 | } // test_set 208 | 209 | constexpr 210 | bitset2_impl & 211 | flip_noexcept( size_t bit ) noexcept 212 | { 213 | m_value[bit / base_t_n_bits] ^= ( base_t(1) << ( bit % base_t_n_bits ) ); 214 | return *this; 215 | } 216 | 217 | constexpr 218 | bitset2_impl & 219 | flip( size_t bit ) 220 | { 221 | if( bit >= N ) 222 | throw std::out_of_range( "bitset2: Flipping of bit out of range" ); 223 | return flip_noexcept( bit ); 224 | } // flip 225 | 226 | constexpr 227 | bitset2_impl & 228 | flip() noexcept 229 | { 230 | if( N > 0 ) 231 | { 232 | size_t c= 0; 233 | for( ; c < n_words - 1; ++c ) m_value[c] ^= ~base_t(0); 234 | m_value[c] ^= hgh_bit_pattern; 235 | } 236 | return *this; 237 | } // flip 238 | 239 | public: 240 | constexpr 241 | array_t const & 242 | data() const noexcept 243 | { return m_value; } 244 | 245 | constexpr 246 | ULONG_t 247 | to_ulong() const 248 | { 249 | using a2l= array2u_long_t; 250 | return ( N == 0 ) ? 0ul 251 | : a2l().check_overflow( m_value ) 252 | ? throw std::overflow_error( "Cannot convert bitset2 " 253 | "to unsigned long" ) 254 | : a2l()( m_value ); 255 | } // to_ulong 256 | 257 | constexpr 258 | ULLONG_t 259 | to_ullong() const 260 | { 261 | using a2l= array2u_long_t; 262 | return ( N == 0 ) ? 0ull 263 | : a2l().check_overflow( m_value ) 264 | ? throw std::overflow_error( "Cannot convert bitset2 " 265 | "to unsigned long long" ) 266 | : a2l()( m_value ); 267 | } // to_ullong 268 | 269 | #ifdef __SIZEOF_INT128__ 270 | constexpr 271 | LRGST_t 272 | to_u128() const 273 | { 274 | using a2l= array2u_long_t; 275 | return ( N == 0 ) ? LRGST_t(0) 276 | : a2l().check_overflow( m_value ) 277 | ? throw std::overflow_error( "Cannot convert bitset2 " 278 | "to unsigned __int128" ) 279 | : a2l()( m_value ); 280 | } // to_u128 281 | #endif 282 | 283 | constexpr 284 | bool 285 | test( size_t bit ) const 286 | { 287 | return ( bit >= N ) 288 | ? throw std::out_of_range( "bitset2: Testing of bit out of range" ) 289 | : operator[]( bit ); 290 | } 291 | 292 | constexpr 293 | void 294 | set_noexcept( size_t bit, bool value= true ) noexcept 295 | { 296 | if( value ) m_value[bit / base_t_n_bits] 297 | |= base_t( base_t(1) << ( bit % base_t_n_bits ) ); 298 | else m_value[bit / base_t_n_bits] 299 | &= base_t(~( base_t(1) << ( bit % base_t_n_bits ) )); 300 | } 301 | 302 | constexpr 303 | bool 304 | test_set_noexcept( size_t bit, bool value= true ) noexcept 305 | { 306 | auto const dv= bit / base_t_n_bits; 307 | auto const md= bit % base_t_n_bits; 308 | auto const pttrn= ( base_t(1) << md ); 309 | auto const ret_val= bool( m_value[dv] & pttrn ); 310 | 311 | if( value ) m_value[dv] |= pttrn; 312 | else m_value[dv] &= ~pttrn; 313 | 314 | return ret_val; 315 | } // test_set_noexcept 316 | 317 | constexpr 318 | bool 319 | none() const noexcept 320 | { return detail::array_funcs().none( m_value ); } 321 | 322 | constexpr 323 | bool 324 | any() const noexcept 325 | { return ( N > 0 ) && !none(); } 326 | 327 | constexpr 328 | bool 329 | all() const noexcept 330 | { return ( N > 0 ) && detail::array_ops( 0 ).all( m_value ); } 331 | 332 | constexpr 333 | size_t 334 | count() const noexcept 335 | { return detail::array_funcs().count( m_value ); } 336 | 337 | /// True if exactly one bit set. 338 | constexpr 339 | bool 340 | has_single_bit() const noexcept 341 | { return detail::array_funcs().has_single_bit( m_value ); } 342 | 343 | /// \brief Returns index of first (least significant) bit set. 344 | /// Returns npos if all bits are zero. 345 | constexpr 346 | size_t 347 | find_first() const noexcept 348 | { 349 | return detail::array_funcs().idx_lsb_set(m_value, m_value[0], 0, base_t(2)); 350 | } 351 | 352 | /// \brief Returns index of first (least significant) bit unset. 353 | /// Returns npos if all bits are set. 354 | constexpr 355 | size_t 356 | find_first_zero() const noexcept 357 | { 358 | return detail::array_funcs().idx_lsb_set(m_value, ~m_value[0], 0, hgh_bit_pattern); 359 | } 360 | 361 | /// \brief Returns index of last (most significant) bit set. 362 | /// Returns npos if all bits are zero. 363 | constexpr 364 | size_t 365 | find_last() const noexcept 366 | { 367 | return detail::array_funcs().idx_msb_set(m_value, base_t(2)); 368 | } 369 | 370 | /// \brief Returns index of last (most significant) bit unset. 371 | /// Returns npos if all bits are set. 372 | constexpr 373 | size_t 374 | find_last_zero() const noexcept 375 | { 376 | return detail::array_funcs().idx_msb_set(m_value, hgh_bit_pattern); 377 | } 378 | 379 | /// \brief Returns index of next (> idx) bit set. 380 | /// Returns npos if no more bits set. 381 | /// Throws out_of_range if idx >= N. 382 | constexpr 383 | size_t 384 | find_next( size_t idx ) const 385 | { 386 | size_t const arr_idx = (idx+1) / base_t_n_bits; 387 | size_t const idx_mod = (idx+1) % base_t_n_bits; 388 | return idx >= N 389 | ? throw std::out_of_range( "bitset2: find_next index out of range" ) 390 | : idx + 1 == N 391 | ? npos 392 | : detail::array_funcs() 393 | .idx_lsb_set( m_value, 394 | base_t( m_value[arr_idx] & ce_left_shift(T(~T(0)),idx_mod) ), 395 | arr_idx, 396 | base_t(2) ); 397 | } // find_next 398 | 399 | /// \brief Returns index of next (> idx) bit unset. 400 | /// Returns npos if no more bits unset. 401 | /// Throws out_of_range if idx >= N. 402 | constexpr 403 | size_t 404 | find_next_zero( size_t idx ) const 405 | { 406 | size_t const arr_idx = (idx+1) / base_t_n_bits; 407 | size_t const idx_mod = (idx+1) % base_t_n_bits; 408 | return idx >= N 409 | ? throw std::out_of_range( "bitset2: find_next index out of range" ) 410 | : idx + 1 == N 411 | ? npos 412 | : detail::array_funcs() 413 | .idx_lsb_set( m_value, 414 | base_t( ~(m_value[arr_idx]) & ce_left_shift(T(~T(0)),idx_mod) ), 415 | arr_idx, 416 | hgh_bit_pattern ); 417 | } // find_next_zero 418 | 419 | constexpr 420 | bool 421 | operator==( bitset2_impl const &v2 ) const noexcept 422 | { return detail::array_funcs().equal( m_value, v2.m_value ); } 423 | 424 | constexpr 425 | bool 426 | operator!=( bitset2_impl const &v2 ) const noexcept 427 | { return !( *this == v2 ); } 428 | 429 | constexpr 430 | bool 431 | operator<( bitset2_impl const &v2 ) const noexcept 432 | { return detail::array_funcs().less_than( m_value, v2.m_value ); } 433 | 434 | constexpr 435 | bool 436 | operator<=( bitset2_impl const &v2 ) const noexcept 437 | { return ! ( *this > v2 ); } 438 | 439 | constexpr 440 | bool 441 | operator>( bitset2_impl const &v2 ) const noexcept 442 | { return detail::array_funcs().less_than(v2.m_value, m_value); } 443 | 444 | constexpr 445 | bool 446 | operator>=( bitset2_impl const &v2 ) const noexcept 447 | { return ! ( *this < v2 ); } 448 | 449 | explicit 450 | operator std::bitset() const 451 | { 452 | using b_t= std::bitset; 453 | if( N == 0 ) return b_t{}; 454 | if( n_words == 1 && base_t_n_bits <= ullong_n_bits ) return b_t( to_ullong() ); 455 | 456 | b_t ret_val; 457 | for( size_t ct= 0; ct < N; ++ct ) ret_val[ct]= operator[](ct); 458 | 459 | return ret_val; 460 | } 461 | private: 462 | array_t m_value= (detail::gen_empty_array)(); 463 | }; // class bitset2_impl 464 | 465 | 466 | } // namespace detail 467 | } // namespace Bitset2 468 | 469 | 470 | 471 | #endif // BITSET2_IMPL_CB_HPP 472 | -------------------------------------------------------------------------------- /detail/count_bits.hpp: -------------------------------------------------------------------------------- 1 | // BITSET2 2 | // 3 | // Copyright Claas Bontus 4 | // 5 | // Use, modification and distribution is subject to the 6 | // Boost Software License, Version 1.0. (See accompanying 7 | // file LICENSE.txt or copy at 8 | // http://www.boost.org/LICENSE_1_0.txt) 9 | // 10 | // Project home: https://github.com/ClaasBontus/bitset2 11 | // 12 | 13 | #ifndef BITSET2_COUNT_BITS_CB_HPP 14 | #define BITSET2_COUNT_BITS_CB_HPP 15 | 16 | 17 | #include "h_types.hpp" 18 | 19 | #if __cplusplus >= 202002L 20 | # include 21 | #endif 22 | 23 | 24 | namespace Bitset2 25 | { 26 | namespace detail 27 | { 28 | 29 | /// Returns the number of bits set in val 30 | template 31 | constexpr 32 | inline 33 | size_t 34 | count_bits( T val, size_t count= 0 ) noexcept 35 | { 36 | #ifdef __cpp_lib_bitops 37 | # ifdef __SIZEOF_INT128__ 38 | if constexpr( !std::is_same_v ) 39 | # endif 40 | return std::popcount(val); 41 | #endif 42 | return 43 | ( val == T(0) ) 44 | ? count 45 | : count_bits( T(val & T( val - T(1) )), // clears lowest set bit 46 | count + 1 ); 47 | } 48 | 49 | } // namespace detail 50 | } // namespace Bitset2 51 | 52 | 53 | 54 | 55 | #endif // BITSET2_COUNT_BITS_CB_HPP 56 | -------------------------------------------------------------------------------- /detail/h_types.hpp: -------------------------------------------------------------------------------- 1 | // BITSET2 2 | // 3 | // Copyright Claas Bontus 4 | // 5 | // Use, modification and distribution is subject to the 6 | // Boost Software License, Version 1.0. (See accompanying 7 | // file LICENSE.txt or copy at 8 | // http://www.boost.org/LICENSE_1_0.txt) 9 | // 10 | // Project home: https://github.com/ClaasBontus/bitset2 11 | // 12 | 13 | #ifndef BITSET2_H_TYPES_CB_HPP 14 | #define BITSET2_H_TYPES_CB_HPP 15 | 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | 22 | 23 | namespace Bitset2 24 | { 25 | namespace detail 26 | { 27 | template 28 | struct is_unsgnd_int 29 | { 30 | static 31 | constexpr bool value = ( std::is_integral::value 32 | && std::is_unsigned::value ) 33 | #ifdef __SIZEOF_INT128__ 34 | || std::is_same::value 35 | #endif 36 | ; 37 | }; // struct is_unsgnd_int 38 | 39 | 40 | template struct h_types; 41 | 42 | template 43 | struct h_types::value>::type> 45 | { 46 | using ULONG_t= unsigned long; 47 | using ULLONG_t= unsigned long long; 48 | using base_t= T; 49 | #ifdef __SIZEOF_INT128__ 50 | using LRGST_t= unsigned __int128; 51 | #else 52 | using LRGST_t= ULLONG_t; 53 | #endif 54 | 55 | template 56 | using array_t= std::array; 57 | 58 | enum : size_t 59 | { ulong_n_bits= sizeof(ULONG_t) * CHAR_BIT ///< #bits in ULONG_t 60 | , ullong_n_bits= sizeof(ULLONG_t) * CHAR_BIT ///< #bits in ULLONG_t 61 | , lrgst_n_bist= sizeof(LRGST_t) * CHAR_BIT ///< #bits in LRGST_t 62 | , base_t_n_bits= sizeof(base_t) * CHAR_BIT ///< #bits in base_t 63 | , npos= ~size_t(0) 64 | }; 65 | }; // struct h_types 66 | 67 | 68 | template 69 | constexpr 70 | T 71 | ce_min( T v1, T v2 ) noexcept 72 | { return ( v1 < v2 ) ? v1 : v2; } 73 | 74 | 75 | 76 | /// http://stackoverflow.com/q/29136207/3876684 77 | template 78 | constexpr 79 | T 80 | ce_left_shift( T v1, size_t n_shift ) noexcept 81 | { 82 | return ( n_shift == 0 ) ? v1 83 | : ( ( n_shift >= h_types::base_t_n_bits ) ? T(0) 84 | : T( v1 << n_shift ) ); 85 | } 86 | 87 | template 88 | constexpr 89 | T 90 | ce_right_shift( T v1, size_t n_shift ) noexcept 91 | { 92 | return ( n_shift == 0 ) ? v1 93 | : ( ( n_shift >= h_types::base_t_n_bits ) ? T(0) 94 | : T( v1 >> n_shift ) ); 95 | } 96 | 97 | 98 | 99 | template 100 | inline constexpr 101 | typename h_types::template array_t 102 | gen_empty_array_impl( std::index_sequence ) noexcept 103 | { 104 | return 105 | typename h_types::template array_t{{ ( T(S) & T(0) ) ... }}; 106 | } 107 | 108 | 109 | 110 | template 111 | inline constexpr 112 | typename h_types::template array_t 113 | gen_empty_array() noexcept 114 | { 115 | return 116 | gen_empty_array_impl( std::make_index_sequence() ); 117 | } // gen_empty_array 118 | 119 | } // namespace detail 120 | } // namespace Bitset2 121 | 122 | 123 | 124 | 125 | #endif // BITSET2_H_TYPES_CB_HPP 126 | -------------------------------------------------------------------------------- /detail/hash.hpp: -------------------------------------------------------------------------------- 1 | // BITSET2 2 | // 3 | // Copyright Claas Bontus 4 | // 5 | // Use, modification and distribution is subject to the 6 | // Boost Software License, Version 1.0. (See accompanying 7 | // file LICENSE.txt or copy at 8 | // http://www.boost.org/LICENSE_1_0.txt) 9 | // 10 | // Project home: https://github.com/ClaasBontus/bitset2 11 | // 12 | 13 | #ifndef BITSET2_HASH_CB_HPP 14 | #define BITSET2_HASH_CB_HPP 15 | 16 | #include "h_types.hpp" 17 | 18 | #include 19 | #include 20 | #include 21 | #include 22 | 23 | 24 | namespace Bitset2 25 | { 26 | namespace detail 27 | { 28 | 29 | 30 | template 31 | struct hash_impl 32 | { 33 | using base_t= T; 34 | using result_type= std::size_t; 35 | using array_t= typename h_types::template array_t; 36 | 37 | enum : size_t 38 | { size_t_bits= sizeof(result_type) * CHAR_BIT ///< #bits in result_type 39 | , base_t_n_bits= h_types::base_t_n_bits ///< #bits in T 40 | , bits_mod= base_t_n_bits % size_t_bits 41 | , bits_div= base_t_n_bits / size_t_bits + ( bits_mod > 0 ) 42 | , size_t_mod= size_t_bits % base_t_n_bits 43 | , size_t_div= size_t_bits / base_t_n_bits 44 | }; 45 | 46 | enum : bool 47 | { easy_bits= ( size_t_bits >= base_t_n_bits ) 48 | , easy_ratio= ( size_t_mod == 0 ) 49 | }; 50 | 51 | result_type 52 | operator()( array_t const & arr ) const noexcept 53 | { 54 | if( n_words == 0 ) return 0; 55 | if( n_words == 1 ) 56 | { 57 | if( easy_bits ) return arr[0]; 58 | return to_result_t( arr[0] ); 59 | } // if n_words == 1 60 | 61 | return cmpsd_hash( arr ); 62 | } 63 | 64 | result_type 65 | to_result_t( base_t a ) const noexcept 66 | { 67 | result_type ret_val= 0; 68 | size_t shft= 0; 69 | for( size_t c= 0; c < bits_div; ++c, shft += size_t_bits ) 70 | { 71 | auto const crrnt= result_type( a >> shft ); 72 | do_combine( ret_val, crrnt, c ); 73 | } 74 | return ret_val; 75 | } // to_result_t 76 | 77 | result_type 78 | cmpsd_hash( array_t const & arr ) const noexcept 79 | { 80 | result_type ret_val= 0; 81 | 82 | if( easy_ratio ) 83 | { 84 | for( size_t c= 0; c < n_words; c += size_t_div ) 85 | { 86 | result_type r= 0; 87 | auto const uppr= std::min( n_words, c + size_t_div ); 88 | for( size_t w= c; w < uppr; ++w ) 89 | r |= ( result_type(arr[w]) << ((w-c)*base_t_n_bits) ); 90 | do_combine( ret_val, r, c / size_t_div ); 91 | } 92 | } 93 | else 94 | { 95 | for( size_t c= 0; c < n_words; ++c ) 96 | { 97 | auto const crrnt= easy_bits 98 | ? result_type(arr[c]) : to_result_t(arr[c]); 99 | do_combine( ret_val, crrnt, c ); 100 | } 101 | } 102 | 103 | return ret_val; 104 | } // cmpsd_hash 105 | 106 | void 107 | do_combine( result_type &r, result_type crrnt, size_t cnt ) const noexcept 108 | { 109 | crrnt += cnt; 110 | auto const n_rot= cnt % size_t_bits; 111 | if( n_rot > 0 ) 112 | crrnt= ( crrnt << n_rot ) | ( crrnt >> (size_t_bits-n_rot) ); 113 | 114 | r ^= crrnt; 115 | } // do_combine 116 | }; // struct hash_impl 117 | 118 | 119 | 120 | 121 | } } // namespace Bitset2::detail 122 | 123 | 124 | 125 | 126 | #endif // BITSET2_HASH_CB_HPP 127 | -------------------------------------------------------------------------------- /detail/hex_params.hpp: -------------------------------------------------------------------------------- 1 | // BITSET2 2 | // 3 | // Copyright Claas Bontus 4 | // 5 | // Use, modification and distribution is subject to the 6 | // Boost Software License, Version 1.0. (See accompanying 7 | // file LICENSE.txt or copy at 8 | // http://www.boost.org/LICENSE_1_0.txt) 9 | // 10 | // Project home: https://github.com/ClaasBontus/bitset2 11 | // 12 | 13 | #ifndef BITSET2_HEX_PARAMS_CB_HPP 14 | #define BITSET2_HEX_PARAMS_CB_HPP 15 | 16 | #include 17 | 18 | 19 | namespace Bitset2 20 | { 21 | 22 | 23 | template< class CharT = char, 24 | class Traits = std::char_traits, 25 | class Allocator = std::allocator > 26 | struct hex_params 27 | { 28 | using str_t= std::basic_string; 29 | 30 | CharT zeroCh= CharT( '0' ); 31 | CharT aCh= CharT( 'a' ); 32 | bool leadingZeroes= true; 33 | bool nonEmpty= true; 34 | str_t prefix= str_t{}; 35 | }; // struct hex_params 36 | 37 | 38 | 39 | } // namespace Bitset2 40 | 41 | 42 | #endif // BITSET2_HEX_PARAMS_CB_HPP 43 | -------------------------------------------------------------------------------- /detail/index_lsb_set.hpp: -------------------------------------------------------------------------------- 1 | // BITSET2 2 | // 3 | // Copyright Claas Bontus 4 | // 5 | // Use, modification and distribution is subject to the 6 | // Boost Software License, Version 1.0. (See accompanying 7 | // file LICENSE.txt or copy at 8 | // http://www.boost.org/LICENSE_1_0.txt) 9 | // 10 | // Project home: https://github.com/ClaasBontus/bitset2 11 | // 12 | 13 | 14 | #ifndef BITSET2_INDEX_LSB_SET_CB_HPP 15 | #define BITSET2_INDEX_LSB_SET_CB_HPP 16 | 17 | 18 | #include 19 | #include 20 | #include 21 | #include 22 | 23 | #if __cplusplus >= 202002L 24 | # include 25 | # ifdef __cpp_lib_bitops 26 | # define CMPLRCOUNTR 1 27 | # else 28 | # define CMPLRCOUNTR 0 29 | # endif 30 | #else 31 | # define CMPLRCOUNTR 0 32 | #endif 33 | 34 | 35 | 36 | namespace Bitset2 37 | { 38 | namespace detail 39 | { 40 | 41 | 42 | /// https://graphics.stanford.edu/~seander/bithacks.html#ZerosOnRightBinSearch 43 | template 44 | struct index_lsb_set 45 | { 46 | enum : size_t { npos= std::numeric_limits::max() 47 | , n_bits= sizeof(T) * CHAR_BIT }; 48 | 49 | constexpr 50 | index_lsb_set() noexcept 51 | { 52 | static_assert( ( n_bits & ( n_bits - 1 ) ) == 0, 53 | "Number of bits in data type is not a power of 2" ); 54 | } 55 | 56 | constexpr 57 | size_t 58 | impl( T val ) const noexcept 59 | { 60 | size_t c = 1; 61 | size_t sh_rgt = n_bits >> 1; 62 | T pttrn = T( T(~T(0)) >> sh_rgt ); 63 | 64 | while( sh_rgt >= 2 ) 65 | { 66 | if( T( val & pttrn ) == T(0) ) 67 | { 68 | c += sh_rgt; 69 | val >>= sh_rgt; 70 | } 71 | sh_rgt >>= 1; 72 | pttrn >>= sh_rgt; 73 | } 74 | if( T(val & T(1) ) == T(1) ) --c; 75 | 76 | return c; 77 | } // impl 78 | 79 | #ifdef __cpp_lib_bitops 80 | constexpr 81 | size_t 82 | impl2( T val ) const noexcept 83 | { 84 | # ifdef __SIZEOF_INT128__ 85 | if constexpr( std::is_same_v ) return impl(val); 86 | else 87 | # endif 88 | return std::countr_zero(val); 89 | } 90 | #endif 91 | 92 | /// \brief Returns index of first (least significant) bit set in val. 93 | /// Returns npos if all bits are zero. 94 | constexpr 95 | size_t 96 | operator()( T val ) const noexcept 97 | { 98 | if( T(0) == val ) return npos; 99 | if constexpr( CMPLRCOUNTR ) return impl2(val); 100 | return impl(val); 101 | } 102 | }; // struct index_lsb_set 103 | 104 | 105 | 106 | } // namespace detail 107 | } // namespace Bitset2 108 | 109 | 110 | #undef CMPLRCOUNTR 111 | 112 | #endif // BITSET2_INDEX_LSB_SET_CB_HPP 113 | -------------------------------------------------------------------------------- /detail/index_msb_set.hpp: -------------------------------------------------------------------------------- 1 | // BITSET2 2 | // 3 | // Copyright Claas Bontus 4 | // 5 | // Use, modification and distribution is subject to the 6 | // Boost Software License, Version 1.0. (See accompanying 7 | // file LICENSE.txt or copy at 8 | // http://www.boost.org/LICENSE_1_0.txt) 9 | // 10 | // Project home: https://github.com/ClaasBontus/bitset2 11 | // 12 | 13 | 14 | #ifndef BITSET2_INDEX_MSB_SET_CB_HPP 15 | #define BITSET2_INDEX_MSB_SET_CB_HPP 16 | 17 | 18 | #include 19 | #include 20 | #include 21 | #include 22 | 23 | #if __cplusplus >= 202002L 24 | # include 25 | # ifdef __cpp_lib_bitops 26 | # define CMPLRCOUNTR 1 27 | # else 28 | # define CMPLRCOUNTR 0 29 | # endif 30 | #else 31 | # define CMPLRCOUNTR 0 32 | #endif 33 | 34 | 35 | 36 | namespace Bitset2 37 | { 38 | namespace detail 39 | { 40 | 41 | 42 | /// https://graphics.stanford.edu/~seander/bithacks.html#ZerosOnRightBinSearch 43 | template 44 | struct index_msb_set 45 | { 46 | enum : size_t { npos= std::numeric_limits::max() 47 | , n_bits= sizeof(T) * CHAR_BIT }; 48 | 49 | constexpr 50 | index_msb_set() noexcept 51 | { 52 | static_assert( ( n_bits & ( n_bits - 1 ) ) == 0, 53 | "Number of bits in data type is not a power of 2" ); 54 | } 55 | 56 | constexpr 57 | size_t 58 | impl( T val ) const noexcept 59 | { 60 | T const fnl_bit = T( T(1) << (n_bits-1) ); 61 | if( T(val & fnl_bit) == fnl_bit ) return n_bits - 1; 62 | 63 | size_t c = 1; 64 | size_t sh_lft = n_bits >> 1; 65 | T pttrn = T( T(~T(0)) << sh_lft ); 66 | 67 | while( sh_lft >= 2 ) 68 | { 69 | if( T( val & pttrn ) == T(0) ) 70 | { 71 | c += sh_lft; 72 | val <<= sh_lft; 73 | } 74 | sh_lft >>= 1; 75 | pttrn <<= sh_lft; 76 | } 77 | if( T(val & fnl_bit ) == fnl_bit ) --c; 78 | 79 | return n_bits - 1 - c; 80 | } // impl 81 | 82 | #ifdef __cpp_lib_bitops 83 | constexpr 84 | size_t 85 | impl2( T val ) const noexcept 86 | { 87 | # ifdef __SIZEOF_INT128__ 88 | if constexpr( std::is_same_v ) return impl(val); 89 | else 90 | # endif 91 | return n_bits - 1 - std::countl_zero(val); 92 | } 93 | #endif 94 | 95 | /// \brief Returns index of last (most significant) bit set in val. 96 | /// Returns npos if all bits are zero. 97 | constexpr 98 | size_t 99 | operator()( T val ) const noexcept 100 | { 101 | if( T(0) == val ) return npos; 102 | if constexpr( CMPLRCOUNTR ) return impl2(val); 103 | return impl(val); 104 | } 105 | }; // struct index_msb_set 106 | 107 | 108 | 109 | } // namespace detail 110 | } // namespace Bitset2 111 | 112 | 113 | #undef CMPLRCOUNTR 114 | 115 | 116 | #endif // BITSET2_INDEX_MSB_SET_CB_HPP 117 | -------------------------------------------------------------------------------- /detail/reverse_bits.hpp: -------------------------------------------------------------------------------- 1 | // BITSET2 2 | // 3 | // Copyright Claas Bontus 4 | // 5 | // Use, modification and distribution is subject to the 6 | // Boost Software License, Version 1.0. (See accompanying 7 | // file LICENSE.txt or copy at 8 | // http://www.boost.org/LICENSE_1_0.txt) 9 | // 10 | // Project home: https://github.com/ClaasBontus/bitset2 11 | // 12 | 13 | #ifndef BITSET2_REVERSE_BITS_CB_HPP 14 | #define BITSET2_REVERSE_BITS_CB_HPP 15 | 16 | #include 17 | #include 18 | #include 19 | 20 | 21 | 22 | namespace Bitset2 23 | { 24 | namespace detail 25 | { 26 | 27 | 28 | /// https://graphics.stanford.edu/~seander/bithacks.html#ReverseParallel 29 | template 30 | struct reverse_bits 31 | { 32 | enum : size_t { n_bits= sizeof(T) * CHAR_BIT 33 | , n_bits_h= n_bits >> 1 }; 34 | 35 | constexpr 36 | reverse_bits() noexcept 37 | { 38 | static_assert( ( n_bits & ( n_bits - 1 ) ) == 0, 39 | "Number of bits in data type is not a power of 2" ); 40 | } 41 | 42 | /// \brief Reverses bits in val. 43 | constexpr 44 | T 45 | operator()( T val ) const noexcept { return rvrs( val ); } 46 | 47 | private: 48 | constexpr 49 | T 50 | rvrs( T val, 51 | T mask= T( ~T(0) ) >> n_bits_h, 52 | size_t s= n_bits_h ) const noexcept 53 | { 54 | return s == 0 ? val 55 | : rvrs( ( (val >> s) & mask ) | ( (val << s) & ~mask ), 56 | mask ^ ( mask << ( s >> 1 ) ), 57 | s >> 1 ); 58 | } 59 | }; // struct reverse_bits 60 | 61 | 62 | } // namespace detail 63 | } // namespace Bitset2 64 | 65 | 66 | #endif // BITSET2_REVERSE_BITS_CB_HPP 67 | -------------------------------------------------------------------------------- /detail/select_base_t.hpp: -------------------------------------------------------------------------------- 1 | // BITSET2 2 | // 3 | // Copyright Claas Bontus 4 | // 5 | // Use, modification and distribution is subject to the 6 | // Boost Software License, Version 1.0. (See accompanying 7 | // file LICENSE.txt or copy at 8 | // http://www.boost.org/LICENSE_1_0.txt) 9 | // 10 | // Project home: https://github.com/ClaasBontus/bitset2 11 | // 12 | 13 | #ifndef BITSET2_SELECT_BASE_T_CB_HPP 14 | #define BITSET2_SELECT_BASE_T_CB_HPP 15 | 16 | #include 17 | #include 18 | 19 | namespace Bitset2 20 | { 21 | namespace detail 22 | { 23 | 24 | 25 | template 26 | struct if_else { using type= T1; }; 27 | 28 | template 29 | struct if_else { using type= T2; }; 30 | 31 | template 32 | using if_else_t= typename if_else::type ; 33 | 34 | 35 | /// \brief Select any of uint8_t, uint16_t, uint32_t or 36 | /// unsigned long long. Result depends on N and on provision 37 | /// of these types by compiler. 38 | template 39 | struct select_base 40 | { 41 | #ifdef INT8_MIN 42 | enum : bool { has_int8= true }; 43 | using UI8= uint8_t; 44 | #else 45 | enum : bool { has_int8= false }; 46 | using UI8= void; 47 | #endif 48 | #ifdef INT16_MIN 49 | enum : bool { has_int16= true }; 50 | using UI16= uint16_t; 51 | #else 52 | enum : bool { has_int16= false }; 53 | using UI16= void; 54 | #endif 55 | #ifdef INT32_MIN 56 | enum : bool { has_int32= true }; 57 | using UI32= uint32_t; 58 | #else 59 | enum : bool { has_int32= false }; 60 | using UI32= void; 61 | #endif 62 | 63 | using type= 64 | if_else_t< has_int8 && (N<=8), UI8, 65 | if_else_t< has_int16 && (N<=16), UI16, 66 | if_else_t< has_int32 && (N<=32), UI32, 67 | unsigned long long > > >; 68 | }; // struct select_base 69 | 70 | 71 | template 72 | using select_base_t= typename select_base::type; 73 | 74 | 75 | } // namespace detail 76 | } // namespace Bitset2 77 | 78 | 79 | 80 | 81 | 82 | #endif // BITSET2_SELECT_BASE_T_CB_HPP 83 | -------------------------------------------------------------------------------- /detail/ullong2array.hpp: -------------------------------------------------------------------------------- 1 | // BITSET2 2 | // 3 | // Copyright Claas Bontus 4 | // 5 | // Use, modification and distribution is subject to the 6 | // Boost Software License, Version 1.0. (See accompanying 7 | // file LICENSE.txt or copy at 8 | // http://www.boost.org/LICENSE_1_0.txt) 9 | // 10 | // Project home: https://github.com/ClaasBontus/bitset2 11 | // 12 | 13 | 14 | #ifndef BITSET2_ULLONG2ARRAY_CB_HPP 15 | #define BITSET2_ULLONG2ARRAY_CB_HPP 16 | 17 | #include "bit_chars.hpp" 18 | 19 | 20 | namespace Bitset2 21 | { 22 | namespace detail 23 | { 24 | 25 | 26 | /// \brief Takes a variable 'v' of type LRGST_t 27 | /// (unsigned long long or unsigned __int128) 28 | /// and returns a std::array 'a' equivalent to v. 'a' represents 29 | /// an N bit bitset2 with base_t == T. 30 | template 31 | struct lrgst2array 32 | { 33 | using base_t= T; 34 | using b_c= bit_chars; 35 | using LRGST_t= typename b_c::LRGST_t; 36 | 37 | enum : size_t 38 | { n_bits= N 39 | , base_t_n_bits= b_c::base_t_n_bits 40 | , lrgst_n_bist= b_c::lrgst_n_bist 41 | , n_array= b_c::n_array 42 | , centrl_i= ce_min( (lrgst_n_bist-1) / base_t_n_bits, n_array - 1 ) 43 | , n_empty_vals= n_array - centrl_i - 1 44 | }; 45 | 46 | enum : base_t 47 | { hgh_bit_pattern= b_c::hgh_bit_pattern 48 | , use_pattern= (n_empty_vals==0) ? hgh_bit_pattern : base_t(~base_t(0)) 49 | }; 50 | 51 | using array_t= typename h_types::template array_t; 52 | 53 | constexpr 54 | array_t 55 | operator()( LRGST_t v ) const noexcept 56 | { 57 | array_t retval= (detail::gen_empty_array)(); 58 | size_t c= 0; 59 | for( ; c < centrl_i; ++c ) 60 | { 61 | retval[c]= base_t(v); 62 | v = ce_right_shift( v, base_t_n_bits ); 63 | } 64 | retval[c]= base_t( v & use_pattern ); 65 | return retval; 66 | } 67 | }; // struct lrgst2array 68 | 69 | 70 | } // namespace detail 71 | } // namespace Bitset2 72 | 73 | 74 | 75 | 76 | #endif // BITSET2_ULLONG2ARRAY_CB_HPP 77 | -------------------------------------------------------------------------------- /tests/bench01.cpp: -------------------------------------------------------------------------------- 1 | // BITSET2 2 | // 3 | // Copyright Claas Bontus 4 | // 5 | // Use, modification and distribution is subject to the 6 | // Boost Software License, Version 1.0. (See accompanying 7 | // file LICENSE.txt or copy at 8 | // http://www.boost.org/LICENSE_1_0.txt) 9 | // 10 | // Project home: https://github.com/ClaasBontus/bitset2 11 | // 12 | 13 | 14 | #include "../bitset2.hpp" 15 | #include "gen_randoms.hpp" 16 | #include 17 | #include 18 | #include 19 | 20 | 21 | 22 | using ULLONG= unsigned long long; 23 | 24 | template 25 | using t1= Bitset2::bitset2; 26 | 27 | template 28 | using vec_t= std::vector >; 29 | 30 | 31 | constexpr size_t n_loops= 1000000; 32 | 33 | template 34 | vec_t 35 | gen_bs_vec( size_t n ) 36 | { 37 | std::vector > ret_val; 38 | gen_random_bitset2 gen_rand; 39 | ret_val.reserve( n ); 40 | for( size_t c= 0; c < n; ++c ) ret_val.push_back( gen_rand() ); 41 | 42 | return ret_val; 43 | } // gen_bs_vec 44 | 45 | 46 | template 47 | void 48 | apply_or_equal( vec_t & v1, vec_t const & v2 ) 49 | { 50 | auto it2= v2.begin(); 51 | for( auto & bs: v1 ) bs |= *(it2++); 52 | } // apply_or_equal 53 | 54 | 55 | template 56 | std::array & 57 | rm_const( std::array const & a ) 58 | { return const_cast &>(a); } 59 | 60 | 61 | template 62 | void 63 | array_or_equal( vec_t & v1, vec_t const & v2 ) 64 | { 65 | auto const n_array= v1[0].data().size(); 66 | auto it2= v2.begin(); 67 | for( auto & bs: v1 ) 68 | { 69 | auto & a1= rm_const( bs.data() ); 70 | auto & a2= it2->data(); 71 | for( size_t c= 0; c < n_array; ++c ) a1[c] |= a2[c]; 72 | 73 | ++it2; 74 | } 75 | } 76 | 77 | 78 | int main() 79 | { 80 | auto const vec1= gen_bs_vec<2048>( 128 ); 81 | auto const vec2= gen_bs_vec<2048>( 128 ); 82 | 83 | std::cout << "Running computations\n"; 84 | 85 | auto const t1 = std::chrono::high_resolution_clock::now(); 86 | 87 | auto v1= vec1; 88 | for( size_t c= 0; c < n_loops; ++c ) 89 | { 90 | v1= vec1; 91 | apply_or_equal( v1, vec2 ); 92 | } 93 | 94 | auto const t2 = std::chrono::high_resolution_clock::now(); 95 | 96 | auto v1a= vec1; 97 | for( size_t c= 0; c < n_loops; ++c ) 98 | { 99 | v1a= vec1; 100 | array_or_equal( v1a, vec2 ); 101 | } 102 | 103 | auto const t3 = std::chrono::high_resolution_clock::now(); 104 | 105 | assert( v1 == v1a ); 106 | 107 | for( size_t c= 0; c < n_loops; ++c ) 108 | { 109 | v1a= vec1; 110 | array_or_equal( v1a, vec2 ); 111 | } 112 | 113 | auto const t4 = std::chrono::high_resolution_clock::now(); 114 | 115 | for( size_t c= 0; c < n_loops; ++c ) 116 | { 117 | v1= vec1; 118 | apply_or_equal( v1, vec2 ); 119 | } 120 | 121 | auto const t5 = std::chrono::high_resolution_clock::now(); 122 | const std::chrono::duration dt21 = t2 -t1; 123 | const std::chrono::duration dt32 = t3 -t2; 124 | const std::chrono::duration dt43 = t4 -t3; 125 | const std::chrono::duration dt54 = t5 -t4; 126 | 127 | std::cout << "dt21= " << dt21.count() * 1.0e3 << "ms\n"; 128 | std::cout << "dt32= " << dt32.count() * 1.0e3 << "ms\n"; 129 | std::cout << "dt43= " << dt43.count() * 1.0e3 << "ms\n"; 130 | std::cout << "dt54= " << dt54.count() * 1.0e3 << "ms\n"; 131 | } // main 132 | -------------------------------------------------------------------------------- /tests/counter128.cpp: -------------------------------------------------------------------------------- 1 | // BITSET2 2 | // 3 | // Copyright Claas Bontus 4 | // 5 | // Use, modification and distribution is subject to the 6 | // Boost Software License, Version 1.0. (See accompanying 7 | // file LICENSE.txt or copy at 8 | // http://www.boost.org/LICENSE_1_0.txt) 9 | // 10 | // Project home: https://github.com/ClaasBontus/bitset2 11 | // 12 | 13 | 14 | 15 | #include 16 | #include "bitset2.hpp" 17 | 18 | 19 | int main() 20 | { 21 | Bitset2::bitset2<128> c; 22 | constexpr Bitset2::bitset2<128> tst{ 0xFFFFFFFFull }; 23 | 24 | for( ;; ++c ) 25 | { 26 | if( ( c & tst) == tst ) 27 | std::cout << c.to_hex_string() << "\n"; 28 | } 29 | } // main 30 | -------------------------------------------------------------------------------- /tests/example01.cpp: -------------------------------------------------------------------------------- 1 | // BITSET2 2 | // 3 | // Copyright Claas Bontus 4 | // 5 | // Use, modification and distribution is subject to the 6 | // Boost Software License, Version 1.0. (See accompanying 7 | // file LICENSE.txt or copy at 8 | // http://www.boost.org/LICENSE_1_0.txt) 9 | // 10 | // Project home: https://github.com/ClaasBontus/bitset2 11 | // 12 | 13 | #include 14 | #include 15 | #include 16 | #include "bitset2.hpp" 17 | 18 | template 19 | using BS2= Bitset2::bitset2; 20 | 21 | int main() 22 | { 23 | using bs_128= BS2<128>; 24 | using base_t_128= bs_128::base_t; 25 | constexpr std::array 26 | ar1{{ ~(base_t_128(0)), base_t_128(0xFEDCBA) }}; 27 | constexpr bs_128 b1{ ar1 }; 28 | constexpr auto b1_add= b1 + b1; 29 | constexpr auto b1_shft= b1 << 1; // binary shift 30 | static_assert( b1_add == b1_shft, "" ); 31 | 32 | std::cout << b1.to_hex_string() // 0000000000fedcbaffffffffffffffff 33 | << "\n" 34 | << b1_add.to_hex_string() // 0000000001fdb975fffffffffffffffe 35 | << "\n"; 36 | 37 | BS2<12> b2; 38 | for( size_t c= 0; c < 12; c += 2 ) b2[c]= true; 39 | auto b3= ~b2; 40 | std::cout << b2 << "\n"; // 010101010101 41 | std::cout << b2.flip() << "\n"; // 101010101010 42 | assert( b2 == b3 ); 43 | 44 | BS2<7> const b4{ "1110000" }; 45 | auto const b5= Bitset2::rotate_left( b4, 3 ); 46 | std::cout << b4 << "\n" // 1110000 47 | << b5 << "\n"; // 0000111 48 | 49 | BS2<7> b6{ "1010010" }; 50 | b6.reverse(); 51 | std::cout << b6 << "\n"; // 0100101 52 | } // main 53 | -------------------------------------------------------------------------------- /tests/gen_randoms.hpp: -------------------------------------------------------------------------------- 1 | // BITSET2 2 | // 3 | // Copyright Claas Bontus 4 | // 5 | // Use, modification and distribution is subject to the 6 | // Boost Software License, Version 1.0. (See accompanying 7 | // file LICENSE.txt or copy at 8 | // http://www.boost.org/LICENSE_1_0.txt) 9 | // 10 | // Project home: https://github.com/ClaasBontus/bitset2 11 | // 12 | 13 | 14 | #ifndef BITSET2_GEN_RANDOMS_CB_HPP 15 | #define BITSET2_GEN_RANDOMS_CB_HPP 16 | 17 | #include "../bitset2.hpp" 18 | #include 19 | #include 20 | #include 21 | #include 22 | 23 | 24 | 25 | template 26 | class gen_randoms 27 | { 28 | public: 29 | gen_randoms( T max_val, T min_val= 0 ) 30 | : m_generator( std::random_device{}() ) 31 | , m_distri( min_val, max_val ) 32 | {} 33 | // 34 | T 35 | operator()() 36 | { return m_distri( m_generator ); } 37 | // 38 | private: 39 | std::mt19937 m_generator; 40 | std::uniform_int_distribution m_distri; 41 | }; // class gen_randoms 42 | 43 | 44 | 45 | #ifdef __SIZEOF_INT128__ 46 | template<> 47 | class gen_randoms 48 | { 49 | public: 50 | using T = unsigned __int128; 51 | 52 | gen_randoms( T max_val ) 53 | : m_max_lft( uint64_t(max_val >> 64) ) 54 | , m_max_rgt( uint64_t(max_val & uint64_t(-1)) ) 55 | , m_generator( std::random_device{}() ) 56 | , m_distri_lft( 0, m_max_lft ) 57 | , m_distri_rgt( 0, m_max_rgt ) 58 | {} 59 | // 60 | T 61 | operator()() 62 | { return ( T( m_distri_lft(m_generator) ) << 64 ) + T( m_distri_rgt(m_generator) ); } 63 | // 64 | private: 65 | uint64_t m_max_lft, m_max_rgt; 66 | std::mt19937 m_generator; 67 | std::uniform_int_distribution m_distri_lft; 68 | std::uniform_int_distribution m_distri_rgt; 69 | }; // class gen_randoms 70 | #endif 71 | 72 | 73 | 74 | /// Generate N-bit sized bitset2 randomly 75 | template 76 | class gen_random_bitset2 77 | { 78 | // 79 | enum : size_t 80 | { base_t_n_bits= sizeof(T) * CHAR_BIT 81 | , div_val= N / base_t_n_bits 82 | , mod_val= N % base_t_n_bits 83 | , n_words= mod_val ? div_val + 1 : div_val 84 | }; 85 | enum : T 86 | { max_ullong= T(~T(0)) 87 | , hgh_bit_pattern= 88 | N == 0 ? T(0) 89 | : mod_val == 0 90 | ? max_ullong 91 | : max_ullong >> T(base_t_n_bits-mod_val) 92 | }; 93 | // 94 | using arr_t= std::array; 95 | // 96 | public: 97 | using b_t= Bitset2::bitset2; 98 | // 99 | gen_random_bitset2() 100 | : m_gen{ gen_generators() } 101 | {} 102 | // 103 | b_t 104 | operator()() 105 | { 106 | arr_t a; 107 | for( size_t c= 0; c < n_words; ++c ) a[c]= m_gen[c](); 108 | return b_t( a ); 109 | } 110 | // 111 | private: 112 | using gen_rand_t= gen_randoms; 113 | 114 | std::vector m_gen; 115 | // 116 | std::vector 117 | gen_generators() 118 | { 119 | std::vector ret_val; 120 | 121 | if( n_words > 0 ) 122 | { 123 | ret_val.reserve( n_words ); 124 | for( size_t c= 0; c < n_words - 1; ++c ) 125 | ret_val.push_back( gen_rand_t{ max_ullong } ); 126 | ret_val.push_back( gen_rand_t{ hgh_bit_pattern } ); 127 | } 128 | 129 | return ret_val; 130 | } 131 | }; // gen_random_bitset2 132 | 133 | 134 | 135 | 136 | #endif // BITSET2_GEN_RANDOMS_CB_HPP 137 | -------------------------------------------------------------------------------- /tests/gray_code.cpp: -------------------------------------------------------------------------------- 1 | // BITSET2 2 | // 3 | // Copyright Claas Bontus 4 | // 5 | // Use, modification and distribution is subject to the 6 | // Boost Software License, Version 1.0. (See accompanying 7 | // file LICENSE.txt or copy at 8 | // http://www.boost.org/LICENSE_1_0.txt) 9 | // 10 | // Project home: https://github.com/ClaasBontus/bitset2 11 | // 12 | 13 | 14 | #include "../bitset2.hpp" 15 | #include 16 | #include 17 | 18 | 19 | template 20 | constexpr 21 | Bitset2::bitset2 22 | binary_to_gray( Bitset2::bitset2 const &bs ) 23 | { return bs ^ (bs >> 1); } 24 | 25 | 26 | template 27 | constexpr 28 | Bitset2::bitset2 29 | gray_to_binary( Bitset2::bitset2 bs ) 30 | { 31 | Bitset2::bitset2 mask= bs >> 1; 32 | for( ; !mask.none(); mask >>= 1 ) bs ^= mask; 33 | return bs; 34 | } // gray_to_binary 35 | 36 | 37 | int main() 38 | { 39 | using ULLONG= unsigned long long; 40 | constexpr std::array arr_01a{{ 0xFEFDFCFBFAF9F8F7ull, 1ull }}; 41 | constexpr Bitset2::bitset2<129> bs_01a{ arr_01a }; 42 | constexpr auto gray_01a= binary_to_gray( bs_01a ); 43 | constexpr auto bin_01a= gray_to_binary( gray_01a ); 44 | 45 | static_assert( bs_01a == bin_01a ); 46 | 47 | std::cout << bs_01a << '\n' << gray_01a << '\n'; 48 | 49 | return 0; 50 | } // main 51 | -------------------------------------------------------------------------------- /tests/mk.sh: -------------------------------------------------------------------------------- 1 | cc=g++-12 2 | #cc=clang++ 3 | 4 | std=c++20 5 | 6 | p=test_ullong2array 7 | echo "Compiling $p" 8 | $cc -O2 -Wall -Wextra -std=$std -I.. -I../detail -fdiagnostics-color=auto $p.cpp -o $p 9 | 10 | p=tests01 11 | echo "Compiling $p" 12 | $cc -O2 -Wall -Wextra -std=$std -I.. -fdiagnostics-color=auto $p.cpp -o $p 13 | 14 | p=gray_code 15 | echo "Compiling $p" 16 | $cc -O2 -Wall -Wextra -std=$std -I.. -I../detail -fdiagnostics-color=auto $p.cpp -o $p 17 | 18 | p=test_nonconst_constexpr01 19 | echo "Compiling $p" 20 | $cc -O2 -Wall -Wextra -std=$std -I.. -I../detail -fdiagnostics-color=auto $p.cpp -o $p 21 | 22 | p=test_array2array 23 | echo "Compiling $p" 24 | $cc -O2 -Wall -Wextra -std=$std -I.. -I../detail -fdiagnostics-color=auto $p.cpp -o $p 25 | 26 | p=test_bitset2_01 27 | echo "Compiling $p" 28 | $cc -O2 -Wall -Wextra -Wno-unused-but-set-variable -std=$std -I.. -fdiagnostics-color=auto $p.cpp -o $p 29 | 30 | p=test_bitset2_02 31 | echo "Compiling $p" 32 | $cc -O2 -Wall -Wextra -std=$std -I.. -fdiagnostics-color=auto $p.cpp -o $p 33 | 34 | p=counter128 35 | echo "Compiling $p" 36 | $cc -O2 -Wall -Wextra -std=$std -I.. -fdiagnostics-color=auto $p.cpp -o $p 37 | 38 | p=bench01 39 | echo "Compiling $p" 40 | $cc -O2 -Wall -Wextra -std=$std -I.. -fdiagnostics-color=auto -D_GLIBCXX_USE_NANOSLEEP $p.cpp -o $p 41 | 42 | p=example01 43 | echo "Compiling $p" 44 | $cc -O2 -Wall -Wextra -std=$std -I.. -fdiagnostics-color=auto $p.cpp -o $p 45 | -------------------------------------------------------------------------------- /tests/test_array2array.cpp: -------------------------------------------------------------------------------- 1 | // BITSET2 2 | // 3 | // Copyright Claas Bontus 4 | // 5 | // Use, modification and distribution is subject to the 6 | // Boost Software License, Version 1.0. (See accompanying 7 | // file LICENSE.txt or copy at 8 | // http://www.boost.org/LICENSE_1_0.txt) 9 | // 10 | // Project home: https://github.com/ClaasBontus/bitset2 11 | // 12 | 13 | 14 | #include "array2array.hpp" 15 | #include "gen_randoms.hpp" 16 | #include 17 | #include 18 | #include 19 | 20 | 21 | 22 | constexpr size_t n_loops= 100000; 23 | 24 | 25 | 26 | template 27 | void 28 | fwd_bckwd() 29 | { 30 | constexpr size_t bits_T1= sizeof(T1) * CHAR_BIT; 31 | constexpr size_t bits_T2= sizeof(T2) * CHAR_BIT; 32 | 33 | constexpr size_t t_n1= 8, s_n1= 1; 34 | constexpr size_t t_n2= 24, s_n2= 3; 35 | 36 | using a2a_t1a= Bitset2::detail::array2array; 37 | using a2a_t1b= Bitset2::detail::array2array; 38 | using a2a_t2a= Bitset2::detail::array2array; 39 | using a2a_t2b= Bitset2::detail::array2array; 40 | 41 | using a2a_t3a= Bitset2::detail::array2array; 42 | using a2a_t3b= Bitset2::detail::array2array; 43 | using a2a_t4a= Bitset2::detail::array2array; 44 | using a2a_t4b= Bitset2::detail::array2array; 45 | 46 | gen_random_bitset2 gen_rand1a; 47 | gen_random_bitset2 gen_rand1b; 48 | 49 | gen_random_bitset2 gen_rand2a; 50 | gen_random_bitset2 gen_rand2b; 51 | 52 | for( size_t ct= 0; ct < n_loops; ++ct ) 53 | { 54 | // if( (ct+1) % 1000 == 0 ) std::cout << (ct+1) << '\n'; 55 | 56 | auto const bs1= gen_rand1a(); 57 | auto const a1a= a2a_t1a()( ~T2(0), bs1.data() ); 58 | auto const a1b= a2a_t1b()( ~T1(0), a1a ); 59 | assert( bs1.data() == a1b ); 60 | 61 | auto const bs2= gen_rand1b(); 62 | auto const a2a= a2a_t2a()( ~T1(0), bs2.data() ); 63 | auto const a2b= a2a_t2b()( ~T2(0), a2a ); 64 | assert( bs2.data() == a2b ); 65 | 66 | auto const bs3= gen_rand2a(); 67 | auto const a3a= a2a_t3a()( ~T2(0), bs3.data() ); 68 | auto const a3b= a2a_t3b()( T1(T1(~T1(0)) >> (bits_T1/2)), a3a ); 69 | assert( bs3.data() == a3b ); 70 | 71 | auto const bs4= gen_rand2b(); 72 | auto const a4a= a2a_t4a()( ~T1(0), bs4.data() ); 73 | auto const a4b= a2a_t4b()( T2(T2(~T2(0)) >> (bits_T2/2)), a4a ); 74 | assert( bs4.data() == a4b ); 75 | } // for ct 76 | } // fwd_bckwd 77 | 78 | 79 | int main() 80 | { 81 | 82 | constexpr size_t t_n1= 2, s_n1= 2; 83 | 84 | std::cout << Bitset2::detail::array2array::h_all_set 85 | << " " 86 | // << Bitset2::detail::array2array::h_all_set 87 | // << " " 88 | << Bitset2::detail::array2array::h_all_set 89 | << " " 90 | << Bitset2::detail::array2array::h_all_set 91 | << " " 92 | << Bitset2::detail::array2array::h_all_set 93 | << " " 94 | << Bitset2::detail::array2array::h_all_set 95 | << '\n'; 96 | 97 | std::cout << " 8 <-> 64\n"; 98 | fwd_bckwd(); 99 | std::cout << "16 <-> 64\n"; 100 | fwd_bckwd(); 101 | std::cout << "32 <-> 64\n"; 102 | fwd_bckwd(); 103 | 104 | std::cout << "\n 8 <-> 32\n"; 105 | fwd_bckwd(); 106 | std::cout << "16 <-> 32\n"; 107 | fwd_bckwd(); 108 | 109 | std::cout << "\n 8 <-> 16\n"; 110 | fwd_bckwd(); 111 | } // main 112 | -------------------------------------------------------------------------------- /tests/test_bitset2_01.cpp: -------------------------------------------------------------------------------- 1 | // BITSET2 2 | // 3 | // Copyright Claas Bontus 4 | // 5 | // Use, modification and distribution is subject to the 6 | // Boost Software License, Version 1.0. (See accompanying 7 | // file LICENSE.txt or copy at 8 | // http://www.boost.org/LICENSE_1_0.txt) 9 | // 10 | // Project home: https://github.com/ClaasBontus/bitset2 11 | // 12 | 13 | 14 | #include 15 | #include 16 | #include 17 | #include "bitset2.hpp" 18 | 19 | 20 | template 21 | constexpr 22 | bool 23 | is_subset_of( Bitset2::bitset2 const &bs1, 24 | Bitset2::bitset2 const &bs2 ) noexcept 25 | { 26 | using base_t= T; 27 | return Bitset2::zip_fold_and( bs1, bs2, 28 | []( base_t v1, base_t v2 ) noexcept 29 | { return (v1 & ~v2) == 0; } ); 30 | } // is_subset_of 31 | 32 | 33 | template 34 | constexpr 35 | bool 36 | unequal( Bitset2::bitset2 const &bs1, 37 | Bitset2::bitset2 const &bs2 ) noexcept 38 | { 39 | using base_t= T; 40 | return Bitset2::zip_fold_or( bs1, bs2, 41 | []( base_t v1, base_t v2 ) noexcept 42 | { return v1 != v2; } ); 43 | } // unequal 44 | 45 | 46 | 47 | int main() 48 | { 49 | using namespace Bitset2; 50 | using ULLONG= unsigned long long; 51 | 52 | constexpr bitset2<32> b1; 53 | constexpr auto v1= b1.to_ullong(); 54 | constexpr auto b1_n= ~b1; 55 | constexpr bool b1_n_none= b1_n.none(); 56 | constexpr bool b1_n_all= b1_n.all(); 57 | constexpr bool b1_n_any= b1_n.any(); 58 | 59 | bitset2<63> b_63; 60 | bitset2<64> b_64; 61 | bitset2<65> b_65; 62 | auto b1a= b1; 63 | b1a.set(); 64 | b_63.set(); 65 | b_64.set(); 66 | b_65.set(); 67 | 68 | std::bitset<65> sb1; 69 | auto sb2= std::bitset<32>( b1 ); 70 | sb1[64]= 1; 71 | 72 | bitset2<65> b2( sb1 ); 73 | 74 | std::cout << v1 << "\n" 75 | << b2 << "\n" 76 | << sb2 << "\n" 77 | << b1_n << "\n" 78 | << "b1.none()= " << b1.none() << " " 79 | << "b1.any()= " << b1.any() << " " 80 | << "b1.all()= " << b1.all() << "\n" 81 | << "b1a.none()= " << b1a.none() << " " 82 | << "b1a.any()= " << b1a.any() << " " 83 | << "b1a.all()= " << b1a.all() << "\n" 84 | << "b2.none()= " << b2.none() << " " 85 | << "b2.any()= " << b2.any() << " " 86 | << "b2.all()= " << b2.all() << "\n" 87 | << "b1_n.none()= " << b1_n_none << " " 88 | << "b1_n.any()= " << b1_n_any << " " 89 | << "b1_n.all()= " << b1_n_all << "\n" 90 | << "b_63.all()= " << b_63.all() << " " 91 | << "b_64.all()= " << b_64.all() << " " 92 | << "b_65.all()= " << b_65.all() << "\n"; 93 | std::cout << "b_63.flip()= " << b_63.flip() << "\n" 94 | << "b_64.flip()= " << b_64.flip() << "\n" 95 | << "b_65.flip()= " << b_65.flip() << "\n"; 96 | std::cout << "b_63.flip()= " << b_63.flip() << "\n" 97 | << "b_64.flip()= " << b_64.flip() << "\n" 98 | << "b_65.flip()= " << b_65.flip() << "\n"; 99 | std::cout << "b_63.reset()= " << b_63.reset() << "\n" 100 | << "b_64.reset()= " << b_64.reset() << "\n" 101 | << "b_65.reset()= " << b_65.reset() << "\n"; 102 | 103 | detail::bit_chars<4,ULLONG> bc1; 104 | detail::bit_chars<64,ULLONG> bc2; 105 | detail::bit_chars<65,ULLONG> bc3; 106 | detail::bit_chars<63,ULLONG> bc4; 107 | 108 | bitset2<64> lbp1( bc1.low_bit_pattern ); 109 | bitset2<64> lbp2( bc2.low_bit_pattern ); 110 | bitset2<64> lbp3( bc3.low_bit_pattern ); 111 | bitset2<64> lbp4( bc4.low_bit_pattern ); 112 | 113 | std::cout << bc1.low_bit_pattern << " " << bc1.mod_val << "\n" 114 | << " " << lbp1 << "\n" 115 | << bc2.low_bit_pattern << " " << bc2.mod_val << "\n" 116 | << " " << lbp2 << "\n" 117 | << bc3.low_bit_pattern << " " << bc3.mod_val << "\n" 118 | << " " << lbp3 << "\n" 119 | << bc4.low_bit_pattern << " " << bc4.mod_val << "\n" 120 | << " " << lbp4 << "\n"; 121 | 122 | constexpr 123 | std::array ar1{{ ~(0ull), 1 }}; 124 | 125 | constexpr 126 | auto s_ar1= detail::array_ops<128,ULLONG>( 63 ).shift_left( ar1 ); 127 | 128 | std::cout << "\n" << ar1[1] << " " << ar1[0] << "\n"; 129 | std::cout << "\n" << s_ar1[1] << " " << s_ar1[0] << "\n"; 130 | 131 | bitset2<63> bc5{ 1ull }; 132 | bitset2<64> bc6{ 1ull }; 133 | bitset2<65> bc7{ 1ull }; 134 | constexpr bitset2<63> bc5a{ 1ull }; 135 | constexpr bitset2<64> bc6a{ 1ull }; 136 | constexpr bitset2<65> bc7a{ 1ull }; 137 | constexpr bitset2<127> bc8a{ 1ull }; 138 | constexpr bitset2<128> bc9a{ 1ull }; 139 | constexpr bitset2<129> bc10a{ 1ull }; 140 | constexpr auto bc5b= bc5a << 62; 141 | constexpr auto bc6b= bc6a << 63; 142 | constexpr auto bc7b= bc7a << 64; 143 | constexpr auto bc8b= bc8a << 62; 144 | constexpr auto bc8c= bc8a << 63; 145 | constexpr auto bc8d= bc8a << 64; 146 | constexpr auto bc9b= bc9a << 62; 147 | constexpr auto bc9c= bc9a << 63; 148 | constexpr auto bc9d= bc9a << 64; 149 | constexpr auto bc10b= bc10a << 62; 150 | constexpr auto bc10c= bc10a << 63; 151 | constexpr auto bc10d= bc10a << 64; 152 | std::cout << " " << bc8b << "\n " << bc8c << "\n " << bc8d << "\n"; 153 | std::cout << " " << bc9b << "\n " << bc9c << "\n " << bc9d << "\n"; 154 | std::cout << bc10b << "\n" << bc10c << "\n" << bc10d << "\n"; 155 | std::cout << bc5b << " " << bc6b << " " << bc7b << "\n"; 156 | for( size_t c= 0; c < 66; ++c ) 157 | { 158 | std::cout << bc5 << " " << bc6 << " " << bc7 << "\n"; 159 | bc5 <<= 1; bc6 <<= 1; bc7 <<= 1; 160 | } 161 | 162 | std::cout << "\n"; 163 | constexpr auto bc5c= bc5b >> 62; 164 | constexpr auto bc6c= bc6b >> 63; 165 | constexpr auto bc7c= bc7b >> 64; 166 | std::cout << bc5c << " " << bc6c << " " << bc7c << "\n"; 167 | 168 | constexpr auto bc5d= bc5a | bc5b; 169 | constexpr auto bc5e= bc5d & bc5a; 170 | constexpr auto bc5f= bc5d & bc5b; 171 | constexpr auto bc5g= bc5a ^ bc5b; 172 | constexpr auto bc5h= bc5d ^ bc5a; 173 | constexpr auto bc5i= bc5d ^ bc5b; 174 | constexpr auto bc5j= bc5a << 1; 175 | std::cout << "\n" << bc5a << " |\n" << bc5b << " =\n" << bc5d << "\n"; 176 | std::cout << "\n" << bc5d << " &\n" << bc5a << " =\n" << bc5e << "\n"; 177 | std::cout << "\n" << bc5d << " &\n" << bc5b << " =\n" << bc5f << "\n"; 178 | std::cout << "\n" << bc5a << " ^\n" << bc5b << " =\n" << bc5g << "\n"; 179 | std::cout << "\n" << bc5d << " ^\n" << bc5a << " =\n" << bc5h << "\n"; 180 | std::cout << "\n" << bc5d << " ^\n" << bc5b << " =\n" << bc5i << "\n"; 181 | std::cout << "\n" << bc5a << " << 1 = " << bc5j << "\n"; 182 | 183 | constexpr auto bc7d= bc7a | bc7b; 184 | constexpr auto bc7e= bc7d & bc7a; 185 | constexpr auto bc7f= bc7d & bc7b; 186 | constexpr auto bc7g= bc7a ^ bc7b; 187 | constexpr auto bc7h= bc7d ^ bc7a; 188 | constexpr auto bc7i= bc7d ^ bc7b; 189 | std::cout << "\n" << bc7a << " |\n" << bc7b << " =\n" << bc7d << "\n"; 190 | std::cout << "\n" << bc7d << " &\n" << bc7a << " =\n" << bc7e << "\n"; 191 | std::cout << "\n" << bc7d << " &\n" << bc7b << " =\n" << bc7f << "\n"; 192 | std::cout << "\n" << bc7a << " ^\n" << bc7b << " =\n" << bc7g << "\n"; 193 | std::cout << "\n" << bc7d << " ^\n" << bc7a << " =\n" << bc7h << "\n"; 194 | std::cout << "\n" << bc7d << " ^\n" << bc7b << " =\n" << bc7i << "\n"; 195 | 196 | constexpr auto bc5a_f= ~bc5a; 197 | constexpr auto bc5d_f= ~bc5d; 198 | constexpr auto bc7a_f= ~bc7a; 199 | constexpr auto bc7d_f= ~bc7d; 200 | std::cout << "\n~" << bc5a << " =\n " << bc5a_f << "\n"; 201 | std::cout << "\n~" << bc5d << " =\n " << bc5d_f << "\n"; 202 | std::cout << "\n~" << bc7a << " =\n " << bc7a_f << "\n"; 203 | std::cout << "\n~" << bc7d << " =\n " << bc7d_f << "\n"; 204 | std::cout << "\n"; 205 | bitset2<65> bc11a{ 1ull }; 206 | bitset2<65> bc11b{ 1ull }; 207 | bc11b <<= 64; 208 | bc11b |= ( bc11a << 1 ); 209 | std::cout << bc11b << "\n"; 210 | bc11b >>= 1; 211 | std::cout << bc11b << "\n"; 212 | std::cout << bc11b.to_string( '.', 'x' ) << "\n"; 213 | 214 | constexpr auto n_5a= bc5a.count(); 215 | constexpr auto n_5a_f= bc5a_f.count(); 216 | constexpr auto n_7a= bc7a.count(); 217 | constexpr auto n_7a_f= bc7a_f.count(); 218 | std::cout << "count( " << bc5a << " )= " << n_5a << "\n"; 219 | std::cout << "count( " << bc5a_f << " )= " << n_5a_f << "\n"; 220 | std::cout << "count( " << bc7a << " )= " << n_7a << "\n"; 221 | std::cout << "count( " << bc7a_f << " )= " << n_7a_f << "\n"; 222 | std::cout << "\n"; 223 | b_63.reset(); 224 | b_64.reset(); 225 | b_65.reset(); 226 | auto b_63a= b_63; 227 | auto b_64a= b_64; 228 | auto b_65a= b_65; 229 | for( size_t c= 0; c < 64; c += 2 ) 230 | { 231 | if( c < 63 ) b_63[c]= true; 232 | if( c < 64 ) b_64[c]= true; 233 | if( c < 65 ) b_65[c]= true; 234 | b_63a[c/2]= true; b_64a[c/2]= true; b_65a[c/2]= true; 235 | } 236 | std::cout << "Hash values:\n"; 237 | std::cout << " " << b_63 << " " << std::hash>()( b_63 ) << "\n" 238 | << " " << b_64 << " " << std::hash>()( b_64 ) << "\n" 239 | << b_65 << " " << std::hash>()( b_65 ) << "\n"; 240 | 241 | bitset2<0> b_0a, b_0b; 242 | constexpr auto bl_c7d= bc7d == bc7d; 243 | std::cout << "\n" << ( b_63 == b_63 ) << " " 244 | << ( b_64 == b_64 ) << " " 245 | << ( b_65 == b_65 ) << "\n" 246 | << ( b_63 != b_63a ) << " " 247 | << ( b_64 != b_64a ) << " " 248 | << ( b_65 != b_65a ) << " " 249 | << bl_c7d << "\n" 250 | << ( b_0a == b_0b ) << "\n"; 251 | 252 | constexpr bitset2<65> bs33a( 0xFFFFFFFFFFFFFFFFull ); 253 | // constexpr auto bs33b= ( bs33a << 1 ); 254 | //constexpr 255 | auto bs33a_v= bs33a.to_ulong(); 256 | std::cout << bs33a << " == " << bs33a_v << " == " << bs33a.to_hex_string() << "\n"; 257 | // auto bs33b_v= bs33b.to_ulong(); // throws 258 | // std::cout << bs33b << " == " << bs33b_v << "\n"; 259 | 260 | bitset2<63> bc2_63{ 0x700000000000000Eull }; 261 | constexpr bitset2<63> bc2_63a{ 0x700000000000000Eull }; 262 | constexpr auto bc2_63b= rotate_right( bc2_63a, 5 ); 263 | bitset2<65> bc2_65{ 0x700000000000000Eull }; 264 | constexpr bitset2<65> bc2_65a{ 0x700000000000000Eull }; 265 | constexpr auto bc2_65b= rotate_right( bc2_65a, 5 ); 266 | std::cout << " bc2_63= " << bc2_63 267 | << " == " << bc2_63.to_hex_string() << "\n"; 268 | bc2_63.rotate_left( 5 ); 269 | std::cout << "rot_left( bc2_63, 5) = " << bc2_63 << "\n"; 270 | std::cout << "rot_right( bc2_63a,5)= " << bc2_63b << "\n"; 271 | 272 | std::cout << " bc2_65= " << bc2_65 273 | << " == " << bc2_65.to_hex_string() << "\n"; 274 | bc2_65.rotate_left( 5 ); 275 | std::cout << "rot_left( bc2_65, 5) = " << bc2_65 << "\n"; 276 | std::cout << "rot_right( bc2_65a,5)= " << bc2_65b << "\n"; 277 | 278 | constexpr auto add_b5a= bc5a + bc5j; 279 | constexpr auto add_b5b= bc5a + bc5a; 280 | std::cout << bc5a << " +\n" << bc5j << " =\n" << add_b5a << "\n"; 281 | std::cout << bc5a << " +\n" << bc5a << " =\n" << add_b5b << "\n"; 282 | 283 | constexpr std::array arr_add_01a{{ 0xFFFFFFFFFFFFFFFFull, 0ull }}; 284 | std::array arr_add_01ap{{ 0xFFFFFFFFFFFFFFFFull, 0ull }}; 285 | constexpr std::array arr_add_01b{{ 0xFFFFFFFFFFFFFFFFull, 1ull }}; 286 | constexpr bitset2<64> b_a_01a( 0xFFFFFFFFFFFFFFFFull ); 287 | constexpr bitset2<128> b_a_02a( arr_add_01a ); 288 | bitset2<128> b_a_02ap( arr_add_01ap ); 289 | constexpr bitset2<128> b_a_02b( arr_add_01b ); 290 | 291 | std::cout << b_a_02ap.to_hex_string() << "\n"; 292 | 293 | constexpr auto add_b_a_01a= b_a_01a + b_a_01a; 294 | constexpr auto add_b_a_02a= b_a_02a + b_a_02a; 295 | constexpr auto add_b_a_02b= b_a_02a + b_a_02b; 296 | constexpr auto add_b_a_02c= b_a_02b + b_a_02b; 297 | std::cout << b_a_01a << " +\n" << b_a_01a << " =\n" << add_b_a_01a << "\n\n"; 298 | std::cout << b_a_02a << " +\n" << b_a_02a << " =\n" << add_b_a_02a << "\n\n"; 299 | std::cout << b_a_02a << " +\n" << b_a_02b << " =\n" << add_b_a_02b << "\n\n"; 300 | std::cout << b_a_02b << " +\n" << b_a_02b << " =\n" << add_b_a_02c << "\n\n"; 301 | 302 | bitset2<65> bc2_65c{ 0xF00000000000000Eull }; 303 | std::cout << bc2_65c << " +\n" << bc2_65a << " =\n"; 304 | bc2_65c += bc2_65a; 305 | std::cout << bc2_65c << "\n\n"; 306 | 307 | bitset2<65> bc2_65d{ 0xFFFFFFFFFFFFFFFEull }; 308 | std::cout << "++" << bc2_65d << "=\n "; 309 | std::cout << (++bc2_65d) << "\n"; 310 | 311 | bitset2<65> bc2_65e = bc2_65d << 1; 312 | 313 | std::cout << "++" << bc2_65d << "=\n "; 314 | std::cout << (++bc2_65d) << "\n"; 315 | 316 | std::cout << "++" << bc2_65e << "=\n "; 317 | std::cout << (++bc2_65e) << "\n"; 318 | std::cout << " " << bc2_65e << "++ =\n "; 319 | bc2_65e++; 320 | std::cout << bc2_65e << "\n"; 321 | 322 | bitset2<65> bc2_65f= bitset2<65>{1ull} << 64; 323 | bitset2<65> bc2_65g; 324 | std::cout << "\n--" << bc2_65f << "=\n "; 325 | std::cout << (--bc2_65f) << "\n"; 326 | std::cout << " " << bc2_65f << "-- =\n "; 327 | bc2_65f--; 328 | std::cout << bc2_65f << "\n"; 329 | std::cout << "--" << bc2_65g << "=\n "; 330 | std::cout << (--bc2_65g) << "\n"; 331 | 332 | std::string bit_string = "101110"; 333 | std::istringstream bit_stream( bit_string ); 334 | bitset2<3> b_from_stream1; 335 | bitset2<3> b_from_str2( bit_string, 3 ); 336 | bitset2<4> b_from_str3( bit_string.c_str() + 1, 3 ); 337 | bit_stream >> b_from_stream1; 338 | std::cout << b_from_stream1 339 | << "= 0x" << b_from_stream1.to_hex_string() << '\n'; 340 | std::cout << b_from_str2 341 | << "= 0x" << b_from_str2.to_hex_string() << '\n'; 342 | std::cout << b_from_str3 343 | << "= 0x" << b_from_str3.to_hex_string() << '\n'; 344 | 345 | 346 | constexpr std::array s_arr_01a{{ 1ull }}; 347 | constexpr std::array s_arr_01b{{ 0xFFFFFFFFFFFFFFFFull, 1ull }}; 348 | constexpr std::array s_arr_01c{{ 0x1ull, 0xFFFFFFFFFFFFFFFFull, 0x3ull }}; 349 | constexpr std::array s_arr_01d{{ 0xEEEEEEEEEEEEEEEEull, 0xDull, 1ull, 0xFFFFFFFFFFFFFFFFull }}; 350 | constexpr bitset2<129> b_from_s_arr01a{ s_arr_01a }; 351 | constexpr bitset2<129> b_from_s_arr01b{ s_arr_01b }; 352 | constexpr bitset2<129> b_from_s_arr01c{ s_arr_01c }; 353 | constexpr bitset2<129> b_from_s_arr01d{ s_arr_01d }; 354 | std::cout << "b_from_s_arr01a= " << b_from_s_arr01a.to_hex_string() << "\n"; 355 | std::cout << "b_from_s_arr01b= " << b_from_s_arr01b.to_hex_string() << "\n"; 356 | std::cout << "b_from_s_arr01c= " << b_from_s_arr01c.to_hex_string() << "\n"; 357 | std::cout << "b_from_s_arr01d= " << b_from_s_arr01d.to_hex_string() << "\n"; 358 | 359 | constexpr bitset2<24> b24_empty{ 0ull }; 360 | constexpr bitset2<24> b24_full= ~b24_empty; 361 | constexpr bitset2<23> b23_a= convert_to<23>( b24_full ); 362 | constexpr bitset2<25> b25_a= convert_to<25>( b24_full ); 363 | constexpr auto b24_full_ui8= convert_to<24,uint8_t>( b24_full ); 364 | std::cout << "b24_full= " << b24_full << "\n"; 365 | std::cout << "b23_a= " << b23_a << "\n"; 366 | std::cout << "b25_a= " << b25_a << "\n"; 367 | std::cout << "b24_full_ui8= " << b24_full_ui8 << '\n'; 368 | 369 | bitset2<7> b7_a( "1010101" ); 370 | bitset2<7> b7_b( "1000101" ); 371 | bitset2<7> b7_c( "1110101" ); 372 | bitset2<7> b7_d( "0110101" ); 373 | bitset2<7> b7_e( "1010101" ); 374 | 375 | constexpr bitset2<7> b7_a_ce( 0b1010101ull ); 376 | constexpr bitset2<7> b7_b_ce( 0b1000101ull ); 377 | 378 | assert( is_subset_of( b7_b, b7_a ) ); 379 | assert( !is_subset_of( b7_c, b7_a ) ); 380 | assert( !is_subset_of( b7_d, b7_a ) ); 381 | assert( !is_subset_of( b7_a, b7_d ) ); 382 | 383 | assert( unequal( b7_a, b7_b ) ); 384 | assert( !unequal( b7_e, b7_a ) ); 385 | 386 | static_assert( is_subset_of( b7_b_ce, b7_a_ce ), "" ); 387 | static_assert( unequal( b7_a_ce, b7_b_ce ), "" ); 388 | 389 | assert( b7_b < b7_a ); 390 | assert( b7_c > b7_a ); 391 | assert( b7_e <= b7_a ); 392 | assert( b7_a >= b7_d ); 393 | 394 | bitset2<2047> b2047_a( 1ull ); 395 | auto b2047_b= b2047_a << 999; 396 | auto b2047_c= b2047_a + b2047_b; 397 | auto b2047_d= b2047_a << 1999; 398 | std::cout << "b2047_a= " << b2047_a.to_hex_string() << "\n" 399 | << "b2047_b= " << b2047_b.to_hex_string() << "\n" 400 | << "b2047_c= " << b2047_c.to_hex_string() << "\n"; 401 | std::cout << "bitset2<2047>::n_array= " << bitset2<2047>::n_array << '\n'; 402 | assert( unequal( b2047_a, b2047_b ) ); 403 | assert( unequal( b2047_b, b2047_d ) ); 404 | assert( is_subset_of( b2047_a, b2047_c ) ); 405 | assert( !is_subset_of( b2047_b, b2047_d ) ); 406 | 407 | bitset2<16> b16_a( "0000101000011111" ); 408 | bitset2<16> b16_b; 409 | hex_params<> hp1; 410 | hp1.aCh= 'A'; 411 | hp1.leadingZeroes= false; 412 | hp1.prefix= "0x"; 413 | std::cout << '\n' 414 | << b16_a.to_hex_string() << '\n' // 0a1f 415 | << b16_a.to_hex_string( hp1 ) // 0xA1F 416 | << '\n' 417 | #if __cplusplus >= 202002L 418 | << b16_a.to_hex_string( {.aCh='A', .leadingZeroes=false, .prefix="0x"} ) // 0xA1F 419 | << '\n' 420 | #endif 421 | << b16_b.to_hex_string() << '\n' // 0000 422 | << b16_b.to_hex_string( hex_params<>{'0', 'a', false, false, "0X"}) // 0X 423 | << '\n' 424 | #if __cplusplus >= 202002L 425 | << b16_b.to_hex_string( {.leadingZeroes=false, .nonEmpty=false, .prefix="0X"} ) // 0X 426 | << '\n' 427 | #endif 428 | << '\n'; 429 | 430 | #ifdef __SIZEOF_INT128__ 431 | std::cout << "\nEntering __int128 test\n"; 432 | using uint128 = unsigned __int128; 433 | constexpr bitset2<128> b_128_1( uint128(-1) ); 434 | constexpr bitset2<127,uint128> b_128_2( uint128(-1) ); 435 | constexpr bitset2<126,uint8_t> b_128_3( uint128(-1) ); 436 | constexpr auto val_128_1 = b_128_1.to_u128(); 437 | constexpr auto val_128_2 = b_128_2.to_u128(); 438 | constexpr auto val_128_3 = b_128_3.to_u128(); 439 | std::cout << " " << b_128_1 440 | << "\n = " << b_128_1.to_hex_string() 441 | //<< "\n = " << val_128_1 442 | << '\n'; 443 | std::cout << " " << b_128_2 444 | << "\n = " << b_128_2.to_hex_string() << '\n'; 445 | std::cout << " " << b_128_3 446 | << "\n = " << b_128_3.to_hex_string() << '\n'; 447 | static_assert( b_128_1 == bitset2<128>(val_128_1) ); 448 | static_assert( b_128_2 == bitset2<127,uint128>(val_128_2) ); 449 | static_assert( b_128_3 == bitset2<126,uint8_t>(val_128_3) ); 450 | #endif 451 | } // main 452 | -------------------------------------------------------------------------------- /tests/test_bitset2_02.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include "bitset2.hpp" 4 | 5 | 6 | int main() 7 | { 8 | using namespace Bitset2; 9 | 10 | using ULLONG= unsigned long long; 11 | 12 | constexpr 13 | std::array a01{{1ull}}; 14 | 15 | constexpr 16 | std::array a02{}; 17 | 18 | constexpr auto a_app01= detail::array_funcs<1,ULLONG>().prepend( 2ull, a01 ); 19 | constexpr auto a_app02= detail::array_funcs<0,ULLONG>().prepend( 3ull, a02 ); 20 | std::cout << a_app01[0] << "\t" << a_app01[1] << "\n"; 21 | std::cout << a_app02[0] << "\n"; 22 | 23 | //constexpr 24 | auto aop0= detail::array_ops<65,ULLONG>( 0 ); 25 | //constexpr 26 | auto aop65= detail::array_ops<65,ULLONG>( 65 ); 27 | //constexpr 28 | auto slp65= Bitset2::bitset2<64>{ aop65.m_shft_left_pattern }; 29 | 30 | std::cout << "(aop0) m_n_shift_mod= " << aop0.m_n_shift_mod 31 | << "\n m_shft_div= " << aop0.m_shft_div 32 | << "\n m_shft_mod= " << aop0.m_shft_mod 33 | << "\n m_shft_leftright_shift= " << aop0.m_shft_leftright_shift 34 | << "\n m_shft_left_pattern= " << aop0.m_shft_left_pattern 35 | << "\n m_shft_right_pattern= " << aop0.m_shft_right_pattern 36 | << "\n n_words= " << aop0.n_words 37 | << "\n n_array= " << aop0.n_array 38 | << "\n"; 39 | std::cout << "(aop65) m_n_shift_mod= " << aop65.m_n_shift_mod 40 | << "\n m_shft_div= " << aop65.m_shft_div 41 | << "\n m_shft_mod= " << aop65.m_shft_mod 42 | << "\n m_shft_leftright_shift= " << aop65.m_shft_leftright_shift 43 | << "\n m_shft_left_pattern= " << aop65.m_shft_left_pattern 44 | << "\n = " << slp65 45 | << "\n m_shft_right_pattern= " << aop65.m_shft_right_pattern 46 | << "\n n_words= " << aop65.n_words 47 | << "\n n_array= " << aop65.n_array 48 | << "\n"; 49 | } 50 | -------------------------------------------------------------------------------- /tests/test_nonconst_constexpr01.cpp: -------------------------------------------------------------------------------- 1 | // BITSET2 2 | // 3 | // Copyright Claas Bontus 4 | // 5 | // Use, modification and distribution is subject to the 6 | // Boost Software License, Version 1.0. (See accompanying 7 | // file LICENSE.txt or copy at 8 | // http://www.boost.org/LICENSE_1_0.txt) 9 | // 10 | // Project home: https://github.com/ClaasBontus/bitset2 11 | // 12 | 13 | 14 | #include "../bitset2.hpp" 15 | #include 16 | #include 17 | 18 | 19 | template 20 | constexpr 21 | Bitset2::bitset2 22 | ce_op( Bitset2::bitset2 const &bs, size_t n, size_t op_t ) 23 | { 24 | auto ret_val= bs; 25 | for( size_t c= 0; c < n; c++ ) 26 | { 27 | switch( op_t ) 28 | { 29 | case 1: ++ret_val; break; 30 | case 2: ret_val++; break; 31 | case 3: --ret_val; break; 32 | case 4: ret_val--; break; 33 | } 34 | } 35 | return ret_val; 36 | } // ce_op 37 | 38 | 39 | template 40 | constexpr 41 | Bitset2::bitset2 42 | ce_opequal( Bitset2::bitset2 const &bs1, 43 | Bitset2::bitset2 const &bs2, 44 | size_t op_t ) 45 | { 46 | auto ret_val= bs1; 47 | 48 | switch( op_t ) 49 | { 50 | case 1: ret_val += bs2; break; 51 | case 2: ret_val |= bs2; break; 52 | case 3: ret_val &= bs2; break; 53 | case 4: ret_val ^= bs2; break; 54 | case 5: ret_val.difference( bs2 ); break; 55 | } 56 | return ret_val; 57 | } // ce_opequal 58 | 59 | 60 | template 61 | constexpr 62 | Bitset2::bitset2 63 | ce_shftequal( Bitset2::bitset2 const &bs1, 64 | size_t shft, 65 | size_t op_t ) 66 | { 67 | auto ret_val= bs1; 68 | 69 | switch( op_t ) 70 | { 71 | case 1: ret_val <<= shft; break; 72 | case 2: ret_val >>= shft; break; 73 | case 3: ret_val.rotate_left( shft ); break; 74 | case 4: ret_val.rotate_right( shft ); break; 75 | } 76 | return ret_val; 77 | } // ce_shftequal 78 | 79 | 80 | template 81 | constexpr 82 | Bitset2::bitset2 83 | ce_sme_fncs( Bitset2::bitset2 const &bs1 ) 84 | { 85 | auto ret_val= bs1; 86 | Bitset2::bitset2 b2; 87 | b2.set(); 88 | b2.set( 12, false ); 89 | b2.test_set( 15, false ); 90 | 91 | ret_val.reverse(); 92 | ret_val.complement2(); 93 | ret_val ^= b2; 94 | 95 | ret_val.flip(); 96 | ret_val.flip( 42 ); 97 | ret_val.flip(); 98 | 99 | return ret_val; 100 | } // ce_sme_fncs 101 | 102 | 103 | template 104 | constexpr 105 | Bitset2::bitset2 106 | ce_evry_scnd() 107 | { 108 | Bitset2::bitset2 ret_val; 109 | 110 | for( size_t c= 0; c < N; c += 2 ) 111 | { 112 | auto ref= ret_val[c]; 113 | ref= true; 114 | } 115 | 116 | return ret_val; 117 | } // ce_evry_scnd 118 | 119 | 120 | template 121 | constexpr 122 | Bitset2::bitset2 123 | ce_evry_scnd2() 124 | { 125 | Bitset2::bitset2 ret_val{{1}}; 126 | auto const one= ret_val; 127 | 128 | for( size_t c= 0; c < N; c += 2 ) 129 | { 130 | ret_val <<= 2; 131 | ret_val |= one; 132 | } 133 | 134 | return ret_val; 135 | } // ce_evry_scnd2 136 | 137 | 138 | int main() 139 | { 140 | using ULLONG= unsigned long long; 141 | using namespace Bitset2; 142 | 143 | constexpr std::array s_arr_01a{{ 0xFFFFFFFFFFFFFFFFull, 1ull }}; 144 | constexpr std::array s_arr_01b{{ 5ull, 0ull }}; 145 | constexpr std::array bit12{{ 1ull << 12, 0ull }}; 146 | constexpr std::array bit15{{ 1ull << 15, 0ull }}; 147 | constexpr std::array bit42{{ 1ull << 42, 0ull }}; 148 | constexpr bitset2<129> zero; 149 | constexpr bitset2<129> all_set= ~zero; 150 | constexpr bitset2<129> sme_set1= 151 | all_set ^ bitset2<129>{ bit12 } ^ bitset2<129>{ bit15 }; 152 | constexpr bitset2<129> b_from_s_arr01a{ s_arr_01a }; 153 | constexpr bitset2<129> b_from_s_arr01b{ s_arr_01b }; 154 | constexpr auto minus_s_arr_01b= complement2( b_from_s_arr01b ); 155 | constexpr auto add_01a_b= b_from_s_arr01a + b_from_s_arr01b; 156 | constexpr auto sub_01a_b= b_from_s_arr01a + minus_s_arr_01b; 157 | constexpr auto inc_01a_5= ce_op( b_from_s_arr01a, 5, 1 ); 158 | constexpr auto inc_01b_5= ce_op( b_from_s_arr01a, 5, 2 ); 159 | constexpr auto dec_01c_5= ce_op( b_from_s_arr01a, 5, 3 ); 160 | constexpr auto dec_01d_5= ce_op( b_from_s_arr01a, 5, 4 ); 161 | 162 | constexpr auto or_01a_b= b_from_s_arr01a | b_from_s_arr01b; 163 | constexpr auto and_01a_b= b_from_s_arr01a & b_from_s_arr01b; 164 | constexpr auto xor_01a_b= b_from_s_arr01a ^ b_from_s_arr01b; 165 | constexpr auto sdi_01a_b= difference( b_from_s_arr01a, b_from_s_arr01b ); 166 | constexpr auto shl4_01a= b_from_s_arr01a << 4; 167 | constexpr auto shr4_01a= b_from_s_arr01a >> 4; 168 | constexpr auto rol4_01a= rotate_left( b_from_s_arr01a, 4 ); 169 | constexpr auto ror4_01a= rotate_right( b_from_s_arr01a, 4 ); 170 | 171 | constexpr auto rev_01a= reverse( b_from_s_arr01a ); 172 | constexpr auto cpl2_01a= complement2( rev_01a ); 173 | constexpr auto xor12_01a= cpl2_01a ^ sme_set1; 174 | constexpr auto xor42_01a= xor12_01a ^ bitset2<129>{ bit42 }; 175 | 176 | constexpr auto pe1= ce_opequal( b_from_s_arr01a, b_from_s_arr01b, 1 ); 177 | constexpr auto oe1= ce_opequal( b_from_s_arr01a, b_from_s_arr01b, 2 ); 178 | constexpr auto ae1= ce_opequal( b_from_s_arr01a, b_from_s_arr01b, 3 ); 179 | constexpr auto xe1= ce_opequal( b_from_s_arr01a, b_from_s_arr01b, 4 ); 180 | constexpr auto de1= ce_opequal( b_from_s_arr01a, b_from_s_arr01b, 5 ); 181 | 182 | constexpr auto sl4_1= ce_shftequal( b_from_s_arr01a, 4, 1 ); 183 | constexpr auto sr4_1= ce_shftequal( b_from_s_arr01a, 4, 2 ); 184 | constexpr auto rl4_1= ce_shftequal( b_from_s_arr01a, 4, 3 ); 185 | constexpr auto rr4_1= ce_shftequal( b_from_s_arr01a, 4, 4 ); 186 | constexpr auto smf_a= ce_sme_fncs( b_from_s_arr01a ); 187 | 188 | constexpr auto e2_1= ce_evry_scnd<1025,ULLONG>(); 189 | constexpr auto e2_2= ce_evry_scnd2<1025,ULLONG>(); 190 | constexpr auto e2_3= ce_evry_scnd<256,ULLONG>(); 191 | constexpr auto e2_4= ce_evry_scnd2<256,ULLONG>(); 192 | 193 | static_assert( add_01a_b == inc_01a_5, "" ); 194 | static_assert( add_01a_b == inc_01b_5, "" ); 195 | static_assert( sub_01a_b == dec_01c_5, "" ); 196 | static_assert( sub_01a_b == dec_01d_5, "" ); 197 | static_assert( add_01a_b == pe1, "" ); 198 | static_assert( or_01a_b == oe1, "" ); 199 | static_assert( and_01a_b == ae1, "" ); 200 | static_assert( xor_01a_b == xe1, "" ); 201 | static_assert( sdi_01a_b == de1, "" ); 202 | static_assert( shl4_01a == sl4_1, "" ); 203 | static_assert( shr4_01a == sr4_1, "" ); 204 | static_assert( rol4_01a == rl4_1, "" ); 205 | static_assert( ror4_01a == rr4_1, "" ); 206 | static_assert( xor42_01a == smf_a, "" ); 207 | static_assert( e2_1 == e2_2, "" ); 208 | static_assert( e2_3 == e2_4, "" ); 209 | 210 | std::cout << inc_01a_5 << '\n' << inc_01b_5.to_hex_string() << "\n"; 211 | std::cout << sub_01a_b << '\n' << dec_01c_5.to_hex_string() << "\n"; 212 | 213 | return 0; 214 | } // main 215 | -------------------------------------------------------------------------------- /tests/test_ullong2array.cpp: -------------------------------------------------------------------------------- 1 | // BITSET2 2 | // 3 | // Copyright Claas Bontus 4 | // 5 | // Use, modification and distribution is subject to the 6 | // Boost Software License, Version 1.0. (See accompanying 7 | // file LICENSE.txt or copy at 8 | // http://www.boost.org/LICENSE_1_0.txt) 9 | // 10 | // Project home: https://github.com/ClaasBontus/bitset2 11 | // 12 | 13 | 14 | #include "ullong2array.hpp" 15 | #include "array2u_long_t.hpp" 16 | #include 17 | #include 18 | #include 19 | 20 | 21 | int main() 22 | { 23 | using ULLONG= unsigned long long; 24 | 25 | auto const all_set_ull= ~ULLONG(0); 26 | 27 | #ifdef __SIZEOF_INT128__ 28 | auto const all_set= (unsigned __int128)(-1); 29 | #else 30 | auto const all_set= all_set_ull; 31 | #endif 32 | 33 | using namespace Bitset2::detail; 34 | 35 | using a2l_65ll= Bitset2::detail::array2u_long_t<65,ULLONG,ULLONG>; 36 | 37 | auto const a1= lrgst2array<18,uint32_t>()( all_set ); 38 | std::array const expt1{{ uint32_t((1ull << 18) - 1) }}; 39 | size_t ct= 0; 40 | for( auto v: a1 ) 41 | { 42 | std::cout << v << ", "; 43 | assert( v == expt1[ct] ); ct++; 44 | } 45 | std::cout << "\n"; 46 | assert( ct == 1 ); 47 | 48 | 49 | auto const a2= lrgst2array<34,uint32_t>()( all_set ); 50 | std::array const 51 | expt2{{ uint32_t(~uint32_t(0)), uint32_t((1ull << 2) - 1) }}; 52 | ct= 0; 53 | for( auto v: a2 ) 54 | { 55 | std::cout << v << ", "; 56 | assert( v == expt2[ct] ); ct++; 57 | } 58 | std::cout << "\n"; 59 | assert( ct == 2 ); 60 | 61 | 62 | auto const a3= lrgst2array<18,uint16_t>()( all_set ); 63 | std::array const 64 | expt3{{ uint16_t(~uint16_t(0)), uint16_t((1ull << 2) - 1) }}; 65 | ct= 0; 66 | for( auto v: a3 ) 67 | { 68 | std::cout << v << ", "; 69 | assert( v == expt3[ct] ); ct++; 70 | } 71 | std::cout << "\n"; 72 | assert( ct == 2 ); 73 | 74 | 75 | auto const a4= lrgst2array<18,uint8_t>()( all_set ); 76 | std::array const 77 | expt4{{uint8_t(~uint8_t(0)),uint8_t(~uint8_t(0)),uint8_t((1ull << 2) - 1)}}; 78 | ct= 0; 79 | for( auto v: a4 ) 80 | { 81 | std::cout << int(v) << ", "; 82 | assert( v == expt4[ct] ); ct++; 83 | } 84 | std::cout << "\n"; 85 | assert( ct == 3 ); 86 | 87 | 88 | auto const a5= lrgst2array<18,uint64_t>()( all_set ); 89 | std::array const expt5{{ uint64_t((1ull << 18) - 1) }}; 90 | ct= 0; 91 | for( auto v: a5 ) 92 | { 93 | std::cout << v << ", "; 94 | assert( v == expt5[ct] ); ct++; 95 | } 96 | std::cout << "\n"; 97 | assert( ct == 1 ); 98 | 99 | 100 | auto const a6= lrgst2array<34,uint64_t>()( all_set ); 101 | std::array const expt6{{ uint64_t((1ull << 34) - 1) }}; 102 | ct= 0; 103 | for( auto v: a6 ) 104 | { 105 | std::cout << v << ", "; 106 | assert( v == expt6[ct] ); ct++; 107 | } 108 | std::cout << "\n"; 109 | assert( ct == 1 ); 110 | 111 | 112 | auto const a7= lrgst2array<66,uint64_t>()( all_set ); 113 | #ifdef __SIZEOF_INT128__ 114 | std::array const 115 | expt7{{ uint64_t(~uint64_t(0)), uint64_t(3) }}; 116 | #else 117 | std::array const 118 | expt7{{ uint64_t(~uint64_t(0)), uint64_t(0) }}; 119 | #endif 120 | ct= 0; 121 | for( auto v: a7 ) 122 | { 123 | std::cout << v << ", "; 124 | assert( v == expt7[ct] ); ct++; 125 | } 126 | std::cout << "\n"; 127 | assert( ct == 2 ); 128 | 129 | 130 | a2l_65ll::array_t arr1{{ all_set_ull, 0ull }}; 131 | 132 | std::cout << '\n' << a2l_65ll::i_pttrn << '\n'; 133 | std::cout << a2l_65ll::h_pttrn << '\n'; 134 | std::cout << a2l_65ll::allset << '\n'; 135 | std::cout << a2l_65ll::n_array << '\n'; 136 | std::cout << a2l_65ll::use_vals << '\n'; 137 | std::cout << a2l_65ll().check_overflow( arr1 ) << '\n'; 138 | } 139 | -------------------------------------------------------------------------------- /tests/tests01.cpp: -------------------------------------------------------------------------------- 1 | // BITSET2 2 | // 3 | // Copyright Claas Bontus 4 | // 5 | // Use, modification and distribution is subject to the 6 | // Boost Software License, Version 1.0. (See accompanying 7 | // file LICENSE.txt or copy at 8 | // http://www.boost.org/LICENSE_1_0.txt) 9 | // 10 | // Project home: https://github.com/ClaasBontus/bitset2 11 | // 12 | 13 | 14 | #include "../bitset2.hpp" 15 | #include "gen_randoms.hpp" 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | 22 | #define TESTMANY(F) \ 23 | F <7 >(); \ 24 | F <8 >(); \ 25 | F <9 >(); \ 26 | F <63 >(); \ 27 | F <64 >(); \ 28 | F <65 >(); \ 29 | F <95 >(); \ 30 | F <96 >(); \ 31 | F <97 >(); \ 32 | F <127>(); \ 33 | F <128>(); \ 34 | F <129>(); \ 35 | F <255>(); \ 36 | F <256>(); \ 37 | F <257>(); 38 | 39 | #define TESTMANY2(F,T,S) \ 40 | F <7, T>(S); \ 41 | F <8, T>(S); \ 42 | F <9, T>(S); \ 43 | F <63, T>(S); \ 44 | F <64, T>(S); \ 45 | F <65, T>(S); \ 46 | F <95, T>(S); \ 47 | F <96, T>(S); \ 48 | F <97, T>(S); \ 49 | F <127,T>(S); \ 50 | F <128,T>(S); \ 51 | F <129,T>(S); \ 52 | F <255,T>(S); \ 53 | F <256,T>(S); \ 54 | F <257,T>(S); 55 | 56 | #ifdef __SIZEOF_INT128__ 57 | # define USE128(F) TESTMANY2(F,unsigned __int128,"uint128") 58 | #else 59 | # define USE128(F) 60 | #endif 61 | 62 | #define TESTMNY(F) { \ 63 | auto const t1 = std::chrono::high_resolution_clock::now(); \ 64 | TESTMANY2(F,uint8_t, "uint8_t" ) \ 65 | TESTMANY2(F,uint16_t,"uint16_t") \ 66 | TESTMANY2(F,uint32_t,"uint32_t") \ 67 | TESTMANY2(F,unsigned long long,"U_L_LONG") \ 68 | USE128(F) \ 69 | auto const t2 = std::chrono::high_resolution_clock::now(); \ 70 | const std::chrono::duration dt21 = t2 -t1; \ 71 | std::cout << "Total: " << dt21.count() << " seconds\n\n"; \ 72 | } 73 | 74 | 75 | template 76 | using t1= Bitset2::bitset2; 77 | 78 | template 79 | using t1a= Bitset2::bitset2; 80 | 81 | template 82 | using t2= std::bitset; 83 | 84 | 85 | constexpr size_t n_loops= 100000; 86 | 87 | constexpr bool verbose= false; 88 | 89 | 90 | template 91 | struct dummy_add 92 | { 93 | enum : size_t 94 | { ull_bits= sizeof(T) * CHAR_BIT 95 | , div_val= N / ull_bits 96 | , mod_val= N % ull_bits 97 | , n_ull= ( mod_val != 0 ) ? (div_val+1) : div_val 98 | , n_array= ( N == 0 ) ? 1 : n_ull 99 | }; 100 | // 101 | enum : T 102 | { all_one= T(~T(0)) 103 | , hgh_pattern= (N==0) ? T(0) 104 | : (mod_val==0) ? T(all_one) 105 | : T(all_one >> (ull_bits-mod_val)) 106 | }; 107 | // 108 | using array_t= std::array; 109 | // 110 | array_t 111 | add( array_t const &a1, array_t const &a2 ) const 112 | { 113 | array_t ret_val; 114 | T crry= T(0); 115 | 116 | for( size_t c= 0; c < n_ull; ++c ) 117 | { 118 | T const v= T( a1[c] + a2[c] + crry ); 119 | if( v < a1[c] || v < a2[c] || 120 | ( a1[c] == all_one && a2[c] == all_one ) ) crry= T(1); 121 | else crry= T(0); 122 | ret_val[c]= v; 123 | } 124 | if( n_ull > 0 ) ret_val[n_ull-1] &= hgh_pattern; 125 | 126 | return ret_val; 127 | } // add 128 | // 129 | // Returns false if a1 != a2 130 | bool 131 | compare( array_t const &a1, array_t const &a2 ) 132 | { 133 | for( size_t c= 0; c < n_array; ++c ) 134 | { 135 | if( a1[c] != a2[c] ) return false; 136 | } 137 | return true; 138 | } 139 | }; // struct dummy_add 140 | 141 | 142 | template 143 | t1 144 | dummy_reverse( t1 const & bs ) 145 | { 146 | t1 ret_val; 147 | for( size_t c= 0; c < N; ++c ) ret_val[c]= bs[N-c-1]; 148 | 149 | return ret_val; 150 | } 151 | 152 | 153 | template 154 | t1 155 | dummy_average( t1 const & bs1, t1 const & bs2, bool round_down ) 156 | { 157 | t1 tmp= t1(bs1.data()); 158 | tmp += t1(bs2.data()); 159 | tmp >>= 1; 160 | 161 | if(!round_down) 162 | { 163 | T v1 = bs1.data()[0]; 164 | T v2 = bs2.data()[0]; 165 | if( (v1 & 1) && ((~v2) & 1) ) ++tmp; 166 | } 167 | 168 | return t1(tmp.data()); 169 | } 170 | 171 | 172 | 173 | template 174 | void 175 | test_any_all_none( char const * type_str ) 176 | { 177 | std::cout << "Entering test_any_all_none N= " << N << " type= " << type_str << "\n"; 178 | 179 | t1 const empty1; 180 | t2 const empty2; 181 | auto const full1= ~empty1; 182 | auto const full2= ~empty2; 183 | 184 | auto const empty1a= t1( empty2 ); 185 | auto const empty2a= t2( empty1 ); 186 | auto const full1a= t1( full2 ); 187 | auto const full2a= t2( full1 ); 188 | 189 | assert( empty1.none() && !empty1.all() && !empty1.any() ); 190 | assert( empty1a.none() && !empty1a.all() && !empty1a.any() ); 191 | assert( empty2a.none() && !empty2a.all() && !empty2a.any() ); 192 | assert( !full1.none() && full1.all() && full1.any() ); 193 | assert( !full1a.none() && full1a.all() && full1a.any() ); 194 | assert( !full2a.none() && full2a.all() && full2a.any() ); 195 | 196 | 197 | constexpr t1 ce_empty1; 198 | constexpr auto ce_full1= ~ce_empty1; 199 | static_assert( ce_empty1.none() && !ce_empty1.all() && !ce_empty1.any(), "" ); 200 | static_assert( !ce_full1.none() && ce_full1.all() && ce_full1.any(), "" ); 201 | 202 | 203 | gen_random_bitset2 gen_rand; 204 | for( size_t c= 0; c < n_loops; ++c ) 205 | { 206 | auto const bs1= gen_rand(); 207 | auto const bs2= t2( bs1 ); 208 | auto const bs1a= t1( bs2 ); 209 | 210 | if( verbose ) std::cout << bs1.to_hex_string() << "\t" << c << "\n"; 211 | 212 | assert( bs1 == bs1a ); 213 | assert( bs1.none() == bs2.none() ); 214 | assert( bs1.all() == bs2.all() ); 215 | assert( bs1.any() == bs2.any() ); 216 | } // for c 217 | } // test_any_all_none 218 | 219 | 220 | 221 | 222 | template 223 | void 224 | test_set_count_size( char const * type_str ) 225 | { 226 | std::cout << "Entering test_set_count_size N= " << N << " type= " << type_str << "\n"; 227 | 228 | t1 const empty1; 229 | constexpr t1 ce_empty1; 230 | constexpr t1 ce_full1= ~ce_empty1; 231 | constexpr t1 one{1}; 232 | assert( empty1.size() == N ); 233 | static_assert( ce_empty1.size() == N, "" ); 234 | static_assert( ce_full1.count() == N, "" ); 235 | static_assert( !ce_empty1.test( N - 3 ), "" ); 236 | static_assert( ce_full1.test( N - 2 ), "" ); 237 | 238 | static_assert( !ce_empty1.has_single_bit() ); 239 | static_assert( !ce_full1.has_single_bit() ); 240 | static_assert( one.has_single_bit() ); 241 | 242 | gen_random_bitset2 gen_rand; 243 | for( size_t c= 0; c < n_loops; ++c ) 244 | { 245 | auto const bs1= gen_rand(); 246 | auto const cnt1= bs1.count(); 247 | size_t n_set1= 0, n_set2= 0; 248 | for( size_t b_c= 0; b_c < N; ++b_c ) 249 | { 250 | if( bs1.test( b_c ) ) ++n_set1; 251 | if( bs1[b_c] ) ++n_set2; 252 | 253 | t1 bs3; 254 | bs3.set(b_c); 255 | assert( bs3.has_single_bit() ); 256 | } 257 | 258 | if( verbose ) std::cout << bs1.to_hex_string() << "\t" << n_set1 259 | << "\t" << c << "\t" << bs1 << "\n"; 260 | 261 | auto bs2= bs1; 262 | bs2.flip(); 263 | auto const cnt2= bs2.count(); 264 | 265 | assert( n_set1 == cnt1 ); 266 | assert( n_set1 == n_set2 ); 267 | assert( cnt2 == N - cnt1 ); 268 | 269 | assert( !bs1.has_single_bit() || cnt1 == 1 ); 270 | } // for c 271 | } // test_set_count_size 272 | 273 | 274 | 275 | 276 | template 277 | void 278 | test_set( char const * type_str ) 279 | { 280 | std::cout << "Entering test_set N= " << N << " type= " << type_str << "\n"; 281 | 282 | gen_random_bitset2 gen_rand; 283 | for( size_t c= 0; c < n_loops; ++c ) 284 | { 285 | auto bs1= gen_rand(); 286 | auto bs2= bs1; 287 | auto bs3= t2( bs1 ); 288 | bool flag= false; 289 | for( size_t b= 0; b < N; ++ b ) 290 | { 291 | bool const bt1= bs1[b]; 292 | bs1.set( b, flag ); 293 | auto const bt2= bs2.test_set( b, flag); 294 | assert( bt1 == bt2 ); 295 | bs3.set( b, flag ); 296 | 297 | flag= !flag; 298 | } 299 | assert( bs1 == bs2 ); 300 | assert( bs1 == (t1( bs3 )) ); 301 | } // for c 302 | } // test_set 303 | 304 | 305 | 306 | 307 | template 308 | void 309 | test_rotate( char const * type_str ) 310 | { 311 | std::cout << "Entering test_rotate N= " << N << " type= " << type_str << "\n"; 312 | 313 | constexpr std::array ce_arr1{{ T(2), T(5) }}; 314 | constexpr std::array ce_arr2{{ T(4), T(10) }}; 315 | constexpr t1<74,T> ce_bs1( ce_arr1 ); 316 | constexpr t1<74,T> ce_bs1_r= Bitset2::rotate_left( ce_bs1, 1 ); 317 | constexpr t1<74,T> ce_bs2( ce_arr2 ); 318 | static_assert( ce_bs1_r == ce_bs2, "" ); 319 | 320 | gen_random_bitset2 gen_rand; 321 | for( size_t c= 0; c < n_loops; ++c ) 322 | { 323 | auto const bs1= gen_rand(); 324 | auto const cnt1= bs1.count(); 325 | 326 | for( size_t b_c= 0; b_c < 2 * N; ++b_c ) 327 | { 328 | auto const b_c_mod= b_c % N; 329 | auto const bs2_r= Bitset2::rotate_right( bs1, b_c ); 330 | auto const bs2_l= Bitset2::rotate_left( bs1, b_c ); 331 | auto const bs2a= Bitset2::rotate_left( bs2_r, b_c ); 332 | auto const bs2b= Bitset2::rotate_right( bs2_l, b_c ); 333 | auto const bs2_r2= ( bs1 >> b_c_mod ) | ( bs1 << (N-b_c_mod) ); 334 | auto const bs2_l2= ( bs1 << b_c_mod ) | ( bs1 >> (N-b_c_mod) ); 335 | 336 | auto bc1_c1= bs1; 337 | auto bc1_c2= bs1; 338 | bc1_c1.rotate_left( b_c ); 339 | bc1_c2.rotate_right( b_c ); 340 | 341 | if( verbose ) 342 | std::cout << bs1 << "\t" 343 | << b_c << "\t" 344 | << bs2_l << "\t" 345 | << bs2_r << "\n"; 346 | assert( cnt1 == bs2_r.count() ); 347 | assert( cnt1 == bs2_l.count() ); 348 | assert( bs2a == bs1 ); 349 | assert( bs2b == bs1 ); 350 | assert( bs2_r2 == bs2_r ); 351 | assert( bs2_l2 == bs2_l ); 352 | assert( bc1_c1 == bs2_l ); 353 | assert( bc1_c2 == bs2_r ); 354 | } 355 | } // for c 356 | } // test_rotate 357 | 358 | 359 | 360 | 361 | template 362 | void 363 | test_shift( char const * type_str ) 364 | { 365 | std::cout << "Entering test_shift N= " << N << " type= " << type_str << "\n"; 366 | 367 | gen_random_bitset2 gen_rand; 368 | t1 const empty1; 369 | 370 | constexpr size_t n_bts_m= sizeof(T) * CHAR_BIT - 1; 371 | constexpr std::array ce_arr1{{ T(2), T(5) }}; 372 | constexpr std::array ce_arr2{{ T(4), T(10) }}; 373 | constexpr std::array ce_arr3{{ T(1) + T(T(1) << n_bts_m), T(2) }}; 374 | constexpr t1<74,T> ce_bs1( ce_arr1 ); 375 | constexpr t1<74,T> ce_bs1_s1= ce_bs1 << 1; 376 | constexpr t1<74,T> ce_bs1_s2= ce_bs1 >> 1; 377 | constexpr t1<74,T> ce_bs2( ce_arr2 ); 378 | constexpr t1<74,T> ce_bs3( ce_arr3 ); 379 | static_assert( ce_bs1_s1 == ce_bs2, "" ); 380 | static_assert( ce_bs1_s2 == ce_bs3, "" ); 381 | 382 | for( size_t c= 0; c < n_loops; ++c ) 383 | { 384 | auto const bs1= gen_rand(); 385 | 386 | for( size_t b_c= 0; b_c <= N + 5; ++b_c ) 387 | { 388 | auto const bs1_l= bs1 << b_c; 389 | auto const bs1_r= bs1 >> b_c; 390 | auto bs1_c1= bs1; 391 | auto bs1_c2= bs1; 392 | bs1_c1 <<= b_c; 393 | bs1_c2 >>= b_c; 394 | if( verbose ) 395 | std::cout << bs1 << "\t" 396 | << bs1_l << "\t" 397 | << bs1_r << "\n"; 398 | if( b_c < N ) 399 | { 400 | t2 const bs2{ bs1 }; 401 | auto const bs2_l= bs2 << b_c; 402 | auto const bs2_r= bs2 >> b_c; 403 | assert( bs2_l == t2( bs1_l ) ); 404 | assert( bs2_r == t2( bs1_r ) ); 405 | assert( bs1_c1 == bs1_l ); 406 | assert( bs1_c2 == bs1_r ); 407 | } 408 | else 409 | { 410 | assert( bs1_l == empty1 ); 411 | assert( bs1_r == empty1 ); 412 | assert( bs1_c1 == empty1 ); 413 | assert( bs1_c2 == empty1 ); 414 | } 415 | } // for b_c 416 | } // for c 417 | } // test_shift 418 | 419 | 420 | 421 | 422 | template 423 | void 424 | test_midpoint( const char * type_str ) 425 | { 426 | std::cout << "Entering test_midpoint N= " << N << " type= " << type_str << "\n"; 427 | 428 | gen_random_bitset2 gen_rand; 429 | 430 | constexpr t1 ce_one{{ T(1) }}; 431 | constexpr t1 ce_empty; 432 | constexpr t1 ce_all= ~ce_empty; 433 | constexpr t1 ce_all_but_one= ~ce_one; 434 | constexpr auto ce_all_twice= ce_all + ce_all; 435 | static_assert( Bitset2::midpoint( ce_one, ce_one ) == ce_one, "" ); 436 | static_assert( Bitset2::midpoint( ce_empty, ce_empty ) == ce_empty, "" ); 437 | static_assert( Bitset2::midpoint( ce_all, ce_all ) == ce_all, "" ); 438 | static_assert( Bitset2::midpoint( ce_all_but_one, ce_all_but_one ) == ce_all_but_one, "" ); 439 | static_assert( Bitset2::midpoint( ce_all_twice, ce_all_twice ) == ce_all_twice, "" ); 440 | static_assert( Bitset2::midpoint( ce_all, ce_all_but_one ) == ce_all, "" ); 441 | static_assert( Bitset2::midpoint( ce_all, ce_all_but_one, true ) == ce_all_but_one, "" ); 442 | 443 | for( size_t c= 0; c < n_loops; ++c ) 444 | { 445 | auto const bs1= gen_rand(); 446 | auto const bs2= gen_rand(); 447 | 448 | assert( Bitset2::midpoint(bs1, bs2) == dummy_average(bs1, bs2, false) ); 449 | assert( Bitset2::midpoint(bs1, bs2, true) == dummy_average(bs1, bs2, true) ); 450 | } // for c 451 | } // test_midpoint 452 | 453 | 454 | 455 | 456 | template 457 | void 458 | test_add( const char * type_str ) 459 | { 460 | std::cout << "Entering test_add N= " << N << " type= " << type_str << "\n"; 461 | 462 | gen_random_bitset2 gen_rand; 463 | dummy_add adder; 464 | t1 const zero; 465 | t1 const one{{ T(1) }}; 466 | t1 const all= t1().set(); 467 | 468 | auto const all_twice= all + all; 469 | auto all_twice2= all; 470 | all_twice2 += all; 471 | auto a_m1= all; 472 | a_m1--; 473 | auto a_m2= a_m1; 474 | a_m2--; 475 | auto all_twice_m1= all + a_m1; 476 | assert( all_twice == a_m1 ); 477 | assert( all_twice2 == a_m1 ); 478 | assert( all_twice_m1 == a_m2 ); 479 | 480 | constexpr t1 ce_one{{ T(1) }}; 481 | constexpr t1 ce_empty; 482 | constexpr t1 ce_all= ~ce_empty; 483 | constexpr t1 ce_all_but_one= ~ce_one; 484 | constexpr auto ce_all_twice= ce_all + ce_all; 485 | static_assert( ce_all_twice == ce_all_but_one, "" ); 486 | 487 | for( size_t c= 0; c < n_loops; ++c ) 488 | { 489 | auto const bs1= gen_rand(); 490 | auto const bs2= gen_rand(); 491 | auto bs3= bs1; 492 | auto bs4= bs1; 493 | auto bs5= bs1; 494 | ++bs3; --bs4; 495 | bs5 += bs2; 496 | 497 | auto const add1= bs1 + bs2; 498 | auto const add2= adder.add( bs1.data(), bs2.data() ); 499 | auto const add3= adder.add( bs1.data(), one.data() ); 500 | auto const add4= adder.add( bs1.data(), all.data() ); 501 | if( verbose ) 502 | std::cout << " " << bs1 << "\n+ " << bs2 503 | << "\n= " << add1 504 | << "\n, " << t1(add2) << "\n\n"; 505 | auto const cmp1= adder.compare( add2, add1.data() ); 506 | auto const cmp2= adder.compare( add3, bs3.data() ); 507 | auto const cmp3= adder.compare( add4, bs4.data() ); 508 | auto const cmp4= adder.compare( add2, bs5.data() ); 509 | 510 | auto const exp_zero= bs1 + (~bs1 + one); 511 | 512 | assert( cmp1 ); 513 | assert( cmp2 ); 514 | assert( cmp3 ); 515 | assert( cmp4 ); 516 | assert( exp_zero == zero ); 517 | } // for c 518 | } // test_add 519 | 520 | 521 | 522 | 523 | template 524 | void 525 | test_difference( char const * type_str ) 526 | { 527 | std::cout << "Entering test_difference N= " << N << " type= " << type_str << "\n"; 528 | 529 | constexpr std::array ce_arr1{{ T(3), T(5) }}; 530 | constexpr std::array ce_arr2{{ T(6), T(1) }}; 531 | constexpr t1<74,T> ce_bs1( ce_arr1 ); 532 | constexpr t1<74,T> ce_bs2( ce_arr2 ); 533 | constexpr auto ce_diff1= difference( ce_bs1, ce_bs2 ); 534 | constexpr auto ce_ref1= ce_bs1 & ~ce_bs2; 535 | static_assert( ce_diff1 == ce_ref1, "" ); 536 | 537 | gen_random_bitset2 gen_rand; 538 | 539 | for( size_t c= 0; c < n_loops; ++c ) 540 | { 541 | auto const bs1= gen_rand(); 542 | auto const bs2= gen_rand(); 543 | auto bs3= bs1; 544 | 545 | auto const d1= difference( bs1, bs2 ); 546 | auto const d2= bs1 & ~bs2; 547 | bs3.difference( bs2 ); 548 | 549 | assert( d2 == d1 ); 550 | assert( bs3 == d1 ); 551 | } // for c 552 | } // test_difference 553 | 554 | 555 | 556 | 557 | 558 | template 559 | void 560 | test_not( char const * type_str ) 561 | { 562 | std::cout << "Entering test_not N= " << N << " type= " << type_str << "\n"; 563 | 564 | gen_random_bitset2 gen_rand; 565 | 566 | for( size_t c= 0; c < n_loops; ++c ) 567 | { 568 | auto const bs1= gen_rand(); 569 | auto const bs2= ~bs1; 570 | for( size_t b_c= 0; b_c < N; ++b_c ) 571 | { 572 | if( verbose ) std::cout << "~" << bs1 << "\n=" << bs2 << "\n"; 573 | assert( bs1[b_c] != bs2[b_c] ); 574 | } 575 | } // for c 576 | } // test_not 577 | 578 | 579 | template 580 | std::vector 581 | idx_lst( t1 const &bs ) 582 | { 583 | std::vector ret_val; 584 | for( size_t c= 0; c < N; ++c ) 585 | if( bs[c] ) ret_val.push_back( c ); 586 | return ret_val; 587 | } // idx_lst 588 | 589 | 590 | 591 | template 592 | void 593 | test_find( char const * type_str ) 594 | { 595 | std::cout << "Entering test_find N= " << N << " type= " << type_str << "\n"; 596 | 597 | constexpr t1 ce_bs1( 12ull ); 598 | constexpr auto ce_bs2 = ~ce_bs1; 599 | static_assert( ce_bs1.find_first() == 2, "" ); 600 | static_assert( ce_bs2.find_first_zero() == 2, "" ); 601 | static_assert( ce_bs1.find_last() == 3, "" ); 602 | static_assert( ce_bs2.find_last_zero() == 3, "" ); 603 | static_assert( ce_bs1.find_next( 2 ) == 3, "" ); 604 | static_assert( ce_bs2.find_next_zero( 2 ) == 3, "" ); 605 | static_assert( ce_bs1.find_next( 3 ) == t1::npos, "" ); 606 | static_assert( ce_bs2.find_next_zero( 3 ) == t1::npos, "" ); 607 | 608 | gen_random_bitset2 gen_rand; 609 | 610 | for( size_t c= 0; c < N; ++ c) 611 | { 612 | auto bs1= t1(); 613 | 614 | assert( bs1.find_first() == (Bitset2::bitset2::npos) ); 615 | assert( bs1.find_first_zero() == 0 ); 616 | assert( bs1.find_last() == (Bitset2::bitset2::npos) ); 617 | assert( bs1.find_last_zero() == N-1 ); 618 | assert( bs1.find_next(0) == (Bitset2::bitset2::npos) ); 619 | assert( bs1.find_next_zero(0) == 1 ); 620 | 621 | bs1[c]= true; 622 | assert( bs1.find_first() == c ); 623 | assert( bs1.find_last() == c ); 624 | if( c+1 < N ) assert( bs1.find_next_zero(c) == c+1 ); 625 | if( c > 0 ) 626 | { 627 | assert( bs1.find_next( c - 1 ) == c ); 628 | 629 | bs1[0]= true; 630 | bs1[N-1]= true; 631 | assert( bs1.find_first() == 0 ); 632 | assert( bs1.find_last() == N-1 ); 633 | if( c+2 < N ) assert( bs1.find_last_zero() == N-2 ); 634 | else if( c+1 < N ) assert( bs1.find_last_zero() == N-3 ); 635 | if( c > 1 ) assert( bs1.find_first_zero() == 1 ); 636 | else assert( bs1.find_first_zero() == 2 ); 637 | auto idx= bs1.find_next( c ); 638 | auto idx2 = bs1.find_next_zero(c); 639 | if( c + 1 < N ) 640 | { 641 | assert( idx == N - 1 ); 642 | if(c+2 < N) assert( idx2 == c+1 ); 643 | } 644 | else assert( idx == (Bitset2::bitset2::npos) ); 645 | 646 | for( size_t b= 0; b < c; ++b ) bs1[b]= true; 647 | idx= bs1.find_next( c ); 648 | if( c < N - 1 ) assert( idx == N - 1 ); 649 | else assert( idx == (Bitset2::bitset2::npos) ); 650 | } 651 | } // for c 652 | 653 | for( size_t c= 0; c < n_loops; ++c ) 654 | { 655 | auto const bs1= gen_rand(); 656 | auto const lst= idx_lst( bs1 ); 657 | if( lst.empty() ) 658 | { 659 | assert( bs1.find_first() == (Bitset2::bitset2::npos) ); 660 | assert( bs1.find_last() == (Bitset2::bitset2::npos) ); 661 | } 662 | else 663 | { 664 | auto b_it= lst.begin(); 665 | auto e_it= lst.end(); 666 | auto idx= bs1.find_first(); 667 | assert( idx == *(b_it++) ); 668 | for( ; b_it != e_it; ++b_it ) 669 | { 670 | idx= bs1.find_next( idx ); 671 | assert( idx == *b_it ); 672 | } 673 | assert( idx == bs1.find_last() ); 674 | idx= bs1.find_next( idx ); 675 | assert( idx == (Bitset2::bitset2::npos) ); 676 | } 677 | } // for c 678 | 679 | } // test_find 680 | 681 | 682 | 683 | 684 | template 685 | void 686 | test_bitwise_ops( char const * type_str ) 687 | { 688 | std::cout << "Entering test_bitwise_ops N= " << N << " type= " << type_str << "\n"; 689 | 690 | constexpr std::array ce_arr1{{ T(3), T(5) }}; 691 | constexpr std::array ce_arr2{{ T(5), T(1) }}; 692 | constexpr std::array ce_e_or{{ T(7), T(5) }}; 693 | constexpr std::array ce_e_and{{ T(1), T(1) }}; 694 | constexpr std::array ce_e_xor{{ T(6), T(4) }}; 695 | constexpr t1<74,T> ce_bs1( ce_arr1 ); 696 | constexpr t1<74,T> ce_bs2( ce_arr2 ); 697 | constexpr t1<74,T> ce_bs_e_or( ce_e_or ); 698 | constexpr t1<74,T> ce_bs_e_and( ce_e_and ); 699 | constexpr t1<74,T> ce_bs_e_xor( ce_e_xor ); 700 | constexpr auto ce_or= ce_bs1 | ce_bs2; 701 | constexpr auto ce_and= ce_bs1 & ce_bs2; 702 | constexpr auto ce_xor= ce_bs1 ^ ce_bs2; 703 | static_assert( ce_or == ce_bs_e_or, "" ); 704 | static_assert( ce_and == ce_bs_e_and, "" ); 705 | static_assert( ce_xor == ce_bs_e_xor, "" ); 706 | 707 | gen_random_bitset2 gen_rand; 708 | 709 | for( size_t c= 0; c < n_loops; ++c ) 710 | { 711 | auto const bs1= gen_rand(); 712 | auto const bs2= gen_rand(); 713 | auto const b_or= bs1 | bs2; 714 | auto const b_and= bs1 & bs2; 715 | auto const b_xor= bs1 ^ bs2; 716 | 717 | auto const sbs1= t2( bs1 ); 718 | auto const sbs2= t2( bs2 ); 719 | auto const sb_or= sbs1 | sbs2; 720 | auto const sb_and= sbs1 & sbs2; 721 | auto const sb_xor= sbs1 ^ sbs2; 722 | 723 | if( verbose ) 724 | std::cout << " " << bs1 << " op " << bs2 725 | << "\nop= |: " << b_or 726 | << "\nop= &: " << b_and 727 | << "\nop= ^: " << b_xor << "\n"; 728 | 729 | assert( sb_or == t2( b_or ) ); 730 | assert( sb_and == t2( b_and ) ); 731 | assert( sb_xor == t2( b_xor ) ); 732 | } // for c 733 | } // test_bitwise_ops 734 | 735 | 736 | 737 | 738 | template 739 | void 740 | test_reverse( char const * type_str ) 741 | { 742 | std::cout << "Entering test_reverse N= " << N << " type= " << type_str << "\n"; 743 | 744 | constexpr t1 ce_bs1( 3ull ); 745 | constexpr auto ce_bs1_rev= Bitset2::reverse( ce_bs1 ); 746 | constexpr auto ce_bs1_rot= Bitset2::rotate_right( ce_bs1, 2 ); 747 | static_assert( ce_bs1_rev == ce_bs1_rot, "" ); 748 | 749 | gen_random_bitset2 gen_rand; 750 | 751 | for( size_t c= 0; c < n_loops; ++c ) 752 | { 753 | auto const bs1= gen_rand(); 754 | auto bs2= bs1; 755 | auto const bs3= dummy_reverse( bs1 ); 756 | auto const bs4= Bitset2::reverse( bs1 ); 757 | bs2.reverse(); 758 | if( verbose ) 759 | std::cout << " " << bs1 760 | << "\n2 " << bs2 761 | << "\n3 " << bs3 << '\n'; 762 | assert( bs2 == bs3 ); 763 | assert( bs4 == bs3 ); 764 | bs2.reverse(); 765 | assert( bs2 == bs1 ); 766 | } // for c 767 | } // test_reverse 768 | 769 | 770 | 771 | template 772 | void 773 | test_convert( char const * type_str ) 774 | { 775 | std::cout << "Entering test_convert N= " << N << " type= " << type_str << "\n"; 776 | 777 | constexpr t1 ce_bs1( 0ull ); 778 | constexpr auto ce_bs2= ~ce_bs1; 779 | constexpr auto ce_bs2a= ce_bs2 >> 1; 780 | constexpr auto ce_bs2b= Bitset2::convert_to( ce_bs2 ); 781 | constexpr auto ce_bs2c= Bitset2::convert_to( ce_bs2b ); 782 | constexpr auto ce_bs2d= Bitset2::convert_to( ce_bs2 ); 783 | constexpr auto ce_bs2e= Bitset2::convert_to( ce_bs2d ); 784 | static_assert( ce_bs2c == ce_bs2a, "" ); 785 | static_assert( ce_bs2e == ce_bs2, "" ); 786 | 787 | gen_random_bitset2 gen_rand; 788 | 789 | for( size_t c= 0; c < n_loops; ++c ) 790 | { 791 | auto const bs1= gen_rand(); 792 | auto const bs2a= bs1 & ce_bs2a; 793 | auto const bs2b= Bitset2::convert_to( bs1 ); 794 | auto const bs2c= Bitset2::convert_to( bs2b ); 795 | auto const bs2d= Bitset2::convert_to( bs1 ); 796 | auto const bs2e= Bitset2::convert_to( bs2d ); 797 | assert( bs2c == bs2a ); 798 | assert( bs2e == bs1 ); 799 | 800 | auto const bs3a= Bitset2::convert_to( bs1 ); 801 | auto const bs3b= Bitset2::convert_to( bs3a ); 802 | auto const bs3c= Bitset2::convert_to( bs3a ); 803 | auto const bs4a= Bitset2::convert_to( bs1 ); 804 | auto const bs4b= Bitset2::convert_to( bs4a ); 805 | auto const bs5a= Bitset2::convert_to( bs3a ); 806 | auto const bs5b= Bitset2::convert_to( bs5a ); 807 | auto const bs5c= Bitset2::convert_to( bs5a ); 808 | assert( bs3b == bs1 ); 809 | assert( bs4b == bs1 ); 810 | assert( bs5b == bs1 ); 811 | assert( bs3c == bs5c ); 812 | 813 | const Bitset2::bitset2 bs_1a{ bs1.data() }; 814 | const Bitset2::bitset2 bs_1b{ bs1.data() }; 815 | assert( bs_1a == bs3a ); 816 | assert( bs_1b == bs4a ); 817 | } // for c 818 | } // test_convert 819 | 820 | 821 | 822 | 823 | template 824 | void 825 | test_compare( char const * type_str ) 826 | { 827 | std::cout << "Entering test_compare N= " << N << " type= " << type_str << "\n"; 828 | 829 | constexpr t1 ce_bs1( 0ull ); 830 | constexpr auto ce_bs2= ~ce_bs1; 831 | constexpr auto ce_bs2a= ce_bs2 >> 1; 832 | constexpr auto ce_bs2b= ce_bs2a; 833 | static_assert( ce_bs2a < ce_bs2, "" ); 834 | static_assert( ce_bs2b <= ce_bs2a, "" ); 835 | static_assert( ce_bs2 > ce_bs2a, "" ); 836 | static_assert( ce_bs2a >= ce_bs2b, "" ); 837 | static_assert( ce_bs2a != ce_bs2, "" ); 838 | 839 | gen_random_bitset2 gen_rand; 840 | 841 | for( size_t c= 0; c < n_loops; ++c ) 842 | { 843 | auto const bs1= gen_rand(); 844 | auto bs2= bs1; 845 | auto const bs3= bs1; 846 | --bs2; 847 | if( bs1 != ce_bs1 ) 848 | { 849 | assert( bs2 < bs1 ); 850 | assert( bs2 <= bs1 ); 851 | assert( bs1 > bs2 ); 852 | assert( bs1 >= bs1 ); 853 | } 854 | else 855 | { 856 | assert( bs1 == ce_bs1 ); 857 | } 858 | assert( bs3 <= bs1 ); 859 | assert( bs3 >= bs1 ); 860 | } // for c 861 | } // test_compare 862 | 863 | 864 | 865 | 866 | template 867 | void 868 | test_complement2( char const * type_str ) 869 | { 870 | std::cout << "Entering test_complement2 N= " << N << " type= " << type_str << "\n"; 871 | 872 | constexpr t1 zero( 0ull ); 873 | constexpr auto allset= ~zero; 874 | auto one= zero; 875 | ++one; 876 | 877 | constexpr auto ce_bs1= Bitset2::complement2( zero ); 878 | constexpr auto ce_bs2= Bitset2::complement2( allset ); 879 | auto bs1= zero; 880 | auto bs2= allset; 881 | bs1.complement2(); 882 | bs2.complement2(); 883 | static_assert( ce_bs1 == zero, "" ); 884 | assert( bs1 == zero ); 885 | assert( bs2 == one ); 886 | assert( ce_bs2 == one ); 887 | 888 | gen_random_bitset2 gen_rand; 889 | 890 | for( size_t c= 0; c < n_loops; ++c ) 891 | { 892 | auto const bs_1a= gen_rand(); 893 | auto bs_1b= bs_1a; 894 | auto const bs_1c= ~bs_1a + one; 895 | auto const bs_2a= Bitset2::complement2( bs_1a ); 896 | bs_1b.complement2(); 897 | assert( bs_1a + bs_2a == zero ); 898 | assert( bs_1a + bs_1b == zero ); 899 | assert( bs_1b == bs_1c ); 900 | } // for c 901 | } // test_complement2 902 | 903 | 904 | 905 | template 906 | void 907 | test_hash() 908 | { 909 | std::cout << "Entering test_hash N= " << N << "\n"; 910 | 911 | gen_random_bitset2 gen_rand8; 912 | gen_random_bitset2 gen_rand16; 913 | gen_random_bitset2 gen_rand32; 914 | gen_random_bitset2 gen_rand64; 915 | 916 | for( size_t c= 0; c < n_loops; ++c ) 917 | { 918 | auto const bs1_8= gen_rand8(); 919 | auto const bs1a_8= t2( bs1_8 ); 920 | auto const bs2_8= t1( bs1a_8 ); 921 | auto const bs3_8= t1( bs1a_8 ); 922 | auto const bs4_8= t1( bs1a_8 ); 923 | 924 | auto const hs1_8= std::hash >{}( bs1_8 ); 925 | auto const hs2_8= std::hash >{}( bs2_8 ); 926 | auto const hs3_8= std::hash >{}( bs3_8 ); 927 | auto const hs4_8= std::hash >{}( bs4_8 ); 928 | assert( hs1_8 == hs2_8 ); 929 | assert( hs1_8 == hs3_8 ); 930 | assert( hs1_8 == hs4_8 ); 931 | 932 | 933 | auto const bs1_16= gen_rand16(); 934 | auto const bs1a_16= t2( bs1_16 ); 935 | auto const bs2_16= t1( bs1a_16 ); 936 | auto const bs3_16= t1( bs1a_16 ); 937 | auto const bs4_16= t1( bs1a_16 ); 938 | 939 | auto const hs1_16= std::hash >{}( bs1_16 ); 940 | auto const hs2_16= std::hash >{}( bs2_16 ); 941 | auto const hs3_16= std::hash >{}( bs3_16 ); 942 | auto const hs4_16= std::hash >{}( bs4_16 ); 943 | assert( hs1_16 == hs2_16 ); 944 | assert( hs1_16 == hs3_16 ); 945 | assert( hs1_16 == hs4_16 ); 946 | 947 | 948 | auto const bs1_32= gen_rand32(); 949 | auto const bs1a_32= t2( bs1_32 ); 950 | auto const bs2_32= t1( bs1a_32 ); 951 | auto const bs3_32= t1( bs1a_32 ); 952 | auto const bs4_32= t1( bs1a_32 ); 953 | 954 | auto const hs1_32= std::hash >{}( bs1_32 ); 955 | auto const hs2_32= std::hash >{}( bs2_32 ); 956 | auto const hs3_32= std::hash >{}( bs3_32 ); 957 | auto const hs4_32= std::hash >{}( bs4_32 ); 958 | assert( hs1_32 == hs2_32 ); 959 | assert( hs1_32 == hs3_32 ); 960 | assert( hs1_32 == hs4_32 ); 961 | 962 | 963 | auto const bs1_64= gen_rand64(); 964 | auto const bs1a_64= t2( bs1_64 ); 965 | auto const bs2_64= t1( bs1a_64 ); 966 | auto const bs3_64= t1( bs1a_64 ); 967 | auto const bs4_64= t1( bs1a_64 ); 968 | 969 | auto const hs1_64= std::hash >{}( bs1_64 ); 970 | auto const hs2_64= std::hash >{}( bs2_64 ); 971 | auto const hs3_64= std::hash >{}( bs3_64 ); 972 | auto const hs4_64= std::hash >{}( bs4_64 ); 973 | assert( hs1_64 == hs2_64 ); 974 | assert( hs1_64 == hs3_64 ); 975 | assert( hs1_64 == hs4_64 ); 976 | } // for c 977 | } // test_hash 978 | 979 | 980 | 981 | int 982 | main() 983 | { 984 | std::cout << "sizeof( bitset2<8> )= " << sizeof( t1a<8> ) << '\n'; 985 | std::cout << "sizeof( bitset2<16> )= " << sizeof( t1a<16> ) << '\n'; 986 | std::cout << "sizeof( bitset2<32> )= " << sizeof( t1a<32> ) << '\n'; 987 | std::cout << "sizeof( bitset2<36> )= " << sizeof( t1a<36> ) << '\n'; 988 | std::cout << "sizeof( bitset2<36,uint8_t> )= " << sizeof( Bitset2::bitset2<36,uint8_t> ) << '\n'; 989 | std::cout << "sizeof( bitset2<64> )= " << sizeof( t1a<64> ) << '\n'; 990 | std::cout << "sizeof( bitset2<65> )= " << sizeof( t1a<65> ) << '\n'; 991 | 992 | #ifdef __SIZEOF_INT128__ 993 | gen_random_bitset2<128,unsigned __int128> gen_rand; 994 | auto const bs128_1 = gen_rand(); 995 | constexpr auto bs128_allOne = t1a<128>( (unsigned __int128)(-1) ); 996 | std::cout << " " << bs128_1 997 | << "\n = " << bs128_1.to_hex_string() << '\n'; 998 | std::cout << " " << bs128_allOne 999 | << "\n = " << bs128_allOne.to_hex_string() << '\n'; 1000 | #endif 1001 | 1002 | TESTMNY(test_rotate) 1003 | TESTMNY(test_shift) 1004 | TESTMNY(test_find) 1005 | TESTMNY(test_set_count_size) 1006 | TESTMNY(test_difference) 1007 | TESTMNY(test_bitwise_ops) 1008 | TESTMNY(test_midpoint) 1009 | TESTMNY(test_add) 1010 | TESTMNY(test_any_all_none) 1011 | TESTMNY(test_set) 1012 | TESTMNY(test_reverse) 1013 | TESTMNY(test_complement2) 1014 | TESTMNY(test_not) 1015 | TESTMNY(test_convert) 1016 | TESTMNY(test_compare) 1017 | 1018 | TESTMANY(test_hash) 1019 | } // main 1020 | --------------------------------------------------------------------------------