From 2a973b71be12723cb3275d8bdaef3eab8bbe38d9 Mon Sep 17 00:00:00 2001 From: ralfulrich <ralf.ulrich@kit.edu> Date: Wed, 28 Nov 2018 22:09:11 +0100 Subject: [PATCH] particle code conversion works now.... --- Processes/CMakeLists.txt | 2 +- Processes/Sibyll/CMakeLists.txt | 19 +- Processes/Sibyll/ParticleConversion.h | 21 +- Processes/Sibyll/code_generator.py | 54 +- Processes/Sibyll/testSibyll.cc | 4 +- ThirdParty/CMakeLists.txt | 1 + ThirdParty/ThirdParty.dox | 19 +- ThirdParty/bitset2/LICENSE.txt | 23 + ThirdParty/bitset2/README.md | 232 +++++ ThirdParty/bitset2/bitset2.hpp | 646 +++++++++++++ ThirdParty/bitset2/detail/array2array.hpp | 122 +++ ThirdParty/bitset2/detail/array2u_long_t.hpp | 110 +++ ThirdParty/bitset2/detail/array_access.hpp | 82 ++ ThirdParty/bitset2/detail/array_add.hpp | 153 +++ .../bitset2/detail/array_complement2.hpp | 149 +++ ThirdParty/bitset2/detail/array_funcs.hpp | 346 +++++++ ThirdParty/bitset2/detail/array_ops.hpp | 336 +++++++ ThirdParty/bitset2/detail/bit_chars.hpp | 65 ++ ThirdParty/bitset2/detail/bitset2_impl.hpp | 400 ++++++++ ThirdParty/bitset2/detail/count_bits.hpp | 45 + ThirdParty/bitset2/detail/h_types.hpp | 107 +++ ThirdParty/bitset2/detail/hash.hpp | 126 +++ ThirdParty/bitset2/detail/hex_params.hpp | 54 ++ ThirdParty/bitset2/detail/index_lsb_set.hpp | 73 ++ ThirdParty/bitset2/detail/reverse_bits.hpp | 66 ++ ThirdParty/bitset2/detail/select_base_t.hpp | 82 ++ ThirdParty/bitset2/detail/ullong2array.hpp | 80 ++ ThirdParty/bitset2/tests/bench01.cpp | 131 +++ ThirdParty/bitset2/tests/counter128.cpp | 29 + ThirdParty/bitset2/tests/example01.cpp | 52 + ThirdParty/bitset2/tests/gen_randoms.hpp | 108 +++ ThirdParty/bitset2/tests/gray_code.cpp | 50 + ThirdParty/bitset2/tests/mk.sh | 43 + ThirdParty/bitset2/tests/test_array2array.cpp | 111 +++ ThirdParty/bitset2/tests/test_bitset2_01.cpp | 420 ++++++++ ThirdParty/bitset2/tests/test_bitset2_02.cpp | 49 + .../tests/test_nonconst_constexpr01.cpp | 172 ++++ .../bitset2/tests/test_ullong2array.cpp | 127 +++ ThirdParty/bitset2/tests/tests01.cpp | 903 ++++++++++++++++++ 39 files changed, 5570 insertions(+), 42 deletions(-) create mode 100644 ThirdParty/bitset2/LICENSE.txt create mode 100644 ThirdParty/bitset2/README.md create mode 100644 ThirdParty/bitset2/bitset2.hpp create mode 100644 ThirdParty/bitset2/detail/array2array.hpp create mode 100644 ThirdParty/bitset2/detail/array2u_long_t.hpp create mode 100644 ThirdParty/bitset2/detail/array_access.hpp create mode 100644 ThirdParty/bitset2/detail/array_add.hpp create mode 100644 ThirdParty/bitset2/detail/array_complement2.hpp create mode 100644 ThirdParty/bitset2/detail/array_funcs.hpp create mode 100644 ThirdParty/bitset2/detail/array_ops.hpp create mode 100644 ThirdParty/bitset2/detail/bit_chars.hpp create mode 100644 ThirdParty/bitset2/detail/bitset2_impl.hpp create mode 100644 ThirdParty/bitset2/detail/count_bits.hpp create mode 100644 ThirdParty/bitset2/detail/h_types.hpp create mode 100644 ThirdParty/bitset2/detail/hash.hpp create mode 100644 ThirdParty/bitset2/detail/hex_params.hpp create mode 100644 ThirdParty/bitset2/detail/index_lsb_set.hpp create mode 100644 ThirdParty/bitset2/detail/reverse_bits.hpp create mode 100644 ThirdParty/bitset2/detail/select_base_t.hpp create mode 100644 ThirdParty/bitset2/detail/ullong2array.hpp create mode 100644 ThirdParty/bitset2/tests/bench01.cpp create mode 100644 ThirdParty/bitset2/tests/counter128.cpp create mode 100644 ThirdParty/bitset2/tests/example01.cpp create mode 100644 ThirdParty/bitset2/tests/gen_randoms.hpp create mode 100644 ThirdParty/bitset2/tests/gray_code.cpp create mode 100755 ThirdParty/bitset2/tests/mk.sh create mode 100644 ThirdParty/bitset2/tests/test_array2array.cpp create mode 100644 ThirdParty/bitset2/tests/test_bitset2_01.cpp create mode 100644 ThirdParty/bitset2/tests/test_bitset2_02.cpp create mode 100644 ThirdParty/bitset2/tests/test_nonconst_constexpr01.cpp create mode 100644 ThirdParty/bitset2/tests/test_ullong2array.cpp create mode 100644 ThirdParty/bitset2/tests/tests01.cpp diff --git a/Processes/CMakeLists.txt b/Processes/CMakeLists.txt index c59cafa4..c8f8557b 100644 --- a/Processes/CMakeLists.txt +++ b/Processes/CMakeLists.txt @@ -1,6 +1,6 @@ add_subdirectory (NullModel) -#add_subdirectory (Sibyll) +add_subdirectory (Sibyll) add_subdirectory (StackInspector) #add_custom_target(CORSIKAprocesses) diff --git a/Processes/Sibyll/CMakeLists.txt b/Processes/Sibyll/CMakeLists.txt index cd745af0..f2e4a9fe 100644 --- a/Processes/Sibyll/CMakeLists.txt +++ b/Processes/Sibyll/CMakeLists.txt @@ -7,7 +7,7 @@ add_custom_command ( sibyll_codes.dat ${PROJECT_BINARY_DIR}/Framework/Particles/pythia_db.pkl WORKING_DIRECTORY - ${PROJECT_BINARY_DIR}/Processes/Sibyll/Particles/ + ${PROJECT_BINARY_DIR}/Processes/Sibyll/ COMMENT "Generate conversion tables for particle codes SIBYLL <-> CORSIKA" VERBATIM ) @@ -31,6 +31,21 @@ set ( add_library (ProcessSibyll STATIC ${MODEL_SOURCES}) CORSIKA_COPY_HEADERS_TO_NAMESPACE (ProcessSibyll ${MODEL_NAMESPACE} ${MODEL_HEADERS}) +# .................................................... +# since Generated.inc is an automatically produced file in the build directory, +# create a symbolic link into the source tree, so that it can be found and edited more easily +# this is not needed for the build to succeed! ....... +add_custom_command ( + OUTPUT ${CMAKE_CURRENT_SOURCE_DIR}/Generated.inc + COMMAND ${CMAKE_COMMAND} -E create_symlink ${PROJECT_BINARY_DIR}/include/corsika/process/sibyll/Generated.inc ${CMAKE_CURRENT_SOURCE_DIR}/Generated.inc + COMMENT "Generate link in source-dir: ${CMAKE_CURRENT_SOURCE_DIR}/Generated.inc" + ) +add_custom_target (SourceDirLink2 DEPENDS ${PROJECT_BINARY_DIR}/Processes/Sibyll/Generated.inc) +add_dependencies (ProcessSibyll SourceDirLink2) +# ..................................................... + + + set_target_properties ( ProcessSibyll PROPERTIES @@ -42,7 +57,9 @@ set_target_properties ( # target dependencies on other libraries (also the header onlys) target_link_libraries ( ProcessSibyll + CORSIKAparticles CORSIKAunits + CORSIKAthirdparty ) target_include_directories ( diff --git a/Processes/Sibyll/ParticleConversion.h b/Processes/Sibyll/ParticleConversion.h index aa9db1f2..2ad00701 100644 --- a/Processes/Sibyll/ParticleConversion.h +++ b/Processes/Sibyll/ParticleConversion.h @@ -14,27 +14,30 @@ #include <corsika/particles/ParticleProperties.h> +#include <bitset2/bitset2.hpp> + #include <map> namespace corsika::process::sibyll { + enum class Code : int8_t; - using PIDIntType = std::underlying_type<Code>::type; + using SibyllCodeIntType = std::underlying_type<Code>::type; -#include <corsika/processes/sibyll/Generated.inc> +#include <corsika/process/sibyll/Generated.inc> - bool handledBySibyll(corsika::particles::Code pCode) { - return handleable[static_cast<CodeIntType>(pCode)]; + bool HandledBySibyll(corsika::particles::Code pCode) { + return handleable[static_cast<corsika::particles::CodeIntType>(pCode)]; } - + Code constexpr ConvertToSibyll(corsika::particles::Code pCode) { //~ assert(handledBySibyll(pCode)); - return static_cast<Code>(corsika2sibyll[static_cast<CodeIntType>(pCode)]); + return static_cast<Code>(corsika2sibyll[static_cast<corsika::particles::CodeIntType>(pCode)]); } - + corsika::particles::Code constexpr ConvertFromSibyll(Code pCode) { - return sibyll2corsika[static_cast<PIDIntType>(pCode) - minSibyll]; + return sibyll2corsika[static_cast<SibyllCodeIntType>(pCode) - minSibyll]; } - + } // namespace corsika::process::sibyll #endif diff --git a/Processes/Sibyll/code_generator.py b/Processes/Sibyll/code_generator.py index a51deef0..dc082cdb 100755 --- a/Processes/Sibyll/code_generator.py +++ b/Processes/Sibyll/code_generator.py @@ -12,12 +12,14 @@ import pickle, sys, itertools + # loads the pickled pythia_db (which is an OrderedDict) def load_pythiadb(filename): with open(filename, "rb") as f: pythia_db = pickle.load(f) return pythia_db - + + # def read_sibyll_codes(filename, pythia_db): @@ -31,21 +33,23 @@ def read_sibyll_codes(filename, pythia_db): pythia_db[identifier]["sibyll_code"] = int(sib_code) except KeyError as e: raise Exception("Identifier '{:s}' not found in pythia_db".format(identifier)) - + + # generates the enum to access sibyll particles by readable names def generate_sibyll_enum(pythia_db): - output = "enum class PID : int16_t {\n" + output = "enum class Code : int8_t {\n" for identifier, d in pythia_db.items(): if d.get('sibyll_code') != None: output += " {:s} = {:d},\n".format(identifier, d['sibyll_code']) output += "};\n" return output - + + # generates the look-up table to convert corsika codes to sibyll codes def generate_corsika2sibyll(pythia_db): - string = "std::array<PIDIntType, {:d}> constexpr corsika2sibyll = {{".format(len(pythia_db)) + string = "std::array<SibyllCodeIntType, {:d}> constexpr corsika2sibyll = {{".format(len(pythia_db)) for identifier, d in pythia_db.items(): sibCode = d.get("sibyll_code", 0) string += " {:d}, // {:s}\n".format(sibCode, identifier if sibCode else identifier + " (not implemented in SIBYLL)") @@ -53,30 +57,32 @@ def generate_corsika2sibyll(pythia_db): return string + # generates the look-up table to convert sibyll codes to corsika codes -def generate_sibyll2corsika(pythia_db): - d = {} - for identifier, p in pythia_db.items(): - if 'sibyll_code' in p: - sib_code = p['sibyll_code'] - corsika_code = p['ngc_code'] - d[sib_code] = (corsika_code, identifier) - - string = "std::array<corsika::particles::CodeIntType, {:d}> sibyll2corsika = {{\n".format(len(d)) +def generate_sibyll2corsika(pythia_db) : + pDict = {} + for identifier, pData in pythia_db.items() : + if 'sibyll_code' in pData: + sib_code = pData['sibyll_code'] + # corsika_code = pData['ngc_code'] + #d[sib_code] = (corsika_code, identifier) + pDict[sib_code] = identifier + + nPart = max(pDict.keys()) - min(pDict.keys()) + 1 + string = "std::array<corsika::particles::Code, {:d}> sibyll2corsika = {{\n".format(nPart) - for k in range(min(d.keys()), max(d.keys())+1): - if k in d: - corsika_code = d[k][0] - identifier = d[k][1] + for iPart in range(nPart) : + if iPart in pDict: + identifier = pDict[iPart] else: - corsika_code = 0 - identifier = "" - string += " {:d}, // {:s}\n".format(corsika_code, identifier) + identifier = "Unknown" + string += " corsika::particles::Code::{:s}, \n".format(identifier) string += "};\n" - string += "PIDIntType constexpr minSibyll = {:d};\n".format(min(d.keys())) + string += "SibyllCodeIntType constexpr minSibyll = {:d};\n".format(min(pDict.keys())) return string - + + # generates the bitset for the flag whether Sibyll knows the particle def generate_handles_particle(pythia_db): @@ -98,6 +104,7 @@ def generate_handles_particle(pythia_db): return string + if __name__ == "__main__": if len(sys.argv) != 3: print("usage: {:s} <pythia_db.pkl> <sibyll_codes.dat>".format(sys.argv[0]), file=sys.stderr) @@ -106,7 +113,6 @@ if __name__ == "__main__": print("code_generator.py for SIBYLL") pythia_db = load_pythiadb(sys.argv[1]) - read_sibyll_codes(sys.argv[2], pythia_db) with open("Generated.inc", "w") as f: diff --git a/Processes/Sibyll/testSibyll.cc b/Processes/Sibyll/testSibyll.cc index 86fec314..48420c26 100644 --- a/Processes/Sibyll/testSibyll.cc +++ b/Processes/Sibyll/testSibyll.cc @@ -32,9 +32,9 @@ TEST_CASE("Sibyll", "[processes]") { } SECTION("handledBySibyll") { - REQUIRE(process::sibyll::handledBySibyll(corsika::particles::Electron::GetCode())); + REQUIRE(process::sibyll::HandledBySibyll(corsika::particles::Electron::GetCode())); REQUIRE_FALSE( - process::sibyll::handledBySibyll(corsika::particles::XiPrimeC0::GetCode())); + process::sibyll::HandledBySibyll(corsika::particles::XiPrimeC0::GetCode())); } } diff --git a/ThirdParty/CMakeLists.txt b/ThirdParty/CMakeLists.txt index c7f90c5b..fb6c08fc 100644 --- a/ThirdParty/CMakeLists.txt +++ b/ThirdParty/CMakeLists.txt @@ -9,3 +9,4 @@ target_include_directories (CORSIKAthirdparty SYSTEM install (DIRECTORY phys DESTINATION include/ThirdParty/) install (DIRECTORY catch2 DESTINATION include/ThirdParty/) +install (DIRECTORY bitset2 DESTINATION include/ThirdParty/) diff --git a/ThirdParty/ThirdParty.dox b/ThirdParty/ThirdParty.dox index ec0e3de3..a7e46398 100644 --- a/ThirdParty/ThirdParty.dox +++ b/ThirdParty/ThirdParty.dox @@ -10,23 +10,32 @@ the individual copyrights and licences here! @section PhysUnits The PhysUnits library is an external dependency included here just for -convenience: +convenience: -Original source code from: https://github.com/martinmoene/PhysUnits-CT-Cpp11#references +Original source code from: +https://github.com/martinmoene/PhysUnits-CT-Cpp11#references -Licence: BSL-1.0 (https://github.com/martinmoene/PhysUnits-CT-Cpp11/blob/master/LICENSE_1_0.txt) +Licence: BSL-1.0 +(https://github.com/martinmoene/PhysUnits-CT-Cpp11/blob/master/LICENSE_1_0.txt) References: https://github.com/martinmoene/PhysUnits-CT-Cpp11#references @section catch2 -The catch2 unit testing library is from: https://github.com/catchorg/Catch2 -Licence: BSL-1.0 (https://github.com/martinmoene/PhysUnits-CT-Cpp11/blob/master/LICENSE_1_0.txt) +The catch2 unit testing library is from: +https://github.com/catchorg/Catch2 Licence: BSL-1.0 +(https://github.com/martinmoene/PhysUnits-CT-Cpp11/blob/master/LICENSE_1_0.txt) References: https://github.com/catchorg/Catch2 @section eigen3 eigen3 .... +@section bitset2 + +see https://github.com/ClaasBontus/bitset2, this package was obtained +from a Boost Software License 1.0. + + */ diff --git a/ThirdParty/bitset2/LICENSE.txt b/ThirdParty/bitset2/LICENSE.txt new file mode 100644 index 00000000..36b7cd93 --- /dev/null +++ b/ThirdParty/bitset2/LICENSE.txt @@ -0,0 +1,23 @@ +Boost Software License - Version 1.0 - August 17th, 2003 + +Permission is hereby granted, free of charge, to any person or organization +obtaining a copy of the software and accompanying documentation covered by +this license (the "Software") to use, reproduce, display, distribute, +execute, and transmit the Software, and to prepare derivative works of the +Software, and to permit third-parties to whom the Software is furnished to +do so, all subject to the following: + +The copyright notices in the Software and this entire statement, including +the above license grant, this restriction and the following disclaimer, +must be included in all copies of the Software, in whole or in part, and +all derivative works of the Software, unless such copies or derivative +works are solely in the form of machine-executable object code generated by +a source language processor. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. diff --git a/ThirdParty/bitset2/README.md b/ThirdParty/bitset2/README.md new file mode 100644 index 00000000..5e7f2f9e --- /dev/null +++ b/ThirdParty/bitset2/README.md @@ -0,0 +1,232 @@ +# bitset2: bitset improved + +|Note| +|----| +|This version of bitset2 is for C++17. For C++14 checkout the corresponding [branch](https://github.com/ClaasBontus/bitset2/tree/cpp14).| + +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 +following extentions/changes. + + +Focus was set on having as many functions +implemented as [constexpr](http://en.cppreference.com/w/cpp/language/constexpr) +as possible. Moreover a second template parameter (with appropriate default) +allows control of the underlying data structure (see below). +* Copy and move constructors are specified constexpr. +* Additional constexpr constructor `bitset2( std::array<T,N> const & )`, where `T` needs not necessarily be equal to `base_t`. `T` has to be an unsigned integral type. +* Conversion from and to `std::bitset`. +* Operators implemented as constexpr are `~`, `==`, `!=`, `|`, `&`, `^`, `<<` (shift left), `>>` (shift right), `[]` (bit access). +* Non-const operators implemented as constexpr are `<<=`, `>>=`, `|=`, `&=`, `^=` +* Functions implemented as constexpr are `test`, `none`, `any`, `all`, `count`, `to_ulong`, `to_ullong`. +* Non-const functions implemented as constexpr are `set`, `reset`, `flip`. +* Additional constexpr operator `+` for adding two bitset2 objects. +* Additional constexpr operators `++`, `--`, `+=`. +* Additional constexpr operators `<`, `>`, `<=`, `>=`. +* Additional constexpr functions `rotate_left` and `rotate_right` for binary rotations. +* Additional constexpr member functions `rotate_left` and `rotate_right`. +* Additional member function `to_hex_string()` (see below). +* 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. +* Additional constexpr function `difference`, which computes the set difference (`bs1 & ~bs2`) of two bitset2 objects. +* Additional constexpr member function `difference`. +* Additional constexpr member functions `find_first()` and `find_next(size_t)` returning the index of the first (next) bit set. Returning npos if all (remaining) bits are false. +* Additional constexpr function `complement2(bs)` computing the [two's complement](https://en.wikipedia.org/wiki/Two%27s_complement) (~bs +1). +* Additional constexpr member function `complement2`. +* Additional constexpr function `reverse`, which returns argument with bits reversed. +* Additional constexpr member function `reverse`. +* Additional constexpr function `convert_to<n>` for converting an *m*-bit bitset2 into an *n*-bit bitset2. +* Additional constexpr function `convert_to<n,T>` for converting an *m*-bit bitset2 into an *n*-bit bitset2 with `base_t=T`. +* Constexpr member function `data()` gives read access to the underlying `array<base_t,N>`. Here element with index zero is the least significant word. +* Additional constexpr functions `zip_fold_and` and `zip_fold_or`. See below for details. + +## Examples +```.cpp +#include <iostream> +#include <array> +#include <cassert> +#include "bitset2.hpp" + +template<size_t n_bits> +using BS2= Bitset2::bitset2<n_bits>; + +int main() +{ + using bs_128= BS2<128>; + using base_t_128= bs_128::base_t; + constexpr std::array<base_t_128,2> + ar1{{ ~(base_t_128(0)), base_t_128(0xFEDCBA) }}; + constexpr bs_128 b1{ ar1 }; + constexpr auto b1_add= b1 + b1; + constexpr auto b1_shft= b1 << 1; // binary shift + static_assert( b1_add == b1_shft, "" ); + + std::cout << b1.to_hex_string() // 0000000000fedcbaffffffffffffffff + << "\n" + << b1_add.to_hex_string() // 0000000001fdb975fffffffffffffffe + << "\n"; + + BS2<12> b2; + for( size_t c= 0; c < 12; c += 2 ) b2[c]= true; + auto b3= ~b2; + std::cout << b2 << "\n"; // 010101010101 + std::cout << b2.flip() << "\n"; // 101010101010 + assert( b2 == b3 ); + + BS2<7> const b4{ "1110000" }; + auto const b5= Bitset2::rotate_left( b4, 3 ); + std::cout << b4 << "\n" // 1110000 + << b5 << "\n"; // 0000111 + + BS2<7> b6{ "1010010" }; + b6.reverse(); + std::cout << b6 << "\n"; // 0100101 +} +``` + +The following example illustrates how +[non-const constexpr](https://stackoverflow.com/q/43592862/3876684) +operators and functions are useful for writing constexpr functions. +It converts between [gray](https://en.wikipedia.org/wiki/Gray_code) +and binary coding. + +```.cpp +template<size_t N,class T> +constexpr +Bitset2::bitset2<N,T> +binary_to_gray( Bitset2::bitset2<N,T> const &bs ) +{ return bs ^ (bs >> 1); } + +template<size_t N,class T> +constexpr +Bitset2::bitset2<N,T> +gray_to_binary( Bitset2::bitset2<N,T> bs ) +{ + Bitset2::bitset2<N,T> mask= bs >> 1; + for( ; !mask.none(); mask >>= 1 ) bs ^= mask; + return bs; +} // gray_to_binary + +int main() +{ + using ULLONG= unsigned long long; + constexpr std::array<ULLONG,2> arr_01a{{ 0xFEFDFCFBFAF9F8F7ull, 1ull }}; + constexpr Bitset2::bitset2<129> bs_01a{ arr_01a }; + constexpr auto gray_01a= binary_to_gray( bs_01a ); + constexpr auto bin_01a= gray_to_binary( gray_01a ); + + static_assert( bs_01a == bin_01a, "" ); +} +``` + +## Template parameters and underlying data type +`bitset2` is declared as +```.cpp +template< size_t N, class T > +class bitset2; +``` +`N` is the number of bits and `T` has to be an unsigned +[integral type](http://en.cppreference.com/w/cpp/types/is_integral). Data +represented by `bitset2` objects are stored in elements of type +`std::array<T,n_array>`. + +`T` defaults +to `uint8_t`, `uint16_t`, or `uint32_t` if `N` bits fit into these integers +(and the type is supported by the system). +`T` defaults to `unsigned long long` otherwise. The following aliases and +constants are public within `bitset2`: +* `using base_t= T;` +* `size_t n_array;` Number of words in underlying array +* `using array_t= std::array<T,n_array>;` Underlying data type + +## to_hex_string +Function `to_hex_string` takes - as an optional argument - an element of type +`hex_params`, which is defined as +```.cpp +template< class CharT = char, + class Traits = std::char_traits<CharT>, + class Allocator = std::allocator<CharT> > +struct hex_params +{ + using str_t= std::basic_string<CharT,Traits,Allocator>; + + CharT zeroCh= CharT( '0' ); + CharT aCh= CharT( 'a' ); + bool leadingZeroes= true; + bool nonEmpty= true; + str_t prefix; +}; +``` +It allows fine tuning the outcome of the function. In the following +examples the output is shown in the comments. +```.cpp +bitset2<16> b16_a( "0000101000011111" ); +bitset2<16> b16_b; +std::cout + << b16_a.to_hex_string() << '\n' // 0a1f + << b16_a.to_hex_string( hex_params<>{'0', 'A', false, true, "0x"}) // 0xA1F + << '\n' + << b16_b.to_hex_string() << '\n' // 0000 + << b16_b.to_hex_string( hex_params<>{'0', 'a', false, false, "0X"}) // 0X + << '\n'; +``` + +## zip\_fold\_* +Functions `zip_fold_and(bs1,bs2,f)` and `zip_fold_or(bs1,bs2,f)` expect two +variables of type `bitset2` and a functional object `f`. +The latter must accept two variables of type `base_t` and return a `bool`. +`zip_fold_*` are mapped over the underlying +`std::array<base_t,n>`s. They will +[short-circuit](http://en.cppreference.com/w/cpp/language/operator_logical) +if possible, which can result in performance advantages. +`zip_fold_and` returns `true` if `f` +returns `true` for each pair of `base_t`s, while `zip_fold_or` returns `true` +if `f` returns `true` for at least one pair of `base_t`s. +In other words `zip_fold_and` and `zip_fold_or` are similar to +[`std::inner_product(...,BinOp1 op1,BinOp2 op2)`](http://en.cppreference.com/w/cpp/algorithm/inner_product) +with `op1` set to `&&` and `||`, resp. + +For instance `is_subset_of` as proposed in [p0125r0](http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/p0125r0.html) +can be implemented as follows. +```.cpp +template<size_t N,class T> +constexpr +bool +is_subset_of( Bitset2::bitset2<N,T> const &bs1, + Bitset2::bitset2<N,T> const &bs2 ) noexcept +{ + using base_t= T; + return Bitset2::zip_fold_and( bs1, bs2, + []( base_t v1, base_t v2 ) noexcept + // Any bit unset in v2 must not be set in v1 + { return (v1 & ~v2) == 0; } ); +} + +constexpr Bitset2::bitset2<7> b7_a( 0b1000101ull ); +constexpr Bitset2::bitset2<7> b7_b( 0b1010101ull ); +static_assert( is_subset_of( b7_a, b7_b), "" ); +``` + +Similarly an `unequal` function can be defined as +```.cpp +template<size_t N,class T> +bool +unequal( Bitset2::bitset2<N,T> const &bs1, Bitset2::bitset2<N,T> const &bs2 ) +{ + using base_t= T; + return Bitset2::zip_fold_or( bs1, bs2, + []( base_t v1, base_t v2 ) noexcept + { return v1 != v2; } ); +} +``` + +## Trivia +The following code shows a counter based on a 128-bit integer. If the +counter gets incremented once at each nanosecond, you have to wait for +overflow for *only* [1.078 * 10<sup>22</sup> years](http://www.wolframalpha.com/input/?i=2%5E128+nanoseconds). +```.cpp +Bitset2::bitset2<128> c; +for( ;; ++c ) {} +``` + +## Caveats +* bitset2 requires a C++17 compliant compiler. +* Tested with gcc 7 and clang 5. diff --git a/ThirdParty/bitset2/bitset2.hpp b/ThirdParty/bitset2/bitset2.hpp new file mode 100644 index 00000000..0b9c95aa --- /dev/null +++ b/ThirdParty/bitset2/bitset2.hpp @@ -0,0 +1,646 @@ +// BITSET2 +// +// Copyright Claas Bontus +// +// Use, modification and distribution is subject to the +// Boost Software License, Version 1.0. (See accompanying +// file LICENSE.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// +// Project home: https://github.com/ClaasBontus/bitset2 +// + + +#ifndef BITSET2_CB_HPP +#define BITSET2_CB_HPP + + +#include "detail/hex_params.hpp" +#include "detail/select_base_t.hpp" +#include "detail/hash.hpp" +#include "detail/array_access.hpp" +#include "detail/array_funcs.hpp" +#include "detail/array_add.hpp" +#include "detail/array_ops.hpp" +#include "detail/array_complement2.hpp" +#include "detail/array2array.hpp" +#include "detail/bitset2_impl.hpp" + +#include <bitset> +#include <climits> +#include <cstdint> +#include <array> +#include <stdexcept> +#include <utility> +#include <string> +#include <functional> +#include <type_traits> + + + +namespace Bitset2 +{ + + + +template<size_t N, + class T= Bitset2::detail::select_base_t<N>, + class Enabled=void> class bitset2; + +template<size_t N,class T> +class bitset2<N,T, + typename std::enable_if< std::is_integral<T>::value + && std::is_unsigned<T>::value>::type> +: public detail::bitset2_impl<N,T> +{ + enum : size_t { base_t_n_bits= detail::bitset2_impl<N,T>::base_t_n_bits }; +public: + using array_t= typename detail::bitset2_impl<N,T>::array_t; + using ULLONG_t= typename detail::bitset2_impl<N,T>::ULLONG_t; + using base_t= T; + using detail::bitset2_impl<N,T>::n_array; + + enum : size_t { npos= detail::h_types<T>::npos }; + + class reference + { + friend class bitset2; + reference() noexcept {} + reference( bitset2<N,T> *ptr, size_t bit ) noexcept + : m_ptr( ptr ) + , m_bit( bit ) + {} + bitset2<N,T> *m_ptr= nullptr; + size_t m_bit; + public: + ~reference() noexcept {} + reference& operator=( bool x ) noexcept + { + m_ptr->set_noexcept( m_bit, x ); + return *this; + } + reference& operator=( reference const & r ) noexcept + { + m_ptr->set_noexcept( m_bit, bool( r ) ); + return *this; + } + reference& flip() noexcept + { + m_ptr->flip_noexcept( m_bit ); + return *this; + } + operator bool() const noexcept + { return m_ptr->test_noexcept(m_bit); } + bool operator~() const noexcept + { return !bool(*this); } + }; // class reference + + + /* ------------------------------------------------------------- */ + constexpr + bitset2() noexcept + : detail::bitset2_impl<N,T>() + {} + + constexpr + bitset2( bitset2 const & ) noexcept= default; + + constexpr + bitset2( bitset2 && ) noexcept= default; + + constexpr + bitset2 & + operator=( bitset2 const & ) noexcept= default; + + constexpr + bitset2 & + operator=( bitset2 && ) noexcept= default; + + explicit + bitset2( const std::bitset<N> &bs ) noexcept + : detail::bitset2_impl<N,T>( bs ) + {} + + explicit + constexpr + bitset2( ULLONG_t v ) noexcept + : detail::bitset2_impl<N,T>( v ) + {} + + template<size_t n,class Tsrc> + explicit + constexpr + bitset2( std::array<Tsrc,n> const & value ) noexcept + : detail::bitset2_impl<N,T>( value ) + {} + + template< class CharT, class Traits, class Alloc > + explicit + bitset2( std::basic_string<CharT,Traits,Alloc> const + & str, + typename std::basic_string<CharT,Traits,Alloc>::size_type + pos = 0, + typename std::basic_string<CharT,Traits,Alloc>::size_type + n = std::basic_string<CharT,Traits,Alloc>::npos, + CharT zero= CharT('0'), + CharT one= CharT('1') ) + : detail::bitset2_impl<N,T>( str, pos, n, zero, one ) + {} + + + template< class CharT > + explicit + bitset2( const CharT *str, + typename std::basic_string<CharT>::size_type + n= std::basic_string<CharT>::npos, + CharT zero= CharT('0'), + CharT one= CharT('1') ) + : detail::bitset2_impl<N,T>( n == std::basic_string<CharT>::npos + ? std::basic_string<CharT>( str ) + : std::basic_string<CharT>( str, n ), + 0, n, zero, one ) + {} + /* ------------------------------------------------------------- */ + + + //**************************************************** + + /// Bitwise NOT + constexpr + bitset2 + operator~() const noexcept + { return bitset2(detail::array_ops<N,T>( 0 ).flip(this->data())); } + + constexpr + bool + operator[]( size_t bit ) const noexcept + { return detail::bitset2_impl<N,T>::operator[]( bit ); } + + reference + operator[]( size_t bit ) noexcept + { return reference( this, bit ); } + + constexpr + bitset2 & + operator<<=( size_t n_shift ) noexcept + { + detail::array_ops<N,T>( n_shift ).shift_left_assgn( this->get_data() ); + return *this; + } + + constexpr + bitset2 & + operator>>=( size_t n_shift ) noexcept + { + detail::array_ops<N,T>( n_shift ).shift_right_assgn( this->get_data() ); + return *this; + } + + constexpr + bitset2 & + rotate_left( size_t n_rot ) noexcept + { + this->get_data()= detail::array_ops<N,T>(n_rot).rotate_left( this->data() ); + return *this; + } + + constexpr + bitset2 & + rotate_right( size_t n_rot ) noexcept + { + this->get_data()= detail::array_ops<N,T>( N - ( n_rot % N ) ) + .rotate_left( this->data() ); + return *this; + } + + constexpr + bitset2 & + reverse() noexcept + { + this->get_data()= detail::array_ops<N,T>( 0 ).reverse( this->data() ); + return *this; + } + + /// Computes two's complement + constexpr + bitset2 & + complement2() noexcept + { + detail::array_complement2<N,T>().comp2_assgn( this->get_data() ); + return *this; + } + + constexpr + bitset2 & + operator+=( bitset2 const &bs2 ) noexcept + { + detail::array_add<N,T>().add_assgn(this->get_data(), bs2.data()); + return *this; + } + + constexpr + bitset2 & + operator++() noexcept + { + detail::array_ops<N,T>(0).increment( this->get_data() ); + return *this; + } + + constexpr + bitset2 + operator++(int) noexcept + { + bitset2 tmp( *this ); + operator++(); + return tmp; + } + + constexpr + bitset2 & + operator--() noexcept + { + detail::array_ops<N,T>(0).decrement( this->get_data() ); + return *this; + } + + constexpr + bitset2 + operator--(int) noexcept + { + bitset2 tmp( *this ); + operator--(); + return tmp; + } + + constexpr + bitset2 & + operator|=( bitset2 const & v2 ) noexcept + { + detail::array_funcs<bitset2::n_array,T>() + .bitwise_or_assgn(this->get_data(), v2.data() ); + return *this; + } + + constexpr + bitset2 & + operator&=( bitset2 const & v2 ) noexcept + { + detail::array_funcs<bitset2::n_array,T>() + .bitwise_and_assgn( this->get_data(), v2.data() ); + return *this; + } + + constexpr + bitset2 & + operator^=( bitset2 const & v2 ) noexcept + { + detail::array_funcs<bitset2::n_array,T>() + .bitwise_xor_assgn( this->get_data(), v2.data() ); + return *this; + } + + /// Computes the set difference, i.e. *this &= ~v2 + constexpr + bitset2 & + difference( bitset2 const & v2 ) noexcept + { + detail::array_funcs<bitset2::n_array,T>() + .bitwise_setdiff_assgn( this->get_data(), v2.data() ); + return *this; + } + + constexpr + bitset2 & + set() noexcept + { detail::bitset2_impl<N,T>::set(); return *this; } + + constexpr + bitset2 & + set( size_t bit, bool value= true ) + { detail::bitset2_impl<N,T>::set( bit, value ); return *this; } + + constexpr + bitset2 & + reset() noexcept + { detail::bitset2_impl<N,T>::reset(); return *this; } + + constexpr + bitset2 & + reset( size_t bit ) + { + if( bit >= N ) throw std::out_of_range( "bitset2: reset out of range" ); + return set( bit, false ); + } + + /// \brief Sets the specified bit if value==true, + /// clears it otherwise. Returns the previous state of the bit. + constexpr + bool + test_set( size_t bit, bool value= true ) + { return detail::bitset2_impl<N,T>::test_set( bit, value ); } + + constexpr + bitset2 & + flip() noexcept + { detail::bitset2_impl<N,T>::flip(); return *this; } + + constexpr + bitset2 & + flip( size_t bit ) + { detail::bitset2_impl<N,T>::flip( bit ); return *this; } + + constexpr std::size_t size() const noexcept { return N; } + + template<class CharT = char, + class Traits = std::char_traits<CharT>, + class Allocator = std::allocator<CharT> > + std::basic_string<CharT,Traits,Allocator> + to_string( CharT zero = CharT('0'), CharT one = CharT('1') ) const + { + std::basic_string<CharT,Traits,Allocator> ret_val; + ret_val.reserve( N ); + for( size_t ct= N; ct > 0; ) + { + --ct; + ret_val += this->operator[]( ct ) ? one : zero; + } + return ret_val; + } // to_string + + template<class CharT = char, + class Traits = std::char_traits<CharT>, + class Allocator = std::allocator<CharT>, + typename std::enable_if<base_t_n_bits % 4 == 0>::type* = nullptr > + std::basic_string<CharT,Traits,Allocator> + to_hex_string( hex_params<CharT,Traits,Allocator> const ¶ms= + hex_params<CharT,Traits,Allocator>{} ) const + { + using arr_acc= detail::array_access<N,T>; + arr_acc a_a; + constexpr auto div_four= arr_acc::div_four; + constexpr auto mod_four= arr_acc::mod_four; + constexpr auto n_char= div_four + ( mod_four > 0 ); + + auto const zeroCh= params.zeroCh; + auto const aCh= params.aCh; + + std::basic_string<CharT,Traits,Allocator> ret_val; + ret_val.reserve( n_char + params.prefix.size() ); + ret_val= params.prefix; + size_t ct= n_char; + if( !params.leadingZeroes ) + { + for( ; ct > 0; --ct ) + { + auto const val= a_a.get_four_bits( this->data(), 4 * ct - 1 ); + if( val != 0 ) break; + } + } + if( ct == 0 && params.nonEmpty ) ret_val += zeroCh; + for( ; ct > 0; --ct ) + { + auto const val= a_a.get_four_bits( this->data(), 4 * ct - 1 ); + CharT const c= + ( val < 10 ) ? ( zeroCh + val ) : ( aCh + ( val - 10 ) ); + ret_val += c; + } + return ret_val; + } // to_hex_string + +}; // class bitset2 + + +template<size_t N, class T> +constexpr +bitset2<N,T> +rotate_left( bitset2<N,T> const & bs, size_t n_rot ) noexcept +{ + return + bitset2<N,T>( detail::array_ops<N,T>( n_rot ).rotate_left( bs.data() ) ); +} + + +template<size_t N, class T> +constexpr +bitset2<N,T> +rotate_right( bitset2<N,T> const & bs, size_t n_rot ) noexcept +{ + return + bitset2<N,T>( detail::array_ops<N,T>( N - ( n_rot % N ) ). + rotate_left( bs.data() ) ); +} + + +/// Computes the set difference, i.e. bs1 & ~bs2 +template<size_t N, class T> +constexpr +bitset2<N,T> +difference( bitset2<N,T> const & bs1, bitset2<N,T> const & bs2 ) noexcept +{ + return + bitset2<N,T>( detail::array_funcs<bitset2<N,T>::n_array,T>() + .bitwise_setdiff( bs1.data(), bs2.data() ) ); +} + + +/// Returns bs with bits reversed +template<size_t N, class T> +constexpr +bitset2<N,T> +reverse( bitset2<N,T> const & bs ) noexcept +{ return bitset2<N,T>( detail::array_ops<N,T>( 0 ).reverse( bs.data() ) ); } + + +/// Computes the two's complement +template<size_t N, class T> +constexpr +bitset2<N,T> +complement2( bitset2<N,T> const & bs ) noexcept +{ return bitset2<N,T>( detail::array_complement2<N,T>().comp2(bs.data()) ); } + + +/// Converts an M-bit bitset2 to an N-bit bitset2. +template<size_t N,class T1,size_t M, class T2> +constexpr +bitset2<N,T1> +convert_to( bitset2<M,T2> const & bs ) noexcept +{ + using a2a= + detail::array2array<bitset2<N,T1>::n_array,bitset2<M,T2>::n_array,T1,T2>; + return + bitset2<N,T1>(a2a()(detail::bit_chars<N,T1>::hgh_bit_pattern, bs.data())); +} + + +/// Converts an M-bit bitset2 to an N-bit bitset2. +template<size_t N,size_t M, class T> +constexpr +bitset2<N,T> +convert_to( bitset2<M,T> const & bs ) noexcept +{ return bitset2<N,T>( bs.data() ); } + + +/// \brief Returns true if f returns true for each pair +/// of base_t=T values in bs1 and bs2. f should be a binary function +/// taking two base_t values and returning bool. +/// zip_fold_and does short circuit if possible. +template<size_t N, class F, class T> +constexpr +bool +zip_fold_and( bitset2<N,T> const & bs1, bitset2<N,T> const & bs2, + F f ) noexcept(noexcept( f( T(0), T(0) ) )) +{ + return + detail::array_funcs<bitset2<N,T>::n_array,T>().zip_fold_and(bs1.data(), + bs2.data(), f); +} + + +/// \brief Returns true if f returns true for at least one pair +/// of base_t=T values in bs1 and bs2. f should be a binary function +/// taking two base_t values and returning bool. +/// zip_fold_or does short circuit if possible. +template<size_t N, class F,class T> +constexpr +bool +zip_fold_or( bitset2<N,T> const & bs1, bitset2<N,T> const & bs2, + F f ) noexcept(noexcept( f( T(0), T(0) ) )) +{ + return + detail::array_funcs<bitset2<N,T>::n_array,T>().zip_fold_or( bs1.data(), + bs2.data(), f ); +} + + +} // namespace Bitset2 + + + + +/// Stream output +template <class CharT, class Traits, size_t N,class T> +std::basic_ostream<CharT, Traits>& +operator<<( std::basic_ostream<CharT, Traits> & os, + Bitset2::bitset2<N,T> const & x ) +{ + for( size_t ct= N; ct > 0; ) + { + --ct; + os << ( x[ct] ? "1" : "0" ); + } + return os; +} + +/// Stream input +template <class CharT, class Traits, size_t N,class T> +std::basic_istream<CharT, Traits>& +operator>>( std::basic_istream<CharT, Traits> & is, + Bitset2::bitset2<N,T> & x ) +{ + std::bitset<N> bs; + is >> bs; + x= Bitset2::bitset2<N,T>( bs ); + return is; +} + + + +/// Shift left +template<size_t N,class T> +constexpr +Bitset2::bitset2<N,T> +operator<<( Bitset2::bitset2<N,T> const & bs, size_t n_shift ) noexcept +{ + return + Bitset2::bitset2<N,T>( Bitset2::detail::array_ops<N,T>( n_shift ) + .shift_left( bs.data() ) ); +} + + +/// Shift right +template<size_t N,class T> +constexpr +Bitset2::bitset2<N,T> +operator>>( Bitset2::bitset2<N,T> const & bs, size_t n_shift ) noexcept +{ + return + Bitset2::bitset2<N,T>( Bitset2::detail::array_ops<N,T>( n_shift ) + .shift_right( bs.data() ) ); +} + + +template<size_t N,class T> +constexpr +Bitset2::bitset2<N,T> +operator|( Bitset2::bitset2<N,T> const & bs1, + Bitset2::bitset2<N,T> const & bs2 ) noexcept +{ + return + Bitset2::bitset2<N,T>( + Bitset2::detail::array_funcs<Bitset2::bitset2<N,T>::n_array,T>() + .bitwise_or( bs1.data(), bs2.data() ) ); +} + + +template<size_t N,class T> +constexpr +Bitset2::bitset2<N,T> +operator&( Bitset2::bitset2<N,T> const & bs1, + Bitset2::bitset2<N,T> const & bs2 ) noexcept +{ + return + Bitset2::bitset2<N,T>( + Bitset2::detail::array_funcs<Bitset2::bitset2<N,T>::n_array,T>() + .bitwise_and( bs1.data(), bs2.data() ) ); +} + + +template<size_t N,class T> +constexpr +Bitset2::bitset2<N,T> +operator^( Bitset2::bitset2<N,T> const & bs1, + Bitset2::bitset2<N,T> const & bs2 ) noexcept +{ + return + Bitset2::bitset2<N,T>( + Bitset2::detail::array_funcs<Bitset2::bitset2<N,T>::n_array,T>() + .bitwise_xor( bs1.data(), bs2.data() ) ); +} + + +template<size_t N,class T> +constexpr +Bitset2::bitset2<N,T> +operator+( Bitset2::bitset2<N,T> const & bs1, + Bitset2::bitset2<N,T> const & bs2 ) noexcept +{ + return + Bitset2::bitset2<N,T>( + Bitset2::detail::array_add<N,T>().add( bs1.data(), bs2.data() ) ); +} + + +namespace std +{ + template<size_t N,class T> + struct hash<Bitset2::bitset2<N,T> > + { + private: + enum : size_t + { n_array= Bitset2::detail::bitset2_impl<N,T>::n_array }; + + Bitset2::detail::hash_impl<n_array,T> m_func; + + public: + using argument_type= Bitset2::bitset2<N,T>; + using result_type= + typename Bitset2::detail::hash_impl<n_array,T>::result_type; + + result_type operator()( argument_type const& bs ) const + { return m_func( bs.data() ); } + }; // struct hash + +} // namespace std + + +#endif // BITSET2_CB_HPP diff --git a/ThirdParty/bitset2/detail/array2array.hpp b/ThirdParty/bitset2/detail/array2array.hpp new file mode 100644 index 00000000..618af64e --- /dev/null +++ b/ThirdParty/bitset2/detail/array2array.hpp @@ -0,0 +1,122 @@ +// BITSET2 +// +// Copyright Claas Bontus +// +// Use, modification and distribution is subject to the +// Boost Software License, Version 1.0. (See accompanying +// file LICENSE.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// +// Project home: https://github.com/ClaasBontus/bitset2 +// + +#ifndef BITSET2_ARRAY2ARRAY_CB_HPP +#define BITSET2_ARRAY2ARRAY_CB_HPP + + +#include "h_types.hpp" + + +namespace Bitset2 +{ +namespace detail +{ + + +/// \brief Convert std::array<Tsrc,src_n> to std::array<Ttrgt,trgt_n> +template<size_t trgt_n, size_t src_n, class Ttrgt, class Tsrc> +struct array2array +{ + using h_t_trgt= h_types<Ttrgt>; + using h_t_src= h_types<Tsrc>; + using trgt_array_t= typename h_t_trgt::template array_t<trgt_n>; + using src_array_t= typename h_t_src:: template array_t<src_n>; + + enum : size_t + { trgt_base_n_bits= h_t_trgt::base_t_n_bits + , src_base_n_bits= h_t_src:: base_t_n_bits + }; + + enum : bool + { small_to_large= ( src_base_n_bits < trgt_base_n_bits ) }; + + enum : size_t + { ts_div= small_to_large ? trgt_base_n_bits / src_base_n_bits + : src_base_n_bits / trgt_base_n_bits }; + + enum : Tsrc + { h_all_set= Tsrc( Ttrgt(~Ttrgt(0)) ) }; + + /// Applies pttrn to most significant entry in result + constexpr + trgt_array_t + operator()( Ttrgt pttrn, src_array_t const &src ) const noexcept + { + static_assert( ( small_to_large && trgt_base_n_bits % src_base_n_bits == 0) + || (!small_to_large && src_base_n_bits % trgt_base_n_bits == 0), + "Conversion between arrays of these types not supported" ); + return small_to_large + ? conv_small_to_large( pttrn, src, std::make_index_sequence<trgt_n-1>() ) + : conv_large_to_small( pttrn, src, std::make_index_sequence<trgt_n-1>() ); + } + + + template<size_t ... S1> + constexpr + trgt_array_t + conv_small_to_large( Ttrgt pttrn, + src_array_t const &src, + std::index_sequence<S1...> ) const noexcept + { + return {{ get_from_smaller( S1, src, S1 * ts_div )..., + Ttrgt( get_from_smaller( trgt_n-1, src, (trgt_n-1) * ts_div ) + & pttrn ) }}; + } + + template<size_t ... S1> + constexpr + trgt_array_t + conv_large_to_small( Ttrgt pttrn, + src_array_t const &src, + std::index_sequence<S1...> ) const noexcept + { + return + {{ get_from_larger( S1 / ts_div, S1 % ts_div, src )..., + Ttrgt( get_from_larger((trgt_n-1) / ts_div, (trgt_n-1) % ts_div, src) + & pttrn ) }}; + } + + constexpr + Ttrgt + get_from_smaller( size_t trgt_idx, + src_array_t const &src, + size_t src_idx, + size_t src_ct= 0, + Ttrgt so_far= Ttrgt(0) ) const noexcept + { + return ( src_ct >= ts_div || src_idx >= src_n ) + ? so_far + : get_from_smaller( trgt_idx, src, src_idx + 1, src_ct + 1, + so_far | Ttrgt( Ttrgt(src[src_idx]) + << (src_base_n_bits * src_ct) ) ); + } + + constexpr + Ttrgt + get_from_larger( size_t div_val, + size_t mod_val, + src_array_t const &src ) const noexcept + { + return ( div_val >= src_n ) ? Ttrgt(0) + : Ttrgt(Tsrc( src[div_val] >> (mod_val*trgt_base_n_bits) ) & h_all_set ); + } +}; // struct array2array + + + +} // namespace detail +} // namespace Bitset2 + + + +#endif // BITSET2_ARRAY2ARRAY_CB_HPP diff --git a/ThirdParty/bitset2/detail/array2u_long_t.hpp b/ThirdParty/bitset2/detail/array2u_long_t.hpp new file mode 100644 index 00000000..ec2ddc4c --- /dev/null +++ b/ThirdParty/bitset2/detail/array2u_long_t.hpp @@ -0,0 +1,110 @@ +// BITSET2 +// +// Copyright Claas Bontus +// +// Use, modification and distribution is subject to the +// Boost Software License, Version 1.0. (See accompanying +// file LICENSE.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// +// Project home: https://github.com/ClaasBontus/bitset2 +// + + +#ifndef BITSET2_ARRAY2U_LONG_T_CB_HPP +#define BITSET2_ARRAY2U_LONG_T_CB_HPP + +#include "bit_chars.hpp" + + +namespace Bitset2 +{ +namespace detail +{ + + /// \brief Takes a std::array 'arr' and returns a variable 'x' of type Tlong. + /// Bits in 'x' are set if corresponding bits in 'arr' are set. + template<size_t N, class T, class Tlong> + struct array2u_long_t + { + using base_t= T; + using b_c= bit_chars<N,T>; + + enum : size_t + { n_bits= N + , base_t_n_bits= b_c::base_t_n_bits + , long_t_n_bits= sizeof( Tlong ) * CHAR_BIT + , n_array= b_c::n_array + , div_val= long_t_n_bits / base_t_n_bits + , mod_val= long_t_n_bits % base_t_n_bits + , use_vals= ce_min( div_val + (mod_val!=0), n_array ) + , bit_diff= mod_val == 0 ? 0 : ( base_t_n_bits - mod_val ) + }; + + enum : base_t + { allset= base_t( ~base_t(0) ) + , h_pttrn= use_vals < n_array ? allset : ce_right_shift( allset, bit_diff ) + , i_pttrn= base_t( ~h_pttrn ) + }; + + using array_t= typename h_types<T>::template array_t<n_array>; + + constexpr + Tlong + operator()( array_t const & arr ) const noexcept + { + return + base_t_n_bits >= long_t_n_bits ? Tlong( arr[0] ) + : combine( Tlong(0), arr, 0 ); + } + + /// \brief Returns true if arr cannot be converted to Tlong. + constexpr + bool + check_overflow( array_t const & arr ) const noexcept + { return N <= long_t_n_bits ? false : check_impl( arr, use_vals - 1 ); } + + + + constexpr + Tlong + combine( Tlong v, array_t const & arr, size_t idx ) const noexcept + { + return ( idx >= use_vals ) ? v + : idx + 1 == use_vals + ? Tlong( v + take_v( arr, idx, h_pttrn ) ) + : combine( Tlong( v + take_v( arr, idx ) ), arr, idx + 1 ); + } + + constexpr + Tlong + take_v( array_t const & arr, size_t idx, base_t pttrn= allset ) const noexcept + { return ce_left_shift( Tlong( arr[idx] & pttrn ), idx * base_t_n_bits ); } + + constexpr + bool + check_impl( array_t const & arr, size_t idx ) const noexcept + { + return idx >= n_array ? false + : ( ( take_check( arr, idx ) != base_t(0) ) + || check_impl( arr, idx + 1 ) ); + } + + constexpr + base_t + take_check( array_t const & arr, size_t idx ) const noexcept + { return arr[idx] & ( idx + 1 == use_vals ? i_pttrn : allset ); } + + }; // struct array2u_long_t + + +} // namespace detail +} // namespace Bitset2 + + + + + + + +#endif // BITSET2_ARRAY2U_LONG_T_CB_HPP diff --git a/ThirdParty/bitset2/detail/array_access.hpp b/ThirdParty/bitset2/detail/array_access.hpp new file mode 100644 index 00000000..a4e42b49 --- /dev/null +++ b/ThirdParty/bitset2/detail/array_access.hpp @@ -0,0 +1,82 @@ +// BITSET2 +// +// Copyright Claas Bontus +// +// Use, modification and distribution is subject to the +// Boost Software License, Version 1.0. (See accompanying +// file LICENSE.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// +// Project home: https://github.com/ClaasBontus/bitset2 +// + +#ifndef BITSET2_ARRAY_ACCESS_CB_HPP +#define BITSET2_ARRAY_ACCESS_CB_HPP + +#include "bit_chars.hpp" + + +namespace Bitset2 +{ +namespace detail +{ + + /// \brief array_access is used for getting bunches of 4 bits, which is + /// needed when creating hex-strings + template<size_t N,class T> + struct array_access + { + using base_t= T; + using b_chars= bit_chars<N,T>; + enum : size_t { base_t_n_bits= b_chars::base_t_n_bits + , n_array= b_chars::n_array + }; + enum : size_t { div_four= N / 4 + , mod_four= N % 4 + }; + using array_t= typename h_types<T>::template array_t<n_array>; + + constexpr + base_t + get_four_bits( array_t const &arr, size_t offset ) const noexcept + { + return + get_four_bits_impl( arr, + offset / base_t_n_bits, offset % base_t_n_bits ); + } + + constexpr + base_t + get_four_bits_impl( array_t const &arr, + size_t idx, size_t bit_idx ) const noexcept + { + return ( bit_idx >= 3 ) + ? h1_get_four_bits( arr[idx], bit_idx ) + : h2_get_four_bits( arr, idx, bit_idx ); + } + + constexpr + base_t + h1_get_four_bits( base_t v, size_t bit_idx ) const noexcept + { return ( v >> ( bit_idx - 3 ) ) & base_t(0xF); } + + constexpr + base_t + h2_get_four_bits( array_t const &arr, + size_t idx, size_t bit_idx ) const noexcept + { + return + (( arr[idx] & ( ( base_t(1) << (bit_idx+1) ) - 1 ) ) << ( 3 - bit_idx )) + + ( ( idx == 0 ) ? base_t(0) + : ( arr[idx-1] >> (base_t_n_bits - (3 - bit_idx)) ) ); + } + }; // struct array_access + + +} // namespace detail +} // namespace Bitset2 + + + + +#endif // BITSET2_ARRAY_ACCESS_CB_HPP diff --git a/ThirdParty/bitset2/detail/array_add.hpp b/ThirdParty/bitset2/detail/array_add.hpp new file mode 100644 index 00000000..55dc6f7a --- /dev/null +++ b/ThirdParty/bitset2/detail/array_add.hpp @@ -0,0 +1,153 @@ +// BITSET2 +// +// Copyright Claas Bontus +// +// Use, modification and distribution is subject to the +// Boost Software License, Version 1.0. (See accompanying +// file LICENSE.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// +// Project home: https://github.com/ClaasBontus/bitset2 +// + +#ifndef BITSET2_ARRAY_ADD_CB_HPP +#define BITSET2_ARRAY_ADD_CB_HPP + + +#include "bit_chars.hpp" +#include "array_funcs.hpp" + + +namespace Bitset2 +{ +namespace detail +{ + + template<size_t N,size_t it_n,class T> + struct array_add_base + { + using base_t= T; + using b_chars= bit_chars<N,T>; + enum : size_t { n_array= b_chars::n_array }; + enum : base_t + { hgh_bit_pattern= b_chars::hgh_bit_pattern + , all_one= b_chars::all_one + }; + using array_t= typename h_types<T>::template array_t<n_array>; + using zero_array_t= typename h_types<T>::template array_t<0>; + + /// Used to submit the curent result of the addition and the carry over + template<size_t n> + using array_pair_t= std::pair<base_t, + typename h_types<T>::template array_t<n> >; + + + constexpr + array_pair_t<it_n+1> + add_h1( base_t a, base_t b, base_t sm1, base_t sum, + typename + h_types<T>::template array_t<it_n> const &so_far ) const noexcept + { + return + std::make_pair( ( sum < a || sm1 < b ) ? base_t(1) : base_t(0) + , array_funcs<it_n,T>() + .append( so_far + , ( it_n + 1 < n_array ) + ? sum + : base_t(sum & hgh_bit_pattern) ) ); + } + + constexpr + array_pair_t<it_n+1> + add_h2( base_t a, base_t b, array_pair_t<it_n> const &a_p ) const noexcept + { return add_h1( a, b, b + a_p.first, a + b + a_p.first, a_p.second ); } + }; //struct array_add_base + + + /// \brief This struct is introduced for beeing able to partially + /// specialize function add_h3. + template<size_t N,size_t it_n,class T> + struct array_add_h : public array_add_base<N,it_n,T> + { + using array_t= typename array_add_base<N,it_n,T>::array_t; + + template<size_t n> + using array_pair_t= + typename array_add_base<N,it_n,T>::template array_pair_t<n>; + + constexpr + array_pair_t<it_n+1> + add_h3( array_t const &arr1, array_t const &arr2 ) const noexcept + { + return + this->add_h2( arr1[it_n], arr2[it_n] + , array_add_h<N,it_n-1,T>().add_h3( arr1, arr2 ) ); + } + }; // struct array_add_h + + + template<size_t N,class T> + struct array_add_h<N,0,T> : public array_add_base<N,0,T> + { + using array_t= typename array_add_base<N,0,T>::array_t; + using zero_array_t= typename array_add_base<N,0,T>::zero_array_t; + + template<size_t n> + using array_pair_t=typename array_add_base<N,0,T>::template array_pair_t<n>; + + constexpr + array_pair_t<1> + add_h3( array_t const &arr1, array_t const &arr2 ) const noexcept + { + return + this->add_h2( arr1[0], arr2[0] + , std::make_pair( T(0), zero_array_t{} ) ); + } + }; // struct array_add_h + + + /// Allows to add two std::array's in a constexpr + template<size_t N,class T> + struct array_add + { + using base_t= T; + using b_chars= bit_chars<N,T>; + enum : base_t + { hgh_bit_pattern= b_chars::hgh_bit_pattern + , all_one= b_chars::all_one + }; + enum : size_t { n_array= b_chars::n_array }; + using array_t= typename h_types<T>::template array_t<n_array>; + + constexpr + array_t + add( array_t const &arr1, array_t const &arr2 ) const noexcept + { + return + ( N == 0 ) ? array_t{} + : array_add_h<N,n_array-1,T>().add_h3( arr1, arr2 ).second; + } + + constexpr + void + add_assgn( array_t &arr1, array_t const &arr2 ) const noexcept + { + base_t carry= base_t(0); + for( size_t c= 0; c < n_array; ++c ) + { + auto const sm1= base_t( arr2[c] + carry ); + auto const sm= base_t( arr1[c] + sm1 ); + carry= sm < arr1[c] || sm1 < arr2[c]; + arr1[c]= sm; + } + arr1[n_array-1] &= hgh_bit_pattern; + } // add_assgn + }; // struct array_add + +} // namespace detail +} // namespace Bitset2 + + + + +#endif // BITSET2_ARRAY_ADD_CB_HPP diff --git a/ThirdParty/bitset2/detail/array_complement2.hpp b/ThirdParty/bitset2/detail/array_complement2.hpp new file mode 100644 index 00000000..eaab57be --- /dev/null +++ b/ThirdParty/bitset2/detail/array_complement2.hpp @@ -0,0 +1,149 @@ +// BITSET2 +// +// Copyright Claas Bontus +// +// Use, modification and distribution is subject to the +// Boost Software License, Version 1.0. (See accompanying +// file LICENSE.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// +// Project home: https://github.com/ClaasBontus/bitset2 +// + +#ifndef BITSET2_ARRAY_COMPLEMENT2_CB_HPP +#define BITSET2_ARRAY_COMPLEMENT2_CB_HPP + + +#include "bit_chars.hpp" +#include "array_funcs.hpp" + + +namespace Bitset2 +{ +namespace detail +{ + + template<size_t N,size_t it_n,class T> + struct array_complement2_base + { + using base_t= T; + using b_chars= bit_chars<N,T>; + enum : base_t { hgh_bit_pattern= b_chars::hgh_bit_pattern }; + enum : size_t { n_array= b_chars::n_array }; + using array_t= typename h_types<T>::template array_t<n_array>; + + template<size_t n> + using arr_t= typename h_types<T>::template array_t<n>; + + constexpr + arr_t<it_n+1> + comp2_h1( arr_t<it_n> const &so_far, base_t sum ) const noexcept + { + return + array_funcs<it_n,T>().append( so_far + , ( it_n + 1 < n_array ) + ? sum + : base_t(sum & hgh_bit_pattern) ); + } + + constexpr + arr_t<it_n+1> + comp2_h2( array_t const &arr, + arr_t<it_n> const &so_far, + base_t carry ) const noexcept + { return comp2_h1( so_far, base_t( base_t(~arr[it_n]) + carry ) ); } + + constexpr + arr_t<it_n+1> + comp2_h3( array_t const &arr, + arr_t<it_n> const &so_far ) const noexcept + { + return comp2_h2( arr, so_far, + it_n == 0 + ? base_t(1) + : base_t(so_far[it_n-1] == 0 && arr[it_n-1] == 0) ); + } + + }; // struct array_complement2_base + + + template<size_t N,size_t it_n,class T> + struct array_complement2_h : array_complement2_base<N,it_n,T> + { + using array_t= typename array_complement2_base<N,it_n,T>::array_t; + + template<size_t n> + using arr_t= typename array_complement2_base<N,it_n,T>::template arr_t<n>; + + constexpr + arr_t<it_n+1> + comp2_h4( array_t const &arr ) const noexcept + { + return + this->comp2_h3( arr, + array_complement2_h<N,it_n-1,T>().comp2_h4( arr ) ); + } + + }; // struct array_complement2_h + + + template<size_t N,class T> + struct array_complement2_h<N,0,T> : array_complement2_base<N,0,T> + { + using array_t= typename array_complement2_base<N,0,T>::array_t; + + template<size_t n> + using arr_t= typename array_complement2_base<N,0,T>::template arr_t<n>; + + constexpr + arr_t<1> + comp2_h4( array_t const &arr ) const noexcept + { return this->comp2_h3( arr, arr_t<0>{} ); } + + }; // struct array_complement2_h<N,0,T> + + + + /// Computes the two's complement of the number encoded in the array + template<size_t N,class T> + struct array_complement2 + { + using base_t= T; + using b_chars= bit_chars<N,T>; + enum : base_t { hgh_bit_pattern= b_chars::hgh_bit_pattern }; + enum : size_t { n_array= b_chars::n_array }; + using array_t= typename h_types<T>::template array_t<n_array>; + + + constexpr + array_t + comp2( array_t const &arr ) const noexcept + { + return + ( N == 0 ) ? array_t{} + : array_complement2_h<N,n_array-1,T>().comp2_h4( arr ); + } + + constexpr + void + comp2_assgn( array_t &arr ) const noexcept + { + base_t carry= base_t(1); + for( size_t c= 0; c < n_array; ++c ) + { + auto const sm= base_t( base_t(~arr[c]) + carry ); + carry= base_t( (carry == base_t(1)) && ( sm == 0 ) ); + arr[c]= sm; + } // for c + arr[n_array-1] &= hgh_bit_pattern; + } // comp2_assgn + + }; // struct array_complement2 + + +} // namespace detail +} // namespace Bitset2 + + + +#endif // BITSET2_ARRAY_COMPLEMENT2_CB_HPP diff --git a/ThirdParty/bitset2/detail/array_funcs.hpp b/ThirdParty/bitset2/detail/array_funcs.hpp new file mode 100644 index 00000000..f75afb02 --- /dev/null +++ b/ThirdParty/bitset2/detail/array_funcs.hpp @@ -0,0 +1,346 @@ +// BITSET2 +// +// Copyright Claas Bontus +// +// Use, modification and distribution is subject to the +// Boost Software License, Version 1.0. (See accompanying +// file LICENSE.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// +// Project home: https://github.com/ClaasBontus/bitset2 +// + +#ifndef BITSET2_ARRAY_FUNCS_CB_HPP +#define BITSET2_ARRAY_FUNCS_CB_HPP + + +#include "h_types.hpp" +#include "count_bits.hpp" +#include "index_lsb_set.hpp" +#include <utility> + + +namespace Bitset2 +{ +namespace detail +{ + + template<size_t n_array,class T> + struct array_funcs + { + using base_t= T; + using array_t= typename h_types<T>::template array_t<n_array>; + using array_p1_t= typename h_types<T>::template array_t<n_array+1>; + + enum : size_t { base_t_n_bits= h_types<T>::base_t_n_bits + , npos= h_types<T>::npos }; + + /// Binary operator type + enum class op_type { or_op, and_op, xor_op, sdiff_op }; + + constexpr + array_t + bitwise_or( array_t const &arr1, array_t const &arr2 ) const noexcept + { + return bitwise_op_impl( op_type::or_op, arr1, arr2, + std::make_index_sequence<n_array>() ); + } + + /// Used for |= operator. Separate implementation for better performance. + constexpr + void + bitwise_or_assgn( array_t &arr1, array_t const &arr2 ) const noexcept + { return bitwise_op_assgn_impl( op_type::or_op, arr1, arr2 ); } + + constexpr + array_t + bitwise_and( array_t const &arr1, array_t const &arr2 ) const noexcept + { + return bitwise_op_impl( op_type::and_op, arr1, arr2, + std::make_index_sequence<n_array>() ); + } + + /// Used for &= operator. Separate implementation for better performance. + constexpr + void + bitwise_and_assgn( array_t &arr1, array_t const &arr2 ) const noexcept + { return bitwise_op_assgn_impl( op_type::and_op, arr1, arr2 ); } + + constexpr + array_t + bitwise_xor( array_t const &arr1, array_t const &arr2 ) const noexcept + { + return bitwise_op_impl( op_type::xor_op, arr1, arr2, + std::make_index_sequence<n_array>() ); + } + + /// Used for ^= operator. Separate implementation for better performance. + constexpr + void + bitwise_xor_assgn( array_t &arr1, array_t const &arr2 ) const noexcept + { return bitwise_op_assgn_impl( op_type::xor_op, arr1, arr2 ); } + + /// Computes the set difference, i.e. arr1 & ~arr2 + constexpr + array_t + bitwise_setdiff( array_t const &arr1, array_t const &arr2 ) const noexcept + { + return bitwise_op_impl( op_type::sdiff_op, arr1, arr2, + std::make_index_sequence<n_array>() ); + } + + /// \brief Computes the set difference, i.e. arr1 & ~arr2. + /// Separate implementation for better performance. + constexpr + void + bitwise_setdiff_assgn( array_t &arr1, array_t const &arr2 ) const noexcept + { return bitwise_op_assgn_impl( op_type::sdiff_op, arr1, arr2 ); } + + + constexpr + bool + none( array_t const &arr ) const noexcept + { return none_impl( n_array - 1, arr ); } + + + constexpr + size_t + count( array_t const &arr ) const noexcept + { + return + sum_impl( count_impl( arr, std::make_index_sequence<n_array>() ) ); + } + + + constexpr + bool + equal( array_t const &arr1, array_t const &arr2 ) const noexcept + { return equal_impl( arr1, arr2, 0 ); } + + + constexpr + bool + less_than( array_t const &arr1, array_t const &arr2 ) const noexcept + { return less_than_impl( arr1, arr2, n_array - 1 ); } + + + /// \brief Returns true if f returns true for each pair + /// of elements in arr1 and arr2 + template<class F> + constexpr + bool + zip_fold_and( array_t const &arr1, array_t const &arr2, + F &f ) const noexcept(noexcept( f( base_t(0), base_t(0) ) )) + { return zip_fold_and_impl( arr1, arr2, f, 0 ); } + + + /// \brief Returns true if f returns true for at least one pair + /// of elements in arr1 and arr2 + template<class F> + constexpr + bool + zip_fold_or( array_t const &arr1, array_t const &arr2, + F &f ) const noexcept(noexcept( f( base_t(0), base_t(0) ) )) + { return zip_fold_or_impl( arr1, arr2, f, 0 ); } + + + /// Prepend v1 in front of arr + constexpr + array_p1_t + prepend( base_t const v1, array_t const &arr ) const noexcept + { return prepend_impl( v1, arr, std::make_index_sequence<n_array>()); } + + + /// Append v1 to arr + constexpr + array_p1_t + append( array_t const &arr, base_t const v1 ) const noexcept + { return append_impl( arr, v1, std::make_index_sequence<n_array>()); } + + + /// Copy each element in arr but apply pttrn to most significant entry + template<size_t n> + constexpr + array_t + copy_and_map( base_t const pttrn, + typename + h_types<T>::template array_t<n> const &arr ) const noexcept + { + return + n_array == 0 ? array_t{} + : copy_and_map_impl( + pttrn, + arr, + gen_empty_array<n_array,T>(), + n >= n_array, + std::make_index_sequence<ce_min( n_array-1, n )>(), + std::make_index_sequence<n_array-1-ce_min(n_array-1, n)>() ); + } // copy_and_map + + + //** _impl functions + + template<size_t n,size_t ... S1,size_t ... S2> + constexpr + array_t + copy_and_map_impl( base_t const pttrn, + typename + h_types<T>::template array_t<n> const &arr, + array_t const &zeroes, + bool const take_all, + std::index_sequence<S1...>, + std::index_sequence<S2...> ) const noexcept + { + return {{ arr[S1]..., zeroes[S2]..., + base_t(( take_all ? arr[n_array-1] : base_t(0) ) & pttrn) }}; + } + + + + constexpr + bool + none_impl( size_t idx, array_t const &arr ) const noexcept + { + return ( arr[idx] == base_t(0) ) + && ( ( idx == 0 ) ? true : none_impl( idx - 1, arr ) ); + } + + + template<size_t ... S> + constexpr + array_p1_t + append_impl( array_t const &arr, base_t const v1, + std::index_sequence<S...> ) const noexcept + { return {{ arr[S]..., v1 }}; } + + + template<size_t ... S> + constexpr + array_p1_t + prepend_impl( base_t const v1, array_t const &arr, + std::index_sequence<S...> ) const noexcept + { return {{ v1, arr[S]... }}; } + + + constexpr + bool + equal_impl( array_t const &arr1, array_t const &arr2, + size_t ct ) const noexcept + { + return ( ct == n_array ) ? true + : ( arr1[ct] == arr2[ct] ) && equal_impl( arr1, arr2, ct + 1 ); + } + + + constexpr + bool + less_than_impl( array_t const &arr1, array_t const &arr2, + size_t ct ) const noexcept + { + return + ( arr1[ct] < arr2[ct] ) + || ( arr1[ct] == arr2[ct] + && ( ct == 0 ? false : less_than_impl( arr1, arr2, ct-1 ) ) ); + } + + + template<class F> + constexpr + bool + zip_fold_and_impl( array_t const &arr1, array_t const &arr2, + F &f, + size_t ct ) + const noexcept(noexcept( f(base_t(0), base_t(0)))) + { + return ( ct == n_array ) ? true + : ( f( arr1[ct], arr2[ct] ) + && zip_fold_and_impl( arr1, arr2, f, ct + 1 ) ); + } + + + template<class F> + constexpr + bool + zip_fold_or_impl( array_t const &arr1, array_t const &arr2, + F &f, + size_t ct ) + const noexcept(noexcept( f(base_t(0), base_t(0)))) + { + return ( ct == n_array ) ? false + : ( f( arr1[ct], arr2[ct] ) + || zip_fold_or_impl( arr1, arr2, f, ct + 1 ) ); + } + + + constexpr + void + bitwise_op_assgn_impl( op_type opt, + array_t &arr1, array_t const &arr2 ) const noexcept + { + for( size_t c= 0; c < n_array; ++c ) + { + if( opt == op_type::or_op ) arr1[c] |= arr2[c]; + else if( opt == op_type::and_op ) arr1[c] &= arr2[c]; + else if( opt == op_type::xor_op ) arr1[c] ^= arr2[c]; + else arr1[c] &= ~arr2[c]; + } + } // bitwise_op_assgn_impl + + + template<size_t ... S> + constexpr + array_t + bitwise_op_impl( op_type opt, + array_t const &arr1, array_t const &arr2, + std::index_sequence<S...> ) const noexcept + { return {{ h_bitwise_op( S, opt, arr1, arr2 )... }}; } + + constexpr + base_t + h_bitwise_op( size_t idx, op_type opt, + array_t const &arr1, array_t const &arr2 ) const noexcept + { + return ( opt == op_type::or_op ) ? ( arr1[idx] | arr2[idx] ) + : ( ( opt == op_type::and_op ) ? ( arr1[idx] & arr2[idx] ) + : ( opt == op_type::xor_op ) ? ( arr1[idx] ^ arr2[idx] ) + : ( arr1[idx] & ~arr2[idx] ) ); + } + + /// Count bits in each element of arr + template<size_t ... S> + constexpr + std::array<size_t, n_array> + count_impl( array_t const &arr, std::index_sequence<S...> ) const noexcept + { return {{ count_bits( arr[S] )... }}; } + + + /// Sum over all elements in vals + template<class T1> + constexpr + T1 + sum_impl( std::array<T1, n_array> const &vals, + size_t ct= n_array - 1 ) const noexcept + { return vals[ct] + ( ( ct == 0 ) ? T1(0) : sum_impl( vals, ct - 1 ) ); } + + + constexpr + size_t + idx_lsb_set( array_t const &arr, base_t v, size_t idx ) const noexcept + { + return + v == base_t(0) + ? ( idx + 1 == n_array ? npos + : idx_lsb_set( arr, arr[idx+1], idx + 1 ) ) + : idx * base_t_n_bits + index_lsb_set<base_t>()( v ); + } + + }; // struct array_funcs + +} // namespace detail + +} // namespace Bitset2 + + + + +#endif // BITSET2_ARRAY_FUNCS_CB_HPP diff --git a/ThirdParty/bitset2/detail/array_ops.hpp b/ThirdParty/bitset2/detail/array_ops.hpp new file mode 100644 index 00000000..eecbc6d0 --- /dev/null +++ b/ThirdParty/bitset2/detail/array_ops.hpp @@ -0,0 +1,336 @@ +// BITSET2 +// +// Copyright Claas Bontus +// +// Use, modification and distribution is subject to the +// Boost Software License, Version 1.0. (See accompanying +// file LICENSE.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// +// Project home: https://github.com/ClaasBontus/bitset2 +// + +#ifndef BITSET2_ARRAY_OPS_CB_HPP +#define BITSET2_ARRAY_OPS_CB_HPP + +#include "bit_chars.hpp" +#include "reverse_bits.hpp" + + +namespace Bitset2 +{ +namespace detail +{ + + template<size_t N,class T> + struct array_ops + { + using base_t= T; + using this_t= array_ops<N,T>; + using b_chars= bit_chars<N,T>; + enum : size_t { base_t_n_bits= b_chars::base_t_n_bits + , n_words= b_chars::n_words + , n_array= b_chars::n_array + , mod_val= b_chars::mod_val + , n_m_mod= mod_val == 0 ? 0 : base_t_n_bits-mod_val + }; + enum : base_t + { hgh_bit_pattern= b_chars::hgh_bit_pattern + , all_one= b_chars::all_one }; + using array_t= typename h_types<T>::template array_t<n_array>; + using zero_array_t= typename h_types<T>::template array_t<0>; + + constexpr + array_ops( size_t n_shift ) noexcept + : m_n_shift_mod( n_shift % N ) + , m_shft_div( n_shift / base_t_n_bits ) + , m_shft_mod( n_shift % base_t_n_bits ) + , m_shft_leftright_shift( base_t_n_bits-(n_shift % base_t_n_bits) ) + , m_shft_left_pattern( ce_left_shift( T(~T(0)), + base_t_n_bits + - (n_shift % base_t_n_bits) )) + , m_shft_right_pattern( ce_right_shift( T(~T(0)), + base_t_n_bits + - (n_shift % base_t_n_bits) )) + {} + + constexpr + array_t + shift_left( array_t const &arr ) const noexcept + { return shift_left_impl( arr, std::make_index_sequence<n_array>() ); } + + constexpr + array_t + shift_right( array_t const &arr ) const noexcept + { return shift_right_impl( arr, std::make_index_sequence<n_array>() ); } + + /// Used for <<= operator. Separate implementation for better performance. + constexpr + void + shift_left_assgn( array_t &arr ) const noexcept + { + for( size_t c= n_words; c > 0; ) + { + --c; + if( c >= m_shft_div ) + { + auto const c2= c - m_shft_div; + base_t const v1= arr[c2] << m_shft_mod; + base_t const v2= + c2 == 0 ? base_t(0) + : ce_right_shift( base_t(arr[c2-1] & m_shft_left_pattern), + m_shft_leftright_shift ); + arr[c]= base_t( v1 | v2 ); + } + else arr[c]= base_t(0); + } // for c + arr[n_array-1] &= hgh_bit_pattern; + } // shift_left_assgn + + /// Used for >>= operator. Separate implementation for better performance. + constexpr + void + shift_right_assgn( array_t &arr ) const noexcept + { + for( size_t c= 0; c < n_words; ++c ) + { + auto const c2= c + m_shft_div; + if( c2 < n_words ) + { + base_t const v1= arr[c2] >> m_shft_mod; + base_t const v2= + ( c2 + 1 >= n_words ) ? base_t(0) + : ce_left_shift( base_t( arr[c2+1] & m_shft_right_pattern ), + m_shft_leftright_shift ); + arr[c]= v1 | v2; + } + else arr[c]= base_t(0); + } // for c + arr[n_array-1] &= hgh_bit_pattern; + } // shift_right_assgn + + + constexpr + array_t + rotate_left( array_t const &arr ) const noexcept + { + return + ( n_array == 1 ) + ? array_t{{ base_t(( base_t( arr[0] << m_n_shift_mod ) + | ( ce_right_shift( arr[0], N - m_n_shift_mod ) ) + ) & hgh_bit_pattern ) }} + : rotate_left_impl( arr, + array_ops<N,T>( m_n_shift_mod ), + array_ops<N,T>( N - m_n_shift_mod ), + std::make_index_sequence<n_array>() ); + } // rotate_left + + constexpr + array_t + flip( array_t const &arr ) const noexcept + { return flip_impl( arr, std::make_index_sequence<n_array>() ); } + + constexpr + bool + all( array_t const &arr ) const noexcept + { return ( N > 0 ) && all_impl( n_words - 1, arr ); } + + + /// Used for ++ operator. + constexpr + void + increment( array_t &arr ) const noexcept + { + if( N == 0 ) return; + + size_t c= 0; + for( ; c + 1 < n_words; ++c ) + { + if( ( ++arr[c] ) != base_t(0) ) return; + } + ++arr[c]; + arr[c] &= hgh_bit_pattern; + } // increment + + + /// Used for -- operator. + constexpr + void + decrement( array_t &arr ) const noexcept + { + if( N == 0 ) return; + + size_t c= 0; + for( ; c + 1 < n_words; ++c ) + { + if( ( arr[c]-- ) != base_t(0) ) return; + } + --arr[c]; + arr[c] &= hgh_bit_pattern; + } // decrement + + /// Reverse bits + constexpr + array_t + reverse( array_t const &arr ) const noexcept + { + return n_array == 1 + ? array_t{{ base_t( reverse_bits<base_t>()(arr[0]) >> n_m_mod ) }} + : reverse_impl( arr, std::make_index_sequence<n_array>() ); + } // reverse + + + //**************************************************** + + + constexpr + bool + all_impl( size_t idx, array_t const &arr ) const noexcept + { + return h_all( idx, arr ) + && ( ( idx == 0 ) ? true : all_impl( idx - 1, arr ) ); + } + + constexpr + bool + h_all( size_t idx, array_t const &arr ) const noexcept + { + return ( idx + 1 == n_words ) ? ( arr[idx] == hgh_bit_pattern ) + : ( arr[idx] == all_one ); + } + + + template<size_t ... S> + constexpr + array_t + shift_left_impl( array_t const &arr, + std::index_sequence<S...> ) const noexcept + { return {{ h_shift_left( S, arr )... }}; } + + constexpr + base_t + h_shift_left( size_t idx, array_t const &arr ) const noexcept + { + return h_shift_left1( idx, arr ) + & ( ( idx+1 == n_words ) ? hgh_bit_pattern : all_one ); + } + + constexpr + base_t + h_shift_left1( size_t idx, array_t const &arr ) const noexcept + { + return ( idx >= n_words || idx < m_shft_div ) ? base_t(0) + : base_t( ( arr[idx-m_shft_div] << m_shft_mod ) + | h_shift_left_rem( idx - m_shft_div, arr ) ); + } + + constexpr + base_t + h_shift_left_rem( size_t idx, array_t const &arr ) const noexcept + { + return ( idx == 0 ) ? base_t(0) + : ce_right_shift( base_t( arr[idx-1] & m_shft_left_pattern ), + m_shft_leftright_shift ); + } + + + template<size_t ... S> + constexpr + array_t + shift_right_impl( array_t const &arr, + std::index_sequence<S...> ) const noexcept + { return {{ h_shift_right( S, arr )... }}; } + + constexpr + base_t + h_shift_right( size_t idx, array_t const &arr ) const noexcept + { + return ( idx + m_shft_div >= n_words ) ? base_t(0) + : base_t( ( arr[idx+m_shft_div] >> m_shft_mod ) + | h_shift_right_rem( idx + m_shft_div, arr ) ); + } + + constexpr + base_t + h_shift_right_rem( size_t idx, array_t const &arr ) const noexcept + { + return ( idx + 1 >= n_words ) ? base_t(0) + : ce_left_shift( base_t( arr[idx+1] & m_shft_right_pattern ), + m_shft_leftright_shift ); + } + + + template<size_t ... S> + constexpr + array_t + rotate_left_impl( array_t const &arr, + this_t lft, + this_t rgt, + std::index_sequence<S...> ) const noexcept + { + return + {{ ( S > lft.m_shft_div ? lft.h_shift_left( S, arr ) + : S == lft.m_shft_div + ? base_t( lft.h_shift_left( lft.m_shft_div, arr ) + | rgt.h_shift_right( lft.m_shft_div, arr ) ) + : rgt.h_shift_right( S, arr ) )... }}; + } // rotate_left_impl + + + template<size_t ... S> + constexpr + array_t + flip_impl( array_t const &arr, std::index_sequence<S...> ) const noexcept + { return {{ h_flip( S, arr )... }}; } + + constexpr + base_t + h_flip( size_t idx, array_t const &arr ) const noexcept + { + return ( idx >= n_words ) ? base_t(0) + : ( ~arr[idx] ) + & ( (idx+1 == n_words) ? hgh_bit_pattern : all_one ); + } + + + template<size_t ... S> + constexpr + array_t + reverse_impl( array_t const &arr, std::index_sequence<S...> ) const noexcept + { return {{ h_reverse( S, arr )... }}; } + + constexpr + base_t + h_reverse( size_t idx, array_t const &arr ) const noexcept + { + return idx + 1 == n_words + ? base_t( reverse_bits<base_t>()( arr[0] ) >> n_m_mod ) + : reverse_bits<base_t>()( h2_reverse( idx, arr ) ); + } + + constexpr + base_t + h2_reverse( size_t idx, array_t const &arr ) const noexcept + { + return mod_val == 0 ? arr[n_words-idx-1] + : base_t( ( arr[n_words-idx-1] << n_m_mod ) + | ( arr[n_words-idx-2] >> mod_val ) ); + } + + + size_t const m_n_shift_mod; + size_t const m_shft_div; + size_t const m_shft_mod; + size_t const m_shft_leftright_shift; + base_t const m_shft_left_pattern; + base_t const m_shft_right_pattern; + + }; // struct array_ops + +} // namespace detail +} // namespace Bitset2 + + + + +#endif // BITSET2_ARRAY_OPS_CB_HPP diff --git a/ThirdParty/bitset2/detail/bit_chars.hpp b/ThirdParty/bitset2/detail/bit_chars.hpp new file mode 100644 index 00000000..5823d384 --- /dev/null +++ b/ThirdParty/bitset2/detail/bit_chars.hpp @@ -0,0 +1,65 @@ +// BITSET2 +// +// Copyright Claas Bontus +// +// Use, modification and distribution is subject to the +// Boost Software License, Version 1.0. (See accompanying +// file LICENSE.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// +// Project home: https://github.com/ClaasBontus/bitset2 +// + +#ifndef BITSET2_BIT_CHARS_CB_HPP +#define BITSET2_BIT_CHARS_CB_HPP + +#include "h_types.hpp" + + +namespace Bitset2 +{ +namespace detail +{ + + template<size_t N,class T> + struct bit_chars + { + using h_t= h_types<T>; + using ULONG_t= typename h_t::ULONG_t; + using ULLONG_t= typename h_t::ULLONG_t; + using base_t= T; + // + enum : size_t + { n_bits= N + , ulong_n_bits= h_t::ulong_n_bits ///< #bits in ULONG_t + , ullong_n_bits= h_t::ullong_n_bits ///< #bits in ULLONG_t + , base_t_n_bits= h_t::base_t_n_bits ///< #bits in T + , div_val= n_bits / base_t_n_bits + , mod_val= n_bits % base_t_n_bits + , n_words= mod_val ? div_val + 1 : div_val ///< #words required + , n_array= ( n_words == 0 ) ? 1 : n_words ///< #words used + }; + enum : ULONG_t + { ulong_max= ULONG_MAX }; + enum : base_t + { all_one= base_t(~base_t(0)) + , low_bit_pattern= ///< Mask for idx==0 + n_bits == 0 ? base_t(0) + : ( div_val > 0 || mod_val == 0 ) + ? all_one + : ce_right_shift( all_one, base_t_n_bits - mod_val ) + , hgh_bit_pattern= ///< Mask for idx+1==n_words + n_bits == 0 ? base_t(0) + : mod_val == 0 + ? all_one + : ce_right_shift( all_one, base_t_n_bits - mod_val ) + }; + }; // struct bit_chars + +} // namespace detail +} // namespace Bitset2 + + + + +#endif // BITSET2_BIT_CHARS_CB_HPP diff --git a/ThirdParty/bitset2/detail/bitset2_impl.hpp b/ThirdParty/bitset2/detail/bitset2_impl.hpp new file mode 100644 index 00000000..835d76b9 --- /dev/null +++ b/ThirdParty/bitset2/detail/bitset2_impl.hpp @@ -0,0 +1,400 @@ +// BITSET2 +// +// Copyright Claas Bontus +// +// Use, modification and distribution is subject to the +// Boost Software License, Version 1.0. (See accompanying +// file LICENSE.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// +// Project home: https://github.com/ClaasBontus/bitset2 +// + +#ifndef BITSET2_IMPL_CB_HPP +#define BITSET2_IMPL_CB_HPP + +#include "bit_chars.hpp" +#include "array_add.hpp" +#include "ullong2array.hpp" +#include "array2u_long_t.hpp" +#include <bitset> + + +namespace Bitset2 +{ +namespace detail +{ + +template<size_t N,class T> +class bitset2_impl +{ + using b_chars= bit_chars<N,T>; + using h_t= h_types<T>; + +public: + enum : size_t { n_array= b_chars::n_array + , npos= h_t::npos }; + using base_t= T; + using ULONG_t= typename b_chars::ULONG_t; + using ULLONG_t= typename b_chars::ULLONG_t; + using array_t= typename h_types<T>::template array_t<n_array>; + +protected: + enum : size_t + { n_words= b_chars::n_words + , ulong_n_bits= b_chars::ulong_n_bits + , ullong_n_bits= b_chars::ullong_n_bits + , base_t_n_bits= b_chars::base_t_n_bits + }; + enum : ULONG_t + { ulong_max= b_chars::ulong_max }; + enum : base_t + { low_bit_pattern= b_chars::low_bit_pattern + , hgh_bit_pattern= b_chars::hgh_bit_pattern + , all_one= b_chars::all_one + }; + + template<size_t n_arr_src, class Tsrc> + using a2a= detail::array2array<n_array, n_arr_src,T,Tsrc>; + + + /* ----------------------------------------------------------------------- */ + constexpr + bitset2_impl() noexcept + {} + + constexpr + bitset2_impl( bitset2_impl const & ) noexcept= default; + + constexpr + bitset2_impl( bitset2_impl && ) noexcept= default; + + constexpr + bitset2_impl & + operator=( bitset2_impl const & ) noexcept= default; + + constexpr + bitset2_impl & + operator=( bitset2_impl && ) noexcept= default; + + explicit + constexpr + bitset2_impl( ULLONG_t v ) noexcept + : m_value( ullong2array<N,T>()( v ) ) + {} + + template<size_t n,class Tsrc> + explicit + constexpr + bitset2_impl( std::array<Tsrc,n> const & value ) noexcept + : m_value( a2a<n,Tsrc>()( hgh_bit_pattern, value ) ) + {} + + explicit + bitset2_impl( const std::bitset<N> &bs ) noexcept + { + if( N == 0 ) return; + if( ullong_n_bits <= base_t_n_bits && n_words == 1 ) + { + m_value[0]= bs.to_ullong(); + return; + } + + size_t offset= 0; + for( size_t ct= 0; ct < n_words; ++ct ) + { + base_t val= base_t(0); + auto const bit_limit= + ( ct < n_words - 1 ) ? base_t_n_bits : N - offset; + for( size_t bit_ct= 0; bit_ct < bit_limit; ++bit_ct ) + { + auto const test_bit= offset + bit_limit - bit_ct - 1; + val <<= 1; + if( bs.test( test_bit ) ) val |= base_t(1); + } // for bit_ct + m_value[ct]= val; + offset += base_t_n_bits; + } // for ct + } // bitset2_impl( const std::bitset<N> &bs ) + + + template< class CharT, class Traits, class Alloc > + explicit + bitset2_impl( std::basic_string<CharT,Traits,Alloc> const &str, + typename + std::basic_string<CharT,Traits,Alloc>::size_type pos, + typename + std::basic_string<CharT,Traits,Alloc>::size_type n, + CharT zero, + CharT one ) + { + auto const str_sz= str.size(); + if( pos > str_sz ) + throw std::out_of_range( "bitset2: String submitted to " + "constructor smaller than pos" ); + auto const n_bits= std::min( N, std::min( n, str_sz - pos ) ); + + for( size_t bit_ct= 0; bit_ct < n_bits; ++bit_ct ) + { + auto const chr= str[bit_ct+pos]; + if( Traits::eq( one, chr ) ) set( n_bits - bit_ct - 1 ); + else if( !Traits::eq( zero, chr ) ) + throw std::invalid_argument( "bitset2: Invalid argument in " + "string submitted to constructor" ); + } // for bit_ct + } + /* ----------------------------------------------------------------------- */ + + + //********************************************************** + + + constexpr + array_t & + get_data() noexcept + { return m_value; } + + constexpr + bool + operator[]( size_t bit ) const noexcept + { return test_noexcept( bit ); } + + constexpr + bool + test_noexcept( size_t bit ) const noexcept + { return m_value[bit / base_t_n_bits] & ( T(1) << ( bit % base_t_n_bits ) ); } + + constexpr + bitset2_impl & + set( size_t bit, bool value= true ) + { + if( bit >= N ) + throw std::out_of_range( "bitset2: Setting of bit out of range" ); + set_noexcept( bit, value ); + return *this; + } // set + + constexpr + bitset2_impl & + set() noexcept + { + if( N > 0 ) + { + size_t c= 0; + for( ; c < n_words - 1; ++c ) m_value[c]= ~base_t(0); + m_value[c]= hgh_bit_pattern; + } + return *this; + } // set + + constexpr + bitset2_impl & + reset() noexcept + { + for( size_t c= 0; c < n_array; ++c ) m_value[c]= base_t(0); + return *this; + } + + constexpr + bool + test_set( size_t bit, bool value= true ) + { + if( bit >= N ) + throw std::out_of_range( "bitset2: test_set out of range" ); + return test_set_noexcept( bit, value ); + } // test_set + + constexpr + bitset2_impl & + flip_noexcept( size_t bit ) noexcept + { + m_value[bit / base_t_n_bits] ^= ( base_t(1) << ( bit % base_t_n_bits ) ); + return *this; + } + + constexpr + bitset2_impl & + flip( size_t bit ) + { + if( bit >= N ) + throw std::out_of_range( "bitset2: Flipping of bit out of range" ); + return flip_noexcept( bit ); + } // flip + + constexpr + bitset2_impl & + flip() noexcept + { + if( N > 0 ) + { + size_t c= 0; + for( ; c < n_words - 1; ++c ) m_value[c] ^= ~base_t(0); + m_value[c] ^= hgh_bit_pattern; + } + return *this; + } // flip + +public: + constexpr + array_t const & + data() const noexcept + { return m_value; } + + constexpr + ULONG_t + to_ulong() const + { + using a2l= array2u_long_t<N,T,ULONG_t>; + return ( N == 0 ) ? 0ul + : a2l().check_overflow( m_value ) + ? throw std::overflow_error( "Cannot convert bitset2 " + "to unsigned long" ) + : a2l()( m_value ); + } // to_ulong + + constexpr + ULLONG_t + to_ullong() const + { + using a2l= array2u_long_t<N,T,ULLONG_t>; + return ( N == 0 ) ? 0ull + : a2l().check_overflow( m_value ) + ? throw std::overflow_error( "Cannot convert bitset2 " + "to unsigned long long" ) + : a2l()( m_value ); + } // to_ullong + + constexpr + bool + test( size_t bit ) const + { + return ( bit >= N ) + ? throw std::out_of_range( "bitset2: Testing of bit out of range" ) + : operator[]( bit ); + } + + constexpr + void + set_noexcept( size_t bit, bool value= true ) noexcept + { + if( value ) m_value[bit / base_t_n_bits] + |= base_t( base_t(1) << ( bit % base_t_n_bits ) ); + else m_value[bit / base_t_n_bits] + &= base_t(~( base_t(1) << ( bit % base_t_n_bits ) )); + } + + constexpr + bool + test_set_noexcept( size_t bit, bool value= true ) noexcept + { + auto const dv= bit / base_t_n_bits; + auto const md= bit % base_t_n_bits; + auto const pttrn= ( base_t(1) << md ); + auto const ret_val= bool( m_value[dv] & pttrn ); + + if( value ) m_value[dv] |= pttrn; + else m_value[dv] &= ~pttrn; + + return ret_val; + } // test_set_noexcept + + constexpr + bool + none() const noexcept + { return detail::array_funcs<n_array,T>().none( m_value ); } + + constexpr + bool + any() const noexcept + { return ( N > 0 ) && !none(); } + + constexpr + bool + all() const noexcept + { return ( N > 0 ) && detail::array_ops<N,T>( 0 ).all( m_value ); } + + constexpr + size_t + count() const noexcept + { return detail::array_funcs<n_array,T>().count( m_value ); } + + /// \brief Returns index of first (least significant) bit set. + /// Returns npos if all bits are zero. + constexpr + size_t + find_first() const noexcept + { + return detail::array_funcs<n_array,T>().idx_lsb_set(m_value, m_value[0], 0); + } + + /// \brief Returns index of next (> idx) bit set. + /// Returns npos if no more bits set. + /// Throws out_of_range if idx >= N. + constexpr + size_t + find_next( size_t idx ) const + { + return idx >= N + ? throw std::out_of_range( "bitset2: find_next index out of range" ) + : idx + 1 == N + ? npos + : detail::array_funcs<n_array,T>() + .idx_lsb_set( m_value, + base_t( m_value[(idx+1) / base_t_n_bits] + & ce_left_shift(T(~T(0)),(idx+1) % base_t_n_bits) ), + (idx+1) / base_t_n_bits ); + } + + constexpr + bool + operator==( bitset2_impl const &v2 ) const noexcept + { return detail::array_funcs<n_array,T>().equal( m_value, v2.m_value ); } + + constexpr + bool + operator!=( bitset2_impl const &v2 ) const noexcept + { return !( *this == v2 ); } + + constexpr + bool + operator<( bitset2_impl const &v2 ) const noexcept + { return detail::array_funcs<n_array,T>().less_than( m_value, v2.m_value ); } + + constexpr + bool + operator<=( bitset2_impl const &v2 ) const noexcept + { return ! ( *this > v2 ); } + + constexpr + bool + operator>( bitset2_impl const &v2 ) const noexcept + { return detail::array_funcs<n_array,T>().less_than(v2.m_value, m_value); } + + constexpr + bool + operator>=( bitset2_impl const &v2 ) const noexcept + { return ! ( *this < v2 ); } + + explicit + operator std::bitset<N>() const + { + using b_t= std::bitset<N>; + if( N == 0 ) return b_t{}; + if( n_words == 1 ) return b_t( to_ullong() ); + + b_t ret_val; + for( size_t ct= 0; ct < N; ++ct ) ret_val[ct]= operator[](ct); + + return ret_val; + } +private: + array_t m_value= (detail::gen_empty_array<n_array,T>)(); +}; // class bitset2_impl + + +} // namespace detail +} // namespace Bitset2 + + + +#endif // BITSET2_IMPL_CB_HPP diff --git a/ThirdParty/bitset2/detail/count_bits.hpp b/ThirdParty/bitset2/detail/count_bits.hpp new file mode 100644 index 00000000..221e7b05 --- /dev/null +++ b/ThirdParty/bitset2/detail/count_bits.hpp @@ -0,0 +1,45 @@ +// BITSET2 +// +// Copyright Claas Bontus +// +// Use, modification and distribution is subject to the +// Boost Software License, Version 1.0. (See accompanying +// file LICENSE.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// +// Project home: https://github.com/ClaasBontus/bitset2 +// + +#ifndef BITSET2_COUNT_BITS_CB_HPP +#define BITSET2_COUNT_BITS_CB_HPP + + +#include "h_types.hpp" + + +namespace Bitset2 +{ +namespace detail +{ + + /// Returns the number of bits set in val + template<class T> + constexpr + inline + size_t + count_bits( T val, size_t count= 0 ) noexcept + { + return + ( val == T(0) ) + ? count + : count_bits( T(val & T( val - T(1) )), // clears lowest set bit + count + 1 ); + } + +} // namespace detail +} // namespace Bitset2 + + + + +#endif // BITSET2_COUNT_BITS_CB_HPP diff --git a/ThirdParty/bitset2/detail/h_types.hpp b/ThirdParty/bitset2/detail/h_types.hpp new file mode 100644 index 00000000..94b9d9ee --- /dev/null +++ b/ThirdParty/bitset2/detail/h_types.hpp @@ -0,0 +1,107 @@ +// BITSET2 +// +// Copyright Claas Bontus +// +// Use, modification and distribution is subject to the +// Boost Software License, Version 1.0. (See accompanying +// file LICENSE.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// +// Project home: https://github.com/ClaasBontus/bitset2 +// + +#ifndef BITSET2_H_TYPES_CB_HPP +#define BITSET2_H_TYPES_CB_HPP + +#include <array> +#include <utility> +#include <climits> +#include <type_traits> + + +namespace Bitset2 +{ +namespace detail +{ + + template<class T,class Enabled=void> struct h_types; + + template<class T> + struct h_types<T, + typename std::enable_if< std::is_integral<T>::value + && std::is_unsigned<T>::value>::type> + { + using ULONG_t= unsigned long; + using ULLONG_t= unsigned long long; + using base_t= T; + + template<size_t n_array> + using array_t= std::array<base_t,n_array>; + + enum : size_t + { ulong_n_bits= sizeof(ULONG_t) * CHAR_BIT ///< #bits in ULONG_t + , ullong_n_bits= sizeof(ULLONG_t) * CHAR_BIT ///< #bits in ULLONG_t + , base_t_n_bits= sizeof(base_t) * CHAR_BIT ///< #bits in base_t + , npos= ~size_t(0) + }; + }; // struct h_types + + + template<class T> + constexpr + T + ce_min( T v1, T v2 ) noexcept + { return ( v1 < v2 ) ? v1 : v2; } + + + + /// http://stackoverflow.com/q/29136207/3876684 + template<class T> + constexpr + T + ce_left_shift( T v1, size_t n_shift ) noexcept + { + return ( n_shift == 0 ) ? v1 + : ( ( n_shift >= h_types<T>::base_t_n_bits ) ? T(0) + : T( v1 << n_shift ) ); + } + + template<class T> + constexpr + T + ce_right_shift( T v1, size_t n_shift ) noexcept + { + return ( n_shift == 0 ) ? v1 + : ( ( n_shift >= h_types<T>::base_t_n_bits ) ? T(0) + : T( v1 >> n_shift ) ); + } + + + + template<size_t n_array,class T,size_t ... S> + inline constexpr + typename h_types<T>::template array_t<n_array> + gen_empty_array_impl( std::index_sequence<S...> ) noexcept + { + return + typename h_types<T>::template array_t<n_array>{{ ( T(S) & T(0) ) ... }}; + } + + + + template<size_t n_array,class T> + inline constexpr + typename h_types<T>::template array_t<n_array> + gen_empty_array() noexcept + { + return + gen_empty_array_impl<n_array,T>( std::make_index_sequence<n_array>() ); + } // gen_empty_array + +} // namespace detail +} // namespace Bitset2 + + + + +#endif // BITSET2_H_TYPES_CB_HPP diff --git a/ThirdParty/bitset2/detail/hash.hpp b/ThirdParty/bitset2/detail/hash.hpp new file mode 100644 index 00000000..6248737c --- /dev/null +++ b/ThirdParty/bitset2/detail/hash.hpp @@ -0,0 +1,126 @@ +// BITSET2 +// +// Copyright Claas Bontus +// +// Use, modification and distribution is subject to the +// Boost Software License, Version 1.0. (See accompanying +// file LICENSE.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// +// Project home: https://github.com/ClaasBontus/bitset2 +// + +#ifndef BITSET2_HASH_CB_HPP +#define BITSET2_HASH_CB_HPP + +#include "h_types.hpp" + +#include <functional> +#include <array> +#include <climits> +#include <algorithm> + + +namespace Bitset2 +{ +namespace detail +{ + + +template<size_t n_words,class T> +struct hash_impl +{ + using base_t= T; + using result_type= std::size_t; + using array_t= typename h_types<T>::template array_t<n_words>; + + enum : size_t + { size_t_bits= sizeof(result_type) * CHAR_BIT ///< #bits in result_type + , base_t_n_bits= h_types<T>::base_t_n_bits ///< #bits in T + , bits_mod= base_t_n_bits % size_t_bits + , bits_div= base_t_n_bits / size_t_bits + ( bits_mod > 0 ) + , size_t_mod= size_t_bits % base_t_n_bits + , size_t_div= size_t_bits / base_t_n_bits + }; + + enum : bool + { easy_bits= ( size_t_bits >= base_t_n_bits ) + , easy_ratio= ( size_t_mod == 0 ) + }; + + result_type + operator()( array_t const & arr ) const noexcept + { + if( n_words == 0 ) return 0; + if( n_words == 1 ) + { + if( easy_bits ) return arr[0]; + return to_result_t( arr[0] ); + } // if n_words == 1 + + return cmpsd_hash( arr ); + } + + result_type + to_result_t( base_t a ) const noexcept + { + result_type ret_val= 0; + size_t shft= 0; + for( size_t c= 0; c < bits_div; ++c, shft += size_t_bits ) + { + auto const crrnt= result_type( a >> shft ); + do_combine( ret_val, crrnt, c ); + } + return ret_val; + } // to_result_t + + result_type + cmpsd_hash( array_t const & arr ) const noexcept + { + result_type ret_val= 0; + + if( easy_ratio ) + { + for( size_t c= 0; c < n_words; c += size_t_div ) + { + result_type r= 0; + auto const uppr= std::min( n_words, c + size_t_div ); + for( size_t w= c; w < uppr; ++w ) + r |= ( result_type(arr[w]) << ((w-c)*base_t_n_bits) ); + do_combine( ret_val, r, c / size_t_div ); + } + } + else + { + for( size_t c= 0; c < n_words; ++c ) + { + auto const crrnt= easy_bits + ? result_type(arr[c]) : to_result_t(arr[c]); + do_combine( ret_val, crrnt, c ); + } + } + + return ret_val; + } // cmpsd_hash + + void + do_combine( result_type &r, result_type crrnt, size_t cnt ) const noexcept + { + crrnt += cnt; + auto const n_rot= cnt % size_t_bits; + if( n_rot > 0 ) + crrnt= ( crrnt << n_rot ) | ( crrnt >> (size_t_bits-n_rot) ); + + r ^= crrnt; + } // do_combine +}; // struct hash_impl + + + + +} } // namespace Bitset2::detail + + + + +#endif // BITSET2_HASH_CB_HPP diff --git a/ThirdParty/bitset2/detail/hex_params.hpp b/ThirdParty/bitset2/detail/hex_params.hpp new file mode 100644 index 00000000..66e21f66 --- /dev/null +++ b/ThirdParty/bitset2/detail/hex_params.hpp @@ -0,0 +1,54 @@ +// BITSET2 +// +// Copyright Claas Bontus +// +// Use, modification and distribution is subject to the +// Boost Software License, Version 1.0. (See accompanying +// file LICENSE.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// +// Project home: https://github.com/ClaasBontus/bitset2 +// + +#ifndef BITSET2_HEX_PARAMS_CB_HPP +#define BITSET2_HEX_PARAMS_CB_HPP + +#include <string> + + +namespace Bitset2 +{ + + +template< class CharT = char, + class Traits = std::char_traits<CharT>, + class Allocator = std::allocator<CharT> > +struct hex_params +{ + using str_t= std::basic_string<CharT,Traits,Allocator>; + + hex_params( CharT zero_ch= CharT('0'), + CharT a_ch= CharT('a'), + bool leading_zeroes= true, + bool non_empty= true, + str_t const & prfx= str_t{} ) + : zeroCh{ zero_ch } + , aCh{ a_ch } + , leadingZeroes{ leading_zeroes } + , nonEmpty{ non_empty } + , prefix{ prfx } + {} + + CharT zeroCh= CharT( '0' ); + CharT aCh= CharT( 'a' ); + bool leadingZeroes= true; + bool nonEmpty= true; + str_t prefix; +}; // struct hex_params + + + +} // namespace Bitset2 + + +#endif // BITSET2_HEX_PARAMS_CB_HPP diff --git a/ThirdParty/bitset2/detail/index_lsb_set.hpp b/ThirdParty/bitset2/detail/index_lsb_set.hpp new file mode 100644 index 00000000..5c986ca6 --- /dev/null +++ b/ThirdParty/bitset2/detail/index_lsb_set.hpp @@ -0,0 +1,73 @@ +// BITSET2 +// +// Copyright Claas Bontus +// +// Use, modification and distribution is subject to the +// Boost Software License, Version 1.0. (See accompanying +// file LICENSE.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// +// Project home: https://github.com/ClaasBontus/bitset2 +// + + +#ifndef BITSET2_INDEX_LSB_SET_CB_HPP +#define BITSET2_INDEX_LSB_SET_CB_HPP + + +#include <limits> +#include <climits> +#include <cstddef> + + + +namespace Bitset2 +{ +namespace detail +{ + + +/// https://graphics.stanford.edu/~seander/bithacks.html#ZerosOnRightBinSearch +template<class T> +struct index_lsb_set +{ + enum : size_t { npos= std::numeric_limits<size_t>::max() + , n_bits= sizeof(T) * CHAR_BIT }; + + constexpr + index_lsb_set() noexcept + { + static_assert( ( n_bits & ( n_bits - 1 ) ) == 0, + "Number of bits in data type is not a power of 2" ); + } + + /// \brief Returns index of first (least significant) bit set in val. + /// Returns npos if all bits are zero. + constexpr + size_t + operator()( T val ) const noexcept + { + return ( T(0) == val ) ? npos + : find_idx( val, T( T(~T(0)) >> (n_bits >> 1) ), n_bits >> 1, 1 ); + } + +private: + constexpr + size_t + find_idx( T val, T pttrn, size_t sh_rght, size_t ct ) const noexcept + { + return ( sh_rght == 1 ) ? ( ct - size_t( T(val & T(0x1)) ) ) + : T( val & pttrn ) == T(0) + ? find_idx( T(val >> sh_rght), T( pttrn >> ( sh_rght >> 1 )), + sh_rght >> 1, ct + sh_rght ) + : find_idx( val, T(pttrn >> ( sh_rght >> 1 )), sh_rght >> 1, ct ); + } +}; // struct index_lsb_set + + + +} // namespace detail +} // namespace Bitset2 + + +#endif // BITSET2_INDEX_LSB_SET_CB_HPP diff --git a/ThirdParty/bitset2/detail/reverse_bits.hpp b/ThirdParty/bitset2/detail/reverse_bits.hpp new file mode 100644 index 00000000..f4e8db66 --- /dev/null +++ b/ThirdParty/bitset2/detail/reverse_bits.hpp @@ -0,0 +1,66 @@ +// BITSET2 +// +// Copyright Claas Bontus +// +// Use, modification and distribution is subject to the +// Boost Software License, Version 1.0. (See accompanying +// file LICENSE.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// +// Project home: https://github.com/ClaasBontus/bitset2 +// + +#ifndef BITSET2_REVERSE_BITS_CB_HPP +#define BITSET2_REVERSE_BITS_CB_HPP + +#include <limits> +#include <climits> +#include <cstddef> + + + +namespace Bitset2 +{ +namespace detail +{ + + +/// https://graphics.stanford.edu/~seander/bithacks.html#ReverseParallel +template<class T> +struct reverse_bits +{ + enum : size_t { n_bits= sizeof(T) * CHAR_BIT + , n_bits_h= n_bits >> 1 }; + + constexpr + reverse_bits() noexcept + { + static_assert( ( n_bits & ( n_bits - 1 ) ) == 0, + "Number of bits in data type is not a power of 2" ); + } + + /// \brief Reverses bits in val. + constexpr + T + operator()( T val ) const noexcept { return rvrs( val ); } + +private: + constexpr + T + rvrs( T val, + T mask= T( ~T(0) ) >> n_bits_h, + size_t s= n_bits_h ) const noexcept + { + return s == 0 ? val + : rvrs( ( (val >> s) & mask ) | ( (val << s) & ~mask ), + mask ^ ( mask << ( s >> 1 ) ), + s >> 1 ); + } +}; // struct reverse_bits + + +} // namespace detail +} // namespace Bitset2 + + +#endif // BITSET2_REVERSE_BITS_CB_HPP diff --git a/ThirdParty/bitset2/detail/select_base_t.hpp b/ThirdParty/bitset2/detail/select_base_t.hpp new file mode 100644 index 00000000..abfe9274 --- /dev/null +++ b/ThirdParty/bitset2/detail/select_base_t.hpp @@ -0,0 +1,82 @@ +// BITSET2 +// +// Copyright Claas Bontus +// +// Use, modification and distribution is subject to the +// Boost Software License, Version 1.0. (See accompanying +// file LICENSE.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// +// Project home: https://github.com/ClaasBontus/bitset2 +// + +#ifndef BITSET2_SELECT_BASE_T_CB_HPP +#define BITSET2_SELECT_BASE_T_CB_HPP + +#include <cstdint> +#include <cstddef> + +namespace Bitset2 +{ +namespace detail +{ + + +template<bool b,class T1, class T2> +struct if_else { using type= T1; }; + +template<class T1, class T2> +struct if_else<false,T1,T2> { using type= T2; }; + +template<bool b,class T1, class T2> +using if_else_t= typename if_else<b,T1,T2>::type ; + + +/// \brief Select any of uint8_t, uint16_t, uint32_t or +/// unsigned long long. Result depends on N and on provision +/// of these types by compiler. +template<size_t N> +struct select_base +{ +#ifdef INT8_MIN + enum : bool { has_int8= true }; + using UI8= uint8_t; +#else + enum : bool { has_int8= false }; + using UI8= void; +#endif +#ifdef INT16_MIN + enum : bool { has_int16= true }; + using UI16= uint16_t; +#else + enum : bool { has_int16= false }; + using UI16= void; +#endif +#ifdef INT32_MIN + enum : bool { has_int32= true }; + using UI32= uint32_t; +#else + enum : bool { has_int32= false }; + using UI32= void; +#endif + + using type= + if_else_t< has_int8 && (N<=8), UI8, + if_else_t< has_int16 && (N<=16), UI16, + if_else_t< has_int32 && (N<=32), UI32, + unsigned long long > > >; +}; // struct select_base + + +template<size_t N> +using select_base_t= typename select_base<N>::type; + + +} // namespace detail +} // namespace Bitset2 + + + + + +#endif // BITSET2_SELECT_BASE_T_CB_HPP diff --git a/ThirdParty/bitset2/detail/ullong2array.hpp b/ThirdParty/bitset2/detail/ullong2array.hpp new file mode 100644 index 00000000..41559858 --- /dev/null +++ b/ThirdParty/bitset2/detail/ullong2array.hpp @@ -0,0 +1,80 @@ +// BITSET2 +// +// Copyright Claas Bontus +// +// Use, modification and distribution is subject to the +// Boost Software License, Version 1.0. (See accompanying +// file LICENSE.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// +// Project home: https://github.com/ClaasBontus/bitset2 +// + + +#ifndef BITSET2_ULLONG2ARRAY_CB_HPP +#define BITSET2_ULLONG2ARRAY_CB_HPP + +#include "bit_chars.hpp" + + +namespace Bitset2 +{ +namespace detail +{ + + /// \brief Takes a variable 'v' of type unsigned long long + /// and returns a std::array 'a' equivalent to v. 'a' represents + /// an N bit bitset2 with base_t == T. + template<size_t N,class T> + struct ullong2array + { + using base_t= T; + using b_c= bit_chars<N,T>; + using ULLONG_t= typename b_c::ULLONG_t; + + enum : size_t + { n_bits= N + , base_t_n_bits= b_c::base_t_n_bits + , ullong_n_bits= b_c::ullong_n_bits + , n_array= b_c::n_array + , centrl_i= ce_min( (ullong_n_bits-1) / base_t_n_bits, n_array - 1 ) + , n_empty_vals= n_array - centrl_i - 1 + }; + + enum : base_t + { hgh_bit_pattern= b_c::hgh_bit_pattern + , use_pattern= (n_empty_vals==0) ? hgh_bit_pattern : base_t(~base_t(0)) + }; + + using array_t= typename h_types<T>::template array_t<n_array>; + + constexpr + array_t + operator()( ULLONG_t v ) const noexcept + { + return fill( gen_empty_array<n_array,T>(), v, + std::make_index_sequence<n_empty_vals>(), + std::make_index_sequence<centrl_i>() ); + } + + template<size_t ... S1,size_t ... S2> + constexpr + array_t + fill( array_t const & empty, ULLONG_t v, + std::index_sequence<S1...>, + std::index_sequence<S2...> ) const noexcept + { + return {{ base_t(ce_right_shift(v, S2 * base_t_n_bits))..., + base_t(ce_right_shift(v, centrl_i * base_t_n_bits)&use_pattern), + empty[S1]... }}; + } + }; // struct ullong2array + + +} // namespace detail +} // namespace Bitset2 + + + + +#endif // BITSET2_ULLONG2ARRAY_CB_HPP diff --git a/ThirdParty/bitset2/tests/bench01.cpp b/ThirdParty/bitset2/tests/bench01.cpp new file mode 100644 index 00000000..5e5e0071 --- /dev/null +++ b/ThirdParty/bitset2/tests/bench01.cpp @@ -0,0 +1,131 @@ +// BITSET2 +// +// Copyright Claas Bontus +// +// Use, modification and distribution is subject to the +// Boost Software License, Version 1.0. (See accompanying +// file LICENSE.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// +// Project home: https://github.com/ClaasBontus/bitset2 +// + + +#include "../bitset2.hpp" +#include "gen_randoms.hpp" +#include <iostream> +#include <cassert> +#include <chrono> + + + +using ULLONG= unsigned long long; + +template<size_t N> +using t1= Bitset2::bitset2<N>; + +template<size_t N> +using vec_t= std::vector<t1<N> >; + + +constexpr size_t n_loops= 1000000; + +template<size_t N> +vec_t<N> +gen_bs_vec( size_t n ) +{ + std::vector<t1<N> > ret_val; + gen_random_bitset2<N,ULLONG> gen_rand; + ret_val.reserve( n ); + for( size_t c= 0; c < n; ++c ) ret_val.push_back( gen_rand() ); + + return ret_val; +} // gen_bs_vec + + +template<size_t N> +void +apply_or_equal( vec_t<N> & v1, vec_t<N> const & v2 ) +{ + auto it2= v2.begin(); + for( auto & bs: v1 ) bs |= *(it2++); +} // apply_or_equal + + +template<size_t n> +std::array<ULLONG,n> & +rm_const( std::array<ULLONG,n> const & a ) +{ return const_cast<std::array<ULLONG,n> &>(a); } + + +template<size_t N> +void +array_or_equal( vec_t<N> & v1, vec_t<N> const & v2 ) +{ + auto const n_array= v1[0].data().size(); + auto it2= v2.begin(); + for( auto & bs: v1 ) + { + auto & a1= rm_const( bs.data() ); + auto & a2= it2->data(); + for( size_t c= 0; c < n_array; ++c ) a1[c] |= a2[c]; + + ++it2; + } +} + + +int main() +{ + auto const vec1= gen_bs_vec<2048>( 128 ); + auto const vec2= gen_bs_vec<2048>( 128 ); + + std::cout << "Running computations\n"; + + auto const t1 = std::chrono::high_resolution_clock::now(); + + auto v1= vec1; + for( size_t c= 0; c < n_loops; ++c ) + { + v1= vec1; + apply_or_equal( v1, vec2 ); + } + + auto const t2 = std::chrono::high_resolution_clock::now(); + + auto v1a= vec1; + for( size_t c= 0; c < n_loops; ++c ) + { + v1a= vec1; + array_or_equal( v1a, vec2 ); + } + + auto const t3 = std::chrono::high_resolution_clock::now(); + + assert( v1 == v1a ); + + for( size_t c= 0; c < n_loops; ++c ) + { + v1a= vec1; + array_or_equal( v1a, vec2 ); + } + + auto const t4 = std::chrono::high_resolution_clock::now(); + + for( size_t c= 0; c < n_loops; ++c ) + { + v1= vec1; + apply_or_equal( v1, vec2 ); + } + + auto const t5 = std::chrono::high_resolution_clock::now(); + const std::chrono::duration<double> dt21 = t2 -t1; + const std::chrono::duration<double> dt32 = t3 -t2; + const std::chrono::duration<double> dt43 = t4 -t3; + const std::chrono::duration<double> dt54 = t5 -t4; + + std::cout << "dt21= " << dt21.count() * 1.0e3 << "ms\n"; + std::cout << "dt32= " << dt32.count() * 1.0e3 << "ms\n"; + std::cout << "dt43= " << dt43.count() * 1.0e3 << "ms\n"; + std::cout << "dt54= " << dt54.count() * 1.0e3 << "ms\n"; +} // main diff --git a/ThirdParty/bitset2/tests/counter128.cpp b/ThirdParty/bitset2/tests/counter128.cpp new file mode 100644 index 00000000..8adbb698 --- /dev/null +++ b/ThirdParty/bitset2/tests/counter128.cpp @@ -0,0 +1,29 @@ +// BITSET2 +// +// Copyright Claas Bontus +// +// Use, modification and distribution is subject to the +// Boost Software License, Version 1.0. (See accompanying +// file LICENSE.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// +// Project home: https://github.com/ClaasBontus/bitset2 +// + + + +#include <iostream> +#include "bitset2.hpp" + + +int main() +{ + Bitset2::bitset2<128> c; + constexpr Bitset2::bitset2<128> tst{ 0xFFFFFFFFull }; + + for( ;; ++c ) + { + if( ( c & tst) == tst ) + std::cout << c.to_hex_string() << "\n"; + } +} // main diff --git a/ThirdParty/bitset2/tests/example01.cpp b/ThirdParty/bitset2/tests/example01.cpp new file mode 100644 index 00000000..af1aa2b3 --- /dev/null +++ b/ThirdParty/bitset2/tests/example01.cpp @@ -0,0 +1,52 @@ +// BITSET2 +// +// Copyright Claas Bontus +// +// Use, modification and distribution is subject to the +// Boost Software License, Version 1.0. (See accompanying +// file LICENSE.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// +// Project home: https://github.com/ClaasBontus/bitset2 +// + +#include <iostream> +#include <array> +#include <cassert> +#include "bitset2.hpp" + +template<size_t n_bits> +using BS2= Bitset2::bitset2<n_bits>; + +int main() +{ + using bs_128= BS2<128>; + using base_t_128= bs_128::base_t; + constexpr std::array<base_t_128,2> + ar1{{ ~(base_t_128(0)), base_t_128(0xFEDCBA) }}; + constexpr bs_128 b1{ ar1 }; + constexpr auto b1_add= b1 + b1; + constexpr auto b1_shft= b1 << 1; // binary shift + static_assert( b1_add == b1_shft, "" ); + + std::cout << b1.to_hex_string() // 0000000000fedcbaffffffffffffffff + << "\n" + << b1_add.to_hex_string() // 0000000001fdb975fffffffffffffffe + << "\n"; + + BS2<12> b2; + for( size_t c= 0; c < 12; c += 2 ) b2[c]= true; + auto b3= ~b2; + std::cout << b2 << "\n"; // 010101010101 + std::cout << b2.flip() << "\n"; // 101010101010 + assert( b2 == b3 ); + + BS2<7> const b4{ "1110000" }; + auto const b5= Bitset2::rotate_left( b4, 3 ); + std::cout << b4 << "\n" // 1110000 + << b5 << "\n"; // 0000111 + + BS2<7> b6{ "1010010" }; + b6.reverse(); + std::cout << b6 << "\n"; // 0100101 +} // main diff --git a/ThirdParty/bitset2/tests/gen_randoms.hpp b/ThirdParty/bitset2/tests/gen_randoms.hpp new file mode 100644 index 00000000..9a95e27d --- /dev/null +++ b/ThirdParty/bitset2/tests/gen_randoms.hpp @@ -0,0 +1,108 @@ +// BITSET2 +// +// Copyright Claas Bontus +// +// Use, modification and distribution is subject to the +// Boost Software License, Version 1.0. (See accompanying +// file LICENSE.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// +// Project home: https://github.com/ClaasBontus/bitset2 +// + + +#ifndef BITSET2_GEN_RANDOMS_CB_HPP +#define BITSET2_GEN_RANDOMS_CB_HPP + +#include "../bitset2.hpp" +#include <random> +#include <climits> +#include <array> +#include <vector> + + + +template<class T> +class gen_randoms +{ +public: + gen_randoms( T max_val, T min_val= 0 ) + : m_generator( std::random_device{}() ) + , m_distri( min_val, max_val ) + {} + // + T + operator()() + { return m_distri( m_generator ); } + // +private: + std::mt19937 m_generator; + std::uniform_int_distribution<T> m_distri; +}; // class gen_randoms + + + + +/// Generate N-bit sized bitset2 randomly +template<size_t N,class T> +class gen_random_bitset2 +{ + // + enum : size_t + { base_t_n_bits= sizeof(T) * CHAR_BIT + , div_val= N / base_t_n_bits + , mod_val= N % base_t_n_bits + , n_words= mod_val ? div_val + 1 : div_val + }; + enum : T + { max_ullong= T(~T(0)) + , hgh_bit_pattern= + N == 0 ? T(0) + : mod_val == 0 + ? max_ullong + : max_ullong >> T(base_t_n_bits-mod_val) + }; + // + using arr_t= std::array<T,n_words>; + // +public: + using b_t= Bitset2::bitset2<N,T>; + // + gen_random_bitset2() + : m_gen{ gen_generators() } + {} + // + b_t + operator()() + { + arr_t a; + for( size_t c= 0; c < n_words; ++c ) a[c]= m_gen[c](); + return b_t( a ); + } + // +private: + using gen_rand_t= gen_randoms<T>; + + std::vector<gen_rand_t> m_gen; + // + std::vector<gen_rand_t> + gen_generators() + { + std::vector<gen_rand_t> ret_val; + + if( n_words > 0 ) + { + ret_val.reserve( n_words ); + for( size_t c= 0; c < n_words - 1; ++c ) + ret_val.push_back( gen_rand_t{ max_ullong } ); + ret_val.push_back( gen_rand_t{ hgh_bit_pattern } ); + } + + return ret_val; + } +}; // gen_random_bitset2 + + + + +#endif // BITSET2_GEN_RANDOMS_CB_HPP diff --git a/ThirdParty/bitset2/tests/gray_code.cpp b/ThirdParty/bitset2/tests/gray_code.cpp new file mode 100644 index 00000000..72765bb9 --- /dev/null +++ b/ThirdParty/bitset2/tests/gray_code.cpp @@ -0,0 +1,50 @@ +// BITSET2 +// +// Copyright Claas Bontus +// +// Use, modification and distribution is subject to the +// Boost Software License, Version 1.0. (See accompanying +// file LICENSE.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// +// Project home: https://github.com/ClaasBontus/bitset2 +// + + +#include "../bitset2.hpp" +#include <cassert> +#include <iostream> + + +template<size_t N,class T> +constexpr +Bitset2::bitset2<N,T> +binary_to_gray( Bitset2::bitset2<N,T> const &bs ) +{ return bs ^ (bs >> 1); } + + +template<size_t N,class T> +constexpr +Bitset2::bitset2<N,T> +gray_to_binary( Bitset2::bitset2<N,T> bs ) +{ + Bitset2::bitset2<N,T> mask= bs >> 1; + for( ; !mask.none(); mask >>= 1 ) bs ^= mask; + return bs; +} // gray_to_binary + + +int main() +{ + using ULLONG= unsigned long long; + constexpr std::array<ULLONG,2> arr_01a{{ 0xFEFDFCFBFAF9F8F7ull, 1ull }}; + constexpr Bitset2::bitset2<129> bs_01a{ arr_01a }; + constexpr auto gray_01a= binary_to_gray( bs_01a ); + constexpr auto bin_01a= gray_to_binary( gray_01a ); + + static_assert( bs_01a == bin_01a ); + + std::cout << bs_01a << '\n' << gray_01a << '\n'; + + return 0; +} // main diff --git a/ThirdParty/bitset2/tests/mk.sh b/ThirdParty/bitset2/tests/mk.sh new file mode 100755 index 00000000..45d30d11 --- /dev/null +++ b/ThirdParty/bitset2/tests/mk.sh @@ -0,0 +1,43 @@ +cc=g++-7 +#cc=clang++ + + +p=gray_code +echo "Compiling $p" +$cc -O2 -Wall -Wextra -std=c++1z -I.. -I../detail -fdiagnostics-color=auto $p.cpp -o $p + +p=test_nonconst_constexpr01 +echo "Compiling $p" +$cc -O2 -Wall -Wextra -std=c++1z -I.. -I../detail -fdiagnostics-color=auto $p.cpp -o $p + +p=test_array2array +echo "Compiling $p" +$cc -O2 -Wall -Wextra -std=c++1z -I.. -I../detail -fdiagnostics-color=auto $p.cpp -o $p + +p=tests01 +echo "Compiling $p" +$cc -O2 -Wall -Wextra -std=c++1z -I.. -fdiagnostics-color=auto $p.cpp -o $p + +p=test_bitset2_01 +echo "Compiling $p" +$cc -O2 -Wall -Wextra -Wno-unused-but-set-variable -std=c++1z -I.. -fdiagnostics-color=auto $p.cpp -o $p + +p=test_bitset2_02 +echo "Compiling $p" +$cc -O2 -Wall -Wextra -std=c++1z -I.. -fdiagnostics-color=auto $p.cpp -o $p + +p=counter128 +echo "Compiling $p" +$cc -O2 -Wall -Wextra -std=c++1z -I.. -fdiagnostics-color=auto $p.cpp -o $p + +p=bench01 +echo "Compiling $p" +$cc -O2 -Wall -Wextra -std=c++1z -I.. -fdiagnostics-color=auto -D_GLIBCXX_USE_NANOSLEEP $p.cpp -o $p + +p=example01 +echo "Compiling $p" +$cc -O2 -Wall -Wextra -std=c++1z -I.. -fdiagnostics-color=auto $p.cpp -o $p + +p=test_ullong2array +echo "Compiling $p" +$cc -O2 -Wall -Wextra -std=c++1z -I.. -I../detail -fdiagnostics-color=auto $p.cpp -o $p diff --git a/ThirdParty/bitset2/tests/test_array2array.cpp b/ThirdParty/bitset2/tests/test_array2array.cpp new file mode 100644 index 00000000..70bb3e5a --- /dev/null +++ b/ThirdParty/bitset2/tests/test_array2array.cpp @@ -0,0 +1,111 @@ +// BITSET2 +// +// Copyright Claas Bontus +// +// Use, modification and distribution is subject to the +// Boost Software License, Version 1.0. (See accompanying +// file LICENSE.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// +// Project home: https://github.com/ClaasBontus/bitset2 +// + + +#include "array2array.hpp" +#include "gen_randoms.hpp" +#include <iostream> +#include <cstdint> +#include <cassert> + + + +constexpr size_t n_loops= 100000; + + + +template<class T1,class T2> +void +fwd_bckwd() +{ + constexpr size_t bits_T1= sizeof(T1) * CHAR_BIT; + constexpr size_t bits_T2= sizeof(T2) * CHAR_BIT; + + constexpr size_t t_n1= 8, s_n1= 1; + constexpr size_t t_n2= 24, s_n2= 3; + + using a2a_t1a= Bitset2::detail::array2array<t_n1,s_n1,T2,T1>; + using a2a_t1b= Bitset2::detail::array2array<s_n1,t_n1,T1,T2>; + using a2a_t2a= Bitset2::detail::array2array<t_n1,s_n1,T1,T2>; + using a2a_t2b= Bitset2::detail::array2array<s_n1,t_n1,T2,T1>; + + using a2a_t3a= Bitset2::detail::array2array<t_n2,s_n2,T2,T1>; + using a2a_t3b= Bitset2::detail::array2array<s_n2,t_n2,T1,T2>; + using a2a_t4a= Bitset2::detail::array2array<t_n2,s_n2,T1,T2>; + using a2a_t4b= Bitset2::detail::array2array<s_n2,t_n2,T2,T1>; + + gen_random_bitset2<s_n1*bits_T1,T1> gen_rand1a; + gen_random_bitset2<s_n1*bits_T2,T2> gen_rand1b; + + gen_random_bitset2<s_n2*bits_T1-bits_T1/2,T1> gen_rand2a; + gen_random_bitset2<s_n2*bits_T2-bits_T2/2,T2> gen_rand2b; + + for( size_t ct= 0; ct < n_loops; ++ct ) + { + // if( (ct+1) % 1000 == 0 ) std::cout << (ct+1) << '\n'; + + auto const bs1= gen_rand1a(); + auto const a1a= a2a_t1a()( ~T2(0), bs1.data() ); + auto const a1b= a2a_t1b()( ~T1(0), a1a ); + assert( bs1.data() == a1b ); + + auto const bs2= gen_rand1b(); + auto const a2a= a2a_t2a()( ~T1(0), bs2.data() ); + auto const a2b= a2a_t2b()( ~T2(0), a2a ); + assert( bs2.data() == a2b ); + + auto const bs3= gen_rand2a(); + auto const a3a= a2a_t3a()( ~T2(0), bs3.data() ); + auto const a3b= a2a_t3b()( T1(T1(~T1(0)) >> (bits_T1/2)), a3a ); + assert( bs3.data() == a3b ); + + auto const bs4= gen_rand2b(); + auto const a4a= a2a_t4a()( ~T1(0), bs4.data() ); + auto const a4b= a2a_t4b()( T2(T2(~T2(0)) >> (bits_T2/2)), a4a ); + assert( bs4.data() == a4b ); + } // for ct +} // fwd_bckwd + + +int main() +{ + + constexpr size_t t_n1= 2, s_n1= 2; + + std::cout << Bitset2::detail::array2array<t_n1,s_n1,uint16_t,uint8_t>::h_all_set + << " " + // << Bitset2::detail::array2array<t_n1,s_n1,uint8_t,uint16_t>::h_all_set + // << " " + << Bitset2::detail::array2array<t_n1,s_n1,uint8_t,uint32_t>::h_all_set + << " " + << Bitset2::detail::array2array<t_n1,s_n1,uint16_t,uint32_t>::h_all_set + << " " + << Bitset2::detail::array2array<t_n1,s_n1,uint16_t,uint64_t>::h_all_set + << " " + << Bitset2::detail::array2array<t_n1,s_n1,uint32_t,uint64_t>::h_all_set + << '\n'; + + std::cout << " 8 <-> 64\n"; + fwd_bckwd<uint8_t,uint64_t>(); + std::cout << "16 <-> 64\n"; + fwd_bckwd<uint16_t,uint64_t>(); + std::cout << "32 <-> 64\n"; + fwd_bckwd<uint32_t,uint64_t>(); + + std::cout << "\n 8 <-> 32\n"; + fwd_bckwd<uint8_t,uint32_t>(); + std::cout << "16 <-> 32\n"; + fwd_bckwd<uint16_t,uint32_t>(); + + std::cout << "\n 8 <-> 16\n"; + fwd_bckwd<uint8_t,uint16_t>(); +} // main diff --git a/ThirdParty/bitset2/tests/test_bitset2_01.cpp b/ThirdParty/bitset2/tests/test_bitset2_01.cpp new file mode 100644 index 00000000..2113e96f --- /dev/null +++ b/ThirdParty/bitset2/tests/test_bitset2_01.cpp @@ -0,0 +1,420 @@ +// BITSET2 +// +// Copyright Claas Bontus +// +// Use, modification and distribution is subject to the +// Boost Software License, Version 1.0. (See accompanying +// file LICENSE.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// +// Project home: https://github.com/ClaasBontus/bitset2 +// + + +#include <iostream> +#include <sstream> +#include <cassert> +#include "bitset2.hpp" + + +template<size_t N,class T> +constexpr +bool +is_subset_of( Bitset2::bitset2<N,T> const &bs1, + Bitset2::bitset2<N,T> const &bs2 ) noexcept +{ + using base_t= T; + return Bitset2::zip_fold_and( bs1, bs2, + []( base_t v1, base_t v2 ) noexcept + { return (v1 & ~v2) == 0; } ); +} // is_subset_of + + +template<size_t N,class T> +constexpr +bool +unequal( Bitset2::bitset2<N,T> const &bs1, + Bitset2::bitset2<N,T> const &bs2 ) noexcept +{ + using base_t= T; + return Bitset2::zip_fold_or( bs1, bs2, + []( base_t v1, base_t v2 ) noexcept + { return v1 != v2; } ); +} // unequal + + + +int main() +{ + using namespace Bitset2; + using ULLONG= unsigned long long; + + constexpr bitset2<32> b1; + constexpr auto v1= b1.to_ullong(); + constexpr auto b1_n= ~b1; + constexpr bool b1_n_none= b1_n.none(); + constexpr bool b1_n_all= b1_n.all(); + constexpr bool b1_n_any= b1_n.any(); + + bitset2<63> b_63; + bitset2<64> b_64; + bitset2<65> b_65; + auto b1a= b1; + b1a.set(); + b_63.set(); + b_64.set(); + b_65.set(); + + std::bitset<65> sb1; + auto sb2= std::bitset<32>( b1 ); + sb1[64]= 1; + + bitset2<65> b2( sb1 ); + + std::cout << v1 << "\n" + << b2 << "\n" + << sb2 << "\n" + << b1_n << "\n" + << "b1.none()= " << b1.none() << " " + << "b1.any()= " << b1.any() << " " + << "b1.all()= " << b1.all() << "\n" + << "b1a.none()= " << b1a.none() << " " + << "b1a.any()= " << b1a.any() << " " + << "b1a.all()= " << b1a.all() << "\n" + << "b2.none()= " << b2.none() << " " + << "b2.any()= " << b2.any() << " " + << "b2.all()= " << b2.all() << "\n" + << "b1_n.none()= " << b1_n_none << " " + << "b1_n.any()= " << b1_n_any << " " + << "b1_n.all()= " << b1_n_all << "\n" + << "b_63.all()= " << b_63.all() << " " + << "b_64.all()= " << b_64.all() << " " + << "b_65.all()= " << b_65.all() << "\n"; + std::cout << "b_63.flip()= " << b_63.flip() << "\n" + << "b_64.flip()= " << b_64.flip() << "\n" + << "b_65.flip()= " << b_65.flip() << "\n"; + std::cout << "b_63.flip()= " << b_63.flip() << "\n" + << "b_64.flip()= " << b_64.flip() << "\n" + << "b_65.flip()= " << b_65.flip() << "\n"; + std::cout << "b_63.reset()= " << b_63.reset() << "\n" + << "b_64.reset()= " << b_64.reset() << "\n" + << "b_65.reset()= " << b_65.reset() << "\n"; + + detail::bit_chars<4,ULLONG> bc1; + detail::bit_chars<64,ULLONG> bc2; + detail::bit_chars<65,ULLONG> bc3; + detail::bit_chars<63,ULLONG> bc4; + + bitset2<64> lbp1( bc1.low_bit_pattern ); + bitset2<64> lbp2( bc2.low_bit_pattern ); + bitset2<64> lbp3( bc3.low_bit_pattern ); + bitset2<64> lbp4( bc4.low_bit_pattern ); + + std::cout << bc1.low_bit_pattern << " " << bc1.mod_val << "\n" + << " " << lbp1 << "\n" + << bc2.low_bit_pattern << " " << bc2.mod_val << "\n" + << " " << lbp2 << "\n" + << bc3.low_bit_pattern << " " << bc3.mod_val << "\n" + << " " << lbp3 << "\n" + << bc4.low_bit_pattern << " " << bc4.mod_val << "\n" + << " " << lbp4 << "\n"; + + constexpr + std::array<unsigned long long,2> ar1{{ ~(0ull), 1 }}; + + constexpr + auto s_ar1= detail::array_ops<128,ULLONG>( 63 ).shift_left( ar1 ); + + std::cout << "\n" << ar1[1] << " " << ar1[0] << "\n"; + std::cout << "\n" << s_ar1[1] << " " << s_ar1[0] << "\n"; + + bitset2<63> bc5{ 1ull }; + bitset2<64> bc6{ 1ull }; + bitset2<65> bc7{ 1ull }; + constexpr bitset2<63> bc5a{ 1ull }; + constexpr bitset2<64> bc6a{ 1ull }; + constexpr bitset2<65> bc7a{ 1ull }; + constexpr bitset2<127> bc8a{ 1ull }; + constexpr bitset2<128> bc9a{ 1ull }; + constexpr bitset2<129> bc10a{ 1ull }; + constexpr auto bc5b= bc5a << 62; + constexpr auto bc6b= bc6a << 63; + constexpr auto bc7b= bc7a << 64; + constexpr auto bc8b= bc8a << 62; + constexpr auto bc8c= bc8a << 63; + constexpr auto bc8d= bc8a << 64; + constexpr auto bc9b= bc9a << 62; + constexpr auto bc9c= bc9a << 63; + constexpr auto bc9d= bc9a << 64; + constexpr auto bc10b= bc10a << 62; + constexpr auto bc10c= bc10a << 63; + constexpr auto bc10d= bc10a << 64; + std::cout << " " << bc8b << "\n " << bc8c << "\n " << bc8d << "\n"; + std::cout << " " << bc9b << "\n " << bc9c << "\n " << bc9d << "\n"; + std::cout << bc10b << "\n" << bc10c << "\n" << bc10d << "\n"; + std::cout << bc5b << " " << bc6b << " " << bc7b << "\n"; + for( size_t c= 0; c < 66; ++c ) + { + std::cout << bc5 << " " << bc6 << " " << bc7 << "\n"; + bc5 <<= 1; bc6 <<= 1; bc7 <<= 1; + } + + std::cout << "\n"; + constexpr auto bc5c= bc5b >> 62; + constexpr auto bc6c= bc6b >> 63; + constexpr auto bc7c= bc7b >> 64; + std::cout << bc5c << " " << bc6c << " " << bc7c << "\n"; + + constexpr auto bc5d= bc5a | bc5b; + constexpr auto bc5e= bc5d & bc5a; + constexpr auto bc5f= bc5d & bc5b; + constexpr auto bc5g= bc5a ^ bc5b; + constexpr auto bc5h= bc5d ^ bc5a; + constexpr auto bc5i= bc5d ^ bc5b; + constexpr auto bc5j= bc5a << 1; + std::cout << "\n" << bc5a << " |\n" << bc5b << " =\n" << bc5d << "\n"; + std::cout << "\n" << bc5d << " &\n" << bc5a << " =\n" << bc5e << "\n"; + std::cout << "\n" << bc5d << " &\n" << bc5b << " =\n" << bc5f << "\n"; + std::cout << "\n" << bc5a << " ^\n" << bc5b << " =\n" << bc5g << "\n"; + std::cout << "\n" << bc5d << " ^\n" << bc5a << " =\n" << bc5h << "\n"; + std::cout << "\n" << bc5d << " ^\n" << bc5b << " =\n" << bc5i << "\n"; + std::cout << "\n" << bc5a << " << 1 = " << bc5j << "\n"; + + constexpr auto bc7d= bc7a | bc7b; + constexpr auto bc7e= bc7d & bc7a; + constexpr auto bc7f= bc7d & bc7b; + constexpr auto bc7g= bc7a ^ bc7b; + constexpr auto bc7h= bc7d ^ bc7a; + constexpr auto bc7i= bc7d ^ bc7b; + std::cout << "\n" << bc7a << " |\n" << bc7b << " =\n" << bc7d << "\n"; + std::cout << "\n" << bc7d << " &\n" << bc7a << " =\n" << bc7e << "\n"; + std::cout << "\n" << bc7d << " &\n" << bc7b << " =\n" << bc7f << "\n"; + std::cout << "\n" << bc7a << " ^\n" << bc7b << " =\n" << bc7g << "\n"; + std::cout << "\n" << bc7d << " ^\n" << bc7a << " =\n" << bc7h << "\n"; + std::cout << "\n" << bc7d << " ^\n" << bc7b << " =\n" << bc7i << "\n"; + + constexpr auto bc5a_f= ~bc5a; + constexpr auto bc5d_f= ~bc5d; + constexpr auto bc7a_f= ~bc7a; + constexpr auto bc7d_f= ~bc7d; + std::cout << "\n~" << bc5a << " =\n " << bc5a_f << "\n"; + std::cout << "\n~" << bc5d << " =\n " << bc5d_f << "\n"; + std::cout << "\n~" << bc7a << " =\n " << bc7a_f << "\n"; + std::cout << "\n~" << bc7d << " =\n " << bc7d_f << "\n"; + std::cout << "\n"; + bitset2<65> bc11a{ 1ull }; + bitset2<65> bc11b{ 1ull }; + bc11b <<= 64; + bc11b |= ( bc11a << 1 ); + std::cout << bc11b << "\n"; + bc11b >>= 1; + std::cout << bc11b << "\n"; + std::cout << bc11b.to_string( '.', 'x' ) << "\n"; + + constexpr auto n_5a= bc5a.count(); + constexpr auto n_5a_f= bc5a_f.count(); + constexpr auto n_7a= bc7a.count(); + constexpr auto n_7a_f= bc7a_f.count(); + std::cout << "count( " << bc5a << " )= " << n_5a << "\n"; + std::cout << "count( " << bc5a_f << " )= " << n_5a_f << "\n"; + std::cout << "count( " << bc7a << " )= " << n_7a << "\n"; + std::cout << "count( " << bc7a_f << " )= " << n_7a_f << "\n"; + std::cout << "\n"; + b_63.reset(); + b_64.reset(); + b_65.reset(); + auto b_63a= b_63; + auto b_64a= b_64; + auto b_65a= b_65; + for( size_t c= 0; c < 64; c += 2 ) + { + if( c < 63 ) b_63[c]= true; + if( c < 64 ) b_64[c]= true; + if( c < 65 ) b_65[c]= true; + b_63a[c/2]= true; b_64a[c/2]= true; b_65a[c/2]= true; + } + std::cout << "Hash values:\n"; + std::cout << " " << b_63 << " " << std::hash<bitset2<63>>()( b_63 ) << "\n" + << " " << b_64 << " " << std::hash<bitset2<64>>()( b_64 ) << "\n" + << b_65 << " " << std::hash<bitset2<65>>()( b_65 ) << "\n"; + + bitset2<0> b_0a, b_0b; + constexpr auto bl_c7d= bc7d == bc7d; + std::cout << "\n" << ( b_63 == b_63 ) << " " + << ( b_64 == b_64 ) << " " + << ( b_65 == b_65 ) << "\n" + << ( b_63 != b_63a ) << " " + << ( b_64 != b_64a ) << " " + << ( b_65 != b_65a ) << " " + << bl_c7d << "\n" + << ( b_0a == b_0b ) << "\n"; + + constexpr bitset2<65> bs33a( 0xFFFFFFFFFFFFFFFFull ); + // constexpr auto bs33b= ( bs33a << 1 ); + //constexpr + auto bs33a_v= bs33a.to_ulong(); + std::cout << bs33a << " == " << bs33a_v << " == " << bs33a.to_hex_string() << "\n"; + // auto bs33b_v= bs33b.to_ulong(); // throws + // std::cout << bs33b << " == " << bs33b_v << "\n"; + + bitset2<63> bc2_63{ 0x700000000000000Eull }; + constexpr bitset2<63> bc2_63a{ 0x700000000000000Eull }; + constexpr auto bc2_63b= rotate_right( bc2_63a, 5 ); + bitset2<65> bc2_65{ 0x700000000000000Eull }; + constexpr bitset2<65> bc2_65a{ 0x700000000000000Eull }; + constexpr auto bc2_65b= rotate_right( bc2_65a, 5 ); + std::cout << " bc2_63= " << bc2_63 + << " == " << bc2_63.to_hex_string() << "\n"; + bc2_63.rotate_left( 5 ); + std::cout << "rot_left( bc2_63, 5) = " << bc2_63 << "\n"; + std::cout << "rot_right( bc2_63a,5)= " << bc2_63b << "\n"; + + std::cout << " bc2_65= " << bc2_65 + << " == " << bc2_65.to_hex_string() << "\n"; + bc2_65.rotate_left( 5 ); + std::cout << "rot_left( bc2_65, 5) = " << bc2_65 << "\n"; + std::cout << "rot_right( bc2_65a,5)= " << bc2_65b << "\n"; + + constexpr auto add_b5a= bc5a + bc5j; + constexpr auto add_b5b= bc5a + bc5a; + std::cout << bc5a << " +\n" << bc5j << " =\n" << add_b5a << "\n"; + std::cout << bc5a << " +\n" << bc5a << " =\n" << add_b5b << "\n"; + + constexpr std::array<ULLONG,2> arr_add_01a{{ 0xFFFFFFFFFFFFFFFFull, 0ull }}; + std::array<ULLONG,2> arr_add_01ap{{ 0xFFFFFFFFFFFFFFFFull, 0ull }}; + constexpr std::array<ULLONG,2> arr_add_01b{{ 0xFFFFFFFFFFFFFFFFull, 1ull }}; + constexpr bitset2<64> b_a_01a( 0xFFFFFFFFFFFFFFFFull ); + constexpr bitset2<128> b_a_02a( arr_add_01a ); + bitset2<128> b_a_02ap( arr_add_01ap ); + constexpr bitset2<128> b_a_02b( arr_add_01b ); + + std::cout << b_a_02ap.to_hex_string() << "\n"; + + constexpr auto add_b_a_01a= b_a_01a + b_a_01a; + constexpr auto add_b_a_02a= b_a_02a + b_a_02a; + constexpr auto add_b_a_02b= b_a_02a + b_a_02b; + constexpr auto add_b_a_02c= b_a_02b + b_a_02b; + std::cout << b_a_01a << " +\n" << b_a_01a << " =\n" << add_b_a_01a << "\n\n"; + std::cout << b_a_02a << " +\n" << b_a_02a << " =\n" << add_b_a_02a << "\n\n"; + std::cout << b_a_02a << " +\n" << b_a_02b << " =\n" << add_b_a_02b << "\n\n"; + std::cout << b_a_02b << " +\n" << b_a_02b << " =\n" << add_b_a_02c << "\n\n"; + + bitset2<65> bc2_65c{ 0xF00000000000000Eull }; + std::cout << bc2_65c << " +\n" << bc2_65a << " =\n"; + bc2_65c += bc2_65a; + std::cout << bc2_65c << "\n\n"; + + bitset2<65> bc2_65d{ 0xFFFFFFFFFFFFFFFEull }; + std::cout << "++" << bc2_65d << "=\n "; + std::cout << (++bc2_65d) << "\n"; + + bitset2<65> bc2_65e = bc2_65d << 1; + + std::cout << "++" << bc2_65d << "=\n "; + std::cout << (++bc2_65d) << "\n"; + + std::cout << "++" << bc2_65e << "=\n "; + std::cout << (++bc2_65e) << "\n"; + std::cout << " " << bc2_65e << "++ =\n "; + bc2_65e++; + std::cout << bc2_65e << "\n"; + + bitset2<65> bc2_65f= bitset2<65>{1ull} << 64; + bitset2<65> bc2_65g; + std::cout << "\n--" << bc2_65f << "=\n "; + std::cout << (--bc2_65f) << "\n"; + std::cout << " " << bc2_65f << "-- =\n "; + bc2_65f--; + std::cout << bc2_65f << "\n"; + std::cout << "--" << bc2_65g << "=\n "; + std::cout << (--bc2_65g) << "\n"; + + std::string bit_string = "101110"; + std::istringstream bit_stream( bit_string ); + bitset2<3> b_from_stream1; + bitset2<3> b_from_str2( bit_string, 3 ); + bitset2<4> b_from_str3( bit_string.c_str() + 1, 3 ); + bit_stream >> b_from_stream1; + std::cout << b_from_stream1 + << "= 0x" << b_from_stream1.to_hex_string() << '\n'; + std::cout << b_from_str2 + << "= 0x" << b_from_str2.to_hex_string() << '\n'; + std::cout << b_from_str3 + << "= 0x" << b_from_str3.to_hex_string() << '\n'; + + + constexpr std::array<ULLONG,1> s_arr_01a{{ 1ull }}; + constexpr std::array<ULLONG,2> s_arr_01b{{ 0xFFFFFFFFFFFFFFFFull, 1ull }}; + constexpr std::array<ULLONG,3> s_arr_01c{{ 0x1ull, 0xFFFFFFFFFFFFFFFFull, 0x3ull }}; + constexpr std::array<ULLONG,4> s_arr_01d{{ 0xEEEEEEEEEEEEEEEEull, 0xDull, 1ull, 0xFFFFFFFFFFFFFFFFull }}; + constexpr bitset2<129> b_from_s_arr01a{ s_arr_01a }; + constexpr bitset2<129> b_from_s_arr01b{ s_arr_01b }; + constexpr bitset2<129> b_from_s_arr01c{ s_arr_01c }; + constexpr bitset2<129> b_from_s_arr01d{ s_arr_01d }; + std::cout << "b_from_s_arr01a= " << b_from_s_arr01a.to_hex_string() << "\n"; + std::cout << "b_from_s_arr01b= " << b_from_s_arr01b.to_hex_string() << "\n"; + std::cout << "b_from_s_arr01c= " << b_from_s_arr01c.to_hex_string() << "\n"; + std::cout << "b_from_s_arr01d= " << b_from_s_arr01d.to_hex_string() << "\n"; + + constexpr bitset2<24> b24_empty{ 0ull }; + constexpr bitset2<24> b24_full= ~b24_empty; + constexpr bitset2<23> b23_a= convert_to<23>( b24_full ); + constexpr bitset2<25> b25_a= convert_to<25>( b24_full ); + constexpr auto b24_full_ui8= convert_to<24,uint8_t>( b24_full ); + std::cout << "b24_full= " << b24_full << "\n"; + std::cout << "b23_a= " << b23_a << "\n"; + std::cout << "b25_a= " << b25_a << "\n"; + std::cout << "b24_full_ui8= " << b24_full_ui8 << '\n'; + + bitset2<7> b7_a( "1010101" ); + bitset2<7> b7_b( "1000101" ); + bitset2<7> b7_c( "1110101" ); + bitset2<7> b7_d( "0110101" ); + bitset2<7> b7_e( "1010101" ); + + constexpr bitset2<7> b7_a_ce( 0b1010101ull ); + constexpr bitset2<7> b7_b_ce( 0b1000101ull ); + + assert( is_subset_of( b7_b, b7_a ) ); + assert( !is_subset_of( b7_c, b7_a ) ); + assert( !is_subset_of( b7_d, b7_a ) ); + assert( !is_subset_of( b7_a, b7_d ) ); + + assert( unequal( b7_a, b7_b ) ); + assert( !unequal( b7_e, b7_a ) ); + + static_assert( is_subset_of( b7_b_ce, b7_a_ce ), "" ); + static_assert( unequal( b7_a_ce, b7_b_ce ), "" ); + + assert( b7_b < b7_a ); + assert( b7_c > b7_a ); + assert( b7_e <= b7_a ); + assert( b7_a >= b7_d ); + + bitset2<2047> b2047_a( 1ull ); + auto b2047_b= b2047_a << 999; + auto b2047_c= b2047_a + b2047_b; + auto b2047_d= b2047_a << 1999; + std::cout << "b2047_a= " << b2047_a.to_hex_string() << "\n" + << "b2047_b= " << b2047_b.to_hex_string() << "\n" + << "b2047_c= " << b2047_c.to_hex_string() << "\n"; + std::cout << "bitset2<2047>::n_array= " << bitset2<2047>::n_array << '\n'; + assert( unequal( b2047_a, b2047_b ) ); + assert( unequal( b2047_b, b2047_d ) ); + assert( is_subset_of( b2047_a, b2047_c ) ); + assert( !is_subset_of( b2047_b, b2047_d ) ); + + bitset2<16> b16_a( "0000101000011111" ); + bitset2<16> b16_b; + hex_params<> hp1; + hp1.aCh= 'A'; + hp1.leadingZeroes= false; + hp1.prefix= "0x"; + std::cout << '\n' + << b16_a.to_hex_string() << '\n' // 0a1f + << b16_a.to_hex_string( hp1 ) // 0xA1F + << '\n' + << b16_b.to_hex_string() << '\n' // 0000 + << b16_b.to_hex_string( hex_params<>{'0', 'a', false, false, "0X"}) // 0X + << '\n'; +} // main diff --git a/ThirdParty/bitset2/tests/test_bitset2_02.cpp b/ThirdParty/bitset2/tests/test_bitset2_02.cpp new file mode 100644 index 00000000..9c8de9c8 --- /dev/null +++ b/ThirdParty/bitset2/tests/test_bitset2_02.cpp @@ -0,0 +1,49 @@ + +#include <iostream> +#include "bitset2.hpp" + + +int main() +{ + using namespace Bitset2; + + using ULLONG= unsigned long long; + + constexpr + std::array<ULLONG,1> a01{{1ull}}; + + constexpr + std::array<ULLONG,0> a02{}; + + constexpr auto a_app01= detail::array_funcs<1,ULLONG>().prepend( 2ull, a01 ); + constexpr auto a_app02= detail::array_funcs<0,ULLONG>().prepend( 3ull, a02 ); + std::cout << a_app01[0] << "\t" << a_app01[1] << "\n"; + std::cout << a_app02[0] << "\n"; + + //constexpr + auto aop0= detail::array_ops<65,ULLONG>( 0 ); + //constexpr + auto aop65= detail::array_ops<65,ULLONG>( 65 ); + //constexpr + auto slp65= Bitset2::bitset2<64>{ aop65.m_shft_left_pattern }; + + std::cout << "(aop0) m_n_shift_mod= " << aop0.m_n_shift_mod + << "\n m_shft_div= " << aop0.m_shft_div + << "\n m_shft_mod= " << aop0.m_shft_mod + << "\n m_shft_leftright_shift= " << aop0.m_shft_leftright_shift + << "\n m_shft_left_pattern= " << aop0.m_shft_left_pattern + << "\n m_shft_right_pattern= " << aop0.m_shft_right_pattern + << "\n n_words= " << aop0.n_words + << "\n n_array= " << aop0.n_array + << "\n"; + std::cout << "(aop65) m_n_shift_mod= " << aop65.m_n_shift_mod + << "\n m_shft_div= " << aop65.m_shft_div + << "\n m_shft_mod= " << aop65.m_shft_mod + << "\n m_shft_leftright_shift= " << aop65.m_shft_leftright_shift + << "\n m_shft_left_pattern= " << aop65.m_shft_left_pattern + << "\n = " << slp65 + << "\n m_shft_right_pattern= " << aop65.m_shft_right_pattern + << "\n n_words= " << aop65.n_words + << "\n n_array= " << aop65.n_array + << "\n"; +} diff --git a/ThirdParty/bitset2/tests/test_nonconst_constexpr01.cpp b/ThirdParty/bitset2/tests/test_nonconst_constexpr01.cpp new file mode 100644 index 00000000..03a2aa1b --- /dev/null +++ b/ThirdParty/bitset2/tests/test_nonconst_constexpr01.cpp @@ -0,0 +1,172 @@ +// BITSET2 +// +// Copyright Claas Bontus +// +// Use, modification and distribution is subject to the +// Boost Software License, Version 1.0. (See accompanying +// file LICENSE.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// +// Project home: https://github.com/ClaasBontus/bitset2 +// + + +#include "../bitset2.hpp" +#include <iostream> +#include <array> + + +template<size_t N,class T> +constexpr +Bitset2::bitset2<N,T> +ce_op( Bitset2::bitset2<N,T> const &bs, size_t n, size_t op_t ) +{ + auto ret_val= bs; + for( size_t c= 0; c < n; c++ ) + { + switch( op_t ) + { + case 1: ++ret_val; break; + case 2: ret_val++; break; + case 3: --ret_val; break; + case 4: ret_val--; break; + } + } + return ret_val; +} // ce_op + + +template<size_t N,class T> +constexpr +Bitset2::bitset2<N,T> +ce_opequal( Bitset2::bitset2<N,T> const &bs1, + Bitset2::bitset2<N,T> const &bs2, + size_t op_t ) +{ + auto ret_val= bs1; + + switch( op_t ) + { + case 1: ret_val += bs2; break; + case 2: ret_val |= bs2; break; + case 3: ret_val &= bs2; break; + case 4: ret_val ^= bs2; break; + case 5: ret_val.difference( bs2 ); break; + } + return ret_val; +} // ce_opequal + + +template<size_t N,class T> +constexpr +Bitset2::bitset2<N,T> +ce_shftequal( Bitset2::bitset2<N,T> const &bs1, + size_t shft, + size_t op_t ) +{ + auto ret_val= bs1; + + switch( op_t ) + { + case 1: ret_val <<= shft; break; + case 2: ret_val >>= shft; break; + case 3: ret_val.rotate_left( shft ); break; + case 4: ret_val.rotate_right( shft ); break; + } + return ret_val; +} // ce_shftequal + + +template<size_t N,class T> +constexpr +Bitset2::bitset2<N,T> +ce_sme_fncs( Bitset2::bitset2<N,T> const &bs1 ) +{ + auto ret_val= bs1; + Bitset2::bitset2<N,T> b2; + b2.set(); + b2.set( 12, false ); + b2.test_set( 15, false ); + + ret_val.reverse(); + ret_val.complement2(); + ret_val ^= b2; + + ret_val.flip(); + ret_val.flip( 42 ); + ret_val.flip(); + + return ret_val; +} // ce_sme_fncs + + +int main() +{ + using ULLONG= unsigned long long; + using namespace Bitset2; + + constexpr std::array<ULLONG,2> s_arr_01a{{ 0xFFFFFFFFFFFFFFFFull, 1ull }}; + constexpr std::array<ULLONG,2> s_arr_01b{{ 5ull, 0ull }}; + constexpr std::array<ULLONG,2> bit12{{ 1ull << 12, 0ull }}; + constexpr std::array<ULLONG,2> bit15{{ 1ull << 15, 0ull }}; + constexpr std::array<ULLONG,2> bit42{{ 1ull << 42, 0ull }}; + constexpr bitset2<129> zero; + constexpr bitset2<129> all_set= ~zero; + constexpr bitset2<129> sme_set1= + all_set ^ bitset2<129>{ bit12 } ^ bitset2<129>{ bit15 }; + constexpr bitset2<129> b_from_s_arr01a{ s_arr_01a }; + constexpr bitset2<129> b_from_s_arr01b{ s_arr_01b }; + constexpr auto minus_s_arr_01b= complement2( b_from_s_arr01b ); + constexpr auto add_01a_b= b_from_s_arr01a + b_from_s_arr01b; + constexpr auto sub_01a_b= b_from_s_arr01a + minus_s_arr_01b; + constexpr auto inc_01a_5= ce_op( b_from_s_arr01a, 5, 1 ); + constexpr auto inc_01b_5= ce_op( b_from_s_arr01a, 5, 2 ); + constexpr auto dec_01c_5= ce_op( b_from_s_arr01a, 5, 3 ); + constexpr auto dec_01d_5= ce_op( b_from_s_arr01a, 5, 4 ); + + constexpr auto or_01a_b= b_from_s_arr01a | b_from_s_arr01b; + constexpr auto and_01a_b= b_from_s_arr01a & b_from_s_arr01b; + constexpr auto xor_01a_b= b_from_s_arr01a ^ b_from_s_arr01b; + constexpr auto sdi_01a_b= difference( b_from_s_arr01a, b_from_s_arr01b ); + constexpr auto shl4_01a= b_from_s_arr01a << 4; + constexpr auto shr4_01a= b_from_s_arr01a >> 4; + constexpr auto rol4_01a= rotate_left( b_from_s_arr01a, 4 ); + constexpr auto ror4_01a= rotate_right( b_from_s_arr01a, 4 ); + + constexpr auto rev_01a= reverse( b_from_s_arr01a ); + constexpr auto cpl2_01a= complement2( rev_01a ); + constexpr auto xor12_01a= cpl2_01a ^ sme_set1; + constexpr auto xor42_01a= xor12_01a ^ bitset2<129>{ bit42 }; + + constexpr auto pe1= ce_opequal( b_from_s_arr01a, b_from_s_arr01b, 1 ); + constexpr auto oe1= ce_opequal( b_from_s_arr01a, b_from_s_arr01b, 2 ); + constexpr auto ae1= ce_opequal( b_from_s_arr01a, b_from_s_arr01b, 3 ); + constexpr auto xe1= ce_opequal( b_from_s_arr01a, b_from_s_arr01b, 4 ); + constexpr auto de1= ce_opequal( b_from_s_arr01a, b_from_s_arr01b, 5 ); + + constexpr auto sl4_1= ce_shftequal( b_from_s_arr01a, 4, 1 ); + constexpr auto sr4_1= ce_shftequal( b_from_s_arr01a, 4, 2 ); + constexpr auto rl4_1= ce_shftequal( b_from_s_arr01a, 4, 3 ); + constexpr auto rr4_1= ce_shftequal( b_from_s_arr01a, 4, 4 ); + constexpr auto smf_a= ce_sme_fncs( b_from_s_arr01a ); + + static_assert( add_01a_b == inc_01a_5, "" ); + static_assert( add_01a_b == inc_01b_5, "" ); + static_assert( sub_01a_b == dec_01c_5, "" ); + static_assert( sub_01a_b == dec_01d_5, "" ); + static_assert( add_01a_b == pe1, "" ); + static_assert( or_01a_b == oe1, "" ); + static_assert( and_01a_b == ae1, "" ); + static_assert( xor_01a_b == xe1, "" ); + static_assert( sdi_01a_b == de1, "" ); + static_assert( shl4_01a == sl4_1, "" ); + static_assert( shr4_01a == sr4_1, "" ); + static_assert( rol4_01a == rl4_1, "" ); + static_assert( ror4_01a == rr4_1, "" ); + static_assert( xor42_01a == smf_a, "" ); + + std::cout << inc_01a_5 << '\n' << inc_01b_5.to_hex_string() << "\n"; + std::cout << sub_01a_b << '\n' << dec_01c_5.to_hex_string() << "\n"; + + return 0; +} // main diff --git a/ThirdParty/bitset2/tests/test_ullong2array.cpp b/ThirdParty/bitset2/tests/test_ullong2array.cpp new file mode 100644 index 00000000..7649f6ab --- /dev/null +++ b/ThirdParty/bitset2/tests/test_ullong2array.cpp @@ -0,0 +1,127 @@ +// BITSET2 +// +// Copyright Claas Bontus +// +// Use, modification and distribution is subject to the +// Boost Software License, Version 1.0. (See accompanying +// file LICENSE.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// +// Project home: https://github.com/ClaasBontus/bitset2 +// + + +#include "ullong2array.hpp" +#include "array2u_long_t.hpp" +#include <iostream> +#include <cstdint> +#include <cassert> + + +int main() +{ + using ULLONG= unsigned long long; + + auto const all_set= ~ULLONG(0); + + using namespace Bitset2::detail; + + using a2l_65ll= Bitset2::detail::array2u_long_t<65,ULLONG,ULLONG>; + + auto const a1= ullong2array<18,uint32_t>()( all_set ); + std::array<uint32_t,1> const expt1{{ uint32_t((1ull << 18) - 1) }}; + size_t ct= 0; + for( auto v: a1 ) + { + std::cout << v << ", "; + assert( v == expt1[ct] ); ct++; + } + std::cout << "\n"; + assert( ct == 1 ); + + + auto const a2= ullong2array<34,uint32_t>()( all_set ); + std::array<uint32_t,2> const + expt2{{ uint32_t(~uint32_t(0)), uint32_t((1ull << 2) - 1) }}; + ct= 0; + for( auto v: a2 ) + { + std::cout << v << ", "; + assert( v == expt2[ct] ); ct++; + } + std::cout << "\n"; + assert( ct == 2 ); + + + auto const a3= ullong2array<18,uint16_t>()( all_set ); + std::array<uint32_t,2> const + expt3{{ uint16_t(~uint16_t(0)), uint16_t((1ull << 2) - 1) }}; + ct= 0; + for( auto v: a3 ) + { + std::cout << v << ", "; + assert( v == expt3[ct] ); ct++; + } + std::cout << "\n"; + assert( ct == 2 ); + + + auto const a4= ullong2array<18,uint8_t>()( all_set ); + std::array<uint8_t,3> const + expt4{{uint8_t(~uint8_t(0)),uint8_t(~uint8_t(0)),uint8_t((1ull << 2) - 1)}}; + ct= 0; + for( auto v: a4 ) + { + std::cout << int(v) << ", "; + assert( v == expt4[ct] ); ct++; + } + std::cout << "\n"; + assert( ct == 3 ); + + + auto const a5= ullong2array<18,uint64_t>()( all_set ); + std::array<uint64_t,1> const expt5{{ uint64_t((1ull << 18) - 1) }}; + ct= 0; + for( auto v: a5 ) + { + std::cout << v << ", "; + assert( v == expt5[ct] ); ct++; + } + std::cout << "\n"; + assert( ct == 1 ); + + + auto const a6= ullong2array<34,uint64_t>()( all_set ); + std::array<uint64_t,1> const expt6{{ uint64_t((1ull << 34) - 1) }}; + ct= 0; + for( auto v: a6 ) + { + std::cout << v << ", "; + assert( v == expt6[ct] ); ct++; + } + std::cout << "\n"; + assert( ct == 1 ); + + + auto const a7= ullong2array<66,uint64_t>()( all_set ); + std::array<uint64_t,2> const + expt7{{ uint64_t(~uint64_t(0)), uint64_t(0) }}; + ct= 0; + for( auto v: a7 ) + { + std::cout << v << ", "; + assert( v == expt7[ct] ); ct++; + } + std::cout << "\n"; + assert( ct == 2 ); + + + a2l_65ll::array_t arr1{{ all_set, 0ull }}; + + std::cout << '\n' << a2l_65ll::i_pttrn << '\n'; + std::cout << a2l_65ll::h_pttrn << '\n'; + std::cout << a2l_65ll::allset << '\n'; + std::cout << a2l_65ll::n_array << '\n'; + std::cout << a2l_65ll::use_vals << '\n'; + std::cout << a2l_65ll().check_overflow( arr1 ) << '\n'; +} diff --git a/ThirdParty/bitset2/tests/tests01.cpp b/ThirdParty/bitset2/tests/tests01.cpp new file mode 100644 index 00000000..040e578f --- /dev/null +++ b/ThirdParty/bitset2/tests/tests01.cpp @@ -0,0 +1,903 @@ +// BITSET2 +// +// Copyright Claas Bontus +// +// Use, modification and distribution is subject to the +// Boost Software License, Version 1.0. (See accompanying +// file LICENSE.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// +// Project home: https://github.com/ClaasBontus/bitset2 +// + + +#include "../bitset2.hpp" +#include "gen_randoms.hpp" +#include <bitset> +#include <cassert> +#include <cstdint> +#include <iostream> + +#define TESTMANY(F) \ + F <7 >(); \ + F <8 >(); \ + F <9 >(); \ + F <63 >(); \ + F <64 >(); \ + F <65 >(); \ + F <95 >(); \ + F <96 >(); \ + F <97 >(); \ + F <127>(); \ + F <128>(); \ + F <129>(); \ + F <255>(); \ + F <256>(); \ + F <257>(); + +#define TESTMANY2(F,T,S) \ + F <7, T>(S); \ + F <8, T>(S); \ + F <9, T>(S); \ + F <63, T>(S); \ + F <64, T>(S); \ + F <65, T>(S); \ + F <95, T>(S); \ + F <96, T>(S); \ + F <97, T>(S); \ + F <127,T>(S); \ + F <128,T>(S); \ + F <129,T>(S); \ + F <255,T>(S); \ + F <256,T>(S); \ + F <257,T>(S); + + +#define TESTMNY(F) \ + TESTMANY2(F,uint8_t, "uint8_t" ) \ + TESTMANY2(F,uint16_t,"uint16_t") \ + TESTMANY2(F,uint32_t,"uint32_t") \ + TESTMANY2(F,unsigned long long,"U_L_LONG") + + +template<size_t N,class T=unsigned long long> +using t1= Bitset2::bitset2<N,T>; + +template<size_t N> +using t1a= Bitset2::bitset2<N>; + +template<size_t N> +using t2= std::bitset<N>; + + +constexpr size_t n_loops= 100000; + +constexpr bool verbose= false; + + +template<size_t N,class T> +struct dummy_add +{ + enum : size_t + { ull_bits= sizeof(T) * CHAR_BIT + , div_val= N / ull_bits + , mod_val= N % ull_bits + , n_ull= ( mod_val != 0 ) ? (div_val+1) : div_val + , n_array= ( N == 0 ) ? 1 : n_ull + }; + // + enum : T + { all_one= T(~T(0)) + , hgh_pattern= (N==0) ? T(0) + : (mod_val==0) ? T(all_one) + : T(all_one >> (ull_bits-mod_val)) + }; + // + using array_t= std::array<T,n_array>; + // + array_t + add( array_t const &a1, array_t const &a2 ) const + { + array_t ret_val; + T crry= T(0); + + for( size_t c= 0; c < n_ull; ++c ) + { + T const v= T( a1[c] + a2[c] + crry ); + if( v < a1[c] || v < a2[c] || + ( a1[c] == all_one && a2[c] == all_one ) ) crry= T(1); + else crry= T(0); + ret_val[c]= v; + } + if( n_ull > 0 ) ret_val[n_ull-1] &= hgh_pattern; + + return ret_val; + } // add + // + // Returns false if a1 != a2 + bool + compare( array_t const &a1, array_t const &a2 ) + { + for( size_t c= 0; c < n_array; ++c ) + { + if( a1[c] != a2[c] ) return false; + } + return true; + } +}; // struct dummy_add + + +template<size_t N,class T> +t1<N,T> +dummy_reverse( t1<N,T> const & bs ) +{ + t1<N,T> ret_val; + for( size_t c= 0; c < N; ++c ) ret_val[c]= bs[N-c-1]; + + return ret_val; +} + + + +template<size_t N,class T> +void +test_any_all_none( char const * type_str ) +{ + std::cout << "Entering test_any_all_none N= " << N << " type= " << type_str << "\n"; + + t1<N,T> const empty1; + t2<N> const empty2; + auto const full1= ~empty1; + auto const full2= ~empty2; + + auto const empty1a= t1<N,T>( empty2 ); + auto const empty2a= t2<N>( empty1 ); + auto const full1a= t1<N,T>( full2 ); + auto const full2a= t2<N>( full1 ); + + assert( empty1.none() && !empty1.all() && !empty1.any() ); + assert( empty1a.none() && !empty1a.all() && !empty1a.any() ); + assert( empty2a.none() && !empty2a.all() && !empty2a.any() ); + assert( !full1.none() && full1.all() && full1.any() ); + assert( !full1a.none() && full1a.all() && full1a.any() ); + assert( !full2a.none() && full2a.all() && full2a.any() ); + + + constexpr t1<N,T> ce_empty1; + constexpr auto ce_full1= ~ce_empty1; + static_assert( ce_empty1.none() && !ce_empty1.all() && !ce_empty1.any(), "" ); + static_assert( !ce_full1.none() && ce_full1.all() && ce_full1.any(), "" ); + + + gen_random_bitset2<N,T> gen_rand; + for( size_t c= 0; c < n_loops; ++c ) + { + auto const bs1= gen_rand(); + auto const bs2= t2<N>( bs1 ); + auto const bs1a= t1<N,T>( bs2 ); + + if( verbose ) std::cout << bs1.to_hex_string() << "\t" << c << "\n"; + + assert( bs1 == bs1a ); + assert( bs1.none() == bs2.none() ); + assert( bs1.all() == bs2.all() ); + assert( bs1.any() == bs2.any() ); + } // for c +} // test_any_all_none + + + + +template<size_t N,class T> +void +test_set_count_size( char const * type_str ) +{ + std::cout << "Entering test_set_count_size N= " << N << " type= " << type_str << "\n"; + + t1<N,T> const empty1; + constexpr t1<N,T> ce_empty1; + constexpr t1<N,T> ce_full1= ~ce_empty1; + assert( empty1.size() == N ); + static_assert( ce_empty1.size() == N, "" ); + static_assert( ce_full1.count() == N, "" ); + static_assert( !ce_empty1.test( N - 3 ), "" ); + static_assert( ce_full1.test( N - 2 ), "" ); + + gen_random_bitset2<N,T> gen_rand; + for( size_t c= 0; c < n_loops; ++c ) + { + auto const bs1= gen_rand(); + auto const cnt1= bs1.count(); + size_t n_set1= 0, n_set2= 0; + for( size_t b_c= 0; b_c < N; ++b_c ) + { + if( bs1.test( b_c ) ) ++n_set1; + if( bs1[b_c] ) ++n_set2; + } + + if( verbose ) std::cout << bs1.to_hex_string() << "\t" << n_set1 + << "\t" << c << "\t" << bs1 << "\n"; + + auto bs2= bs1; + bs2.flip(); + auto const cnt2= bs2.count(); + + assert( n_set1 == cnt1 ); + assert( n_set1 == n_set2 ); + assert( cnt2 == N - cnt1 ); + } // for c +} // test_set_count_size + + + + +template<size_t N,class T> +void +test_set( char const * type_str ) +{ + std::cout << "Entering test_set N= " << N << " type= " << type_str << "\n"; + + gen_random_bitset2<N,T> gen_rand; + for( size_t c= 0; c < n_loops; ++c ) + { + auto bs1= gen_rand(); + auto bs2= bs1; + auto bs3= t2<N>( bs1 ); + bool flag= false; + for( size_t b= 0; b < N; ++ b ) + { + bool const bt1= bs1[b]; + bs1.set( b, flag ); + auto const bt2= bs2.test_set( b, flag); + assert( bt1 == bt2 ); + bs3.set( b, flag ); + + flag= !flag; + } + assert( bs1 == bs2 ); + assert( bs1 == (t1<N,T>( bs3 )) ); + } // for c +} // test_set + + + + +template<size_t N,class T> +void +test_rotate( char const * type_str ) +{ + std::cout << "Entering test_rotate N= " << N << " type= " << type_str << "\n"; + + constexpr std::array<T,2> ce_arr1{{ T(2), T(5) }}; + constexpr std::array<T,2> ce_arr2{{ T(4), T(10) }}; + constexpr t1<74,T> ce_bs1( ce_arr1 ); + constexpr t1<74,T> ce_bs1_r= Bitset2::rotate_left( ce_bs1, 1 ); + constexpr t1<74,T> ce_bs2( ce_arr2 ); + static_assert( ce_bs1_r == ce_bs2, "" ); + + gen_random_bitset2<N,T> gen_rand; + for( size_t c= 0; c < n_loops; ++c ) + { + auto const bs1= gen_rand(); + auto const cnt1= bs1.count(); + + for( size_t b_c= 0; b_c < 2 * N; ++b_c ) + { + auto const b_c_mod= b_c % N; + auto const bs2_r= Bitset2::rotate_right( bs1, b_c ); + auto const bs2_l= Bitset2::rotate_left( bs1, b_c ); + auto const bs2a= Bitset2::rotate_left( bs2_r, b_c ); + auto const bs2b= Bitset2::rotate_right( bs2_l, b_c ); + auto const bs2_r2= ( bs1 >> b_c_mod ) | ( bs1 << (N-b_c_mod) ); + auto const bs2_l2= ( bs1 << b_c_mod ) | ( bs1 >> (N-b_c_mod) ); + + auto bc1_c1= bs1; + auto bc1_c2= bs1; + bc1_c1.rotate_left( b_c ); + bc1_c2.rotate_right( b_c ); + + if( verbose ) + std::cout << bs1 << "\t" + << b_c << "\t" + << bs2_l << "\t" + << bs2_r << "\n"; + assert( cnt1 == bs2_r.count() ); + assert( cnt1 == bs2_l.count() ); + assert( bs2a == bs1 ); + assert( bs2b == bs1 ); + assert( bs2_r2 == bs2_r ); + assert( bs2_l2 == bs2_l ); + assert( bc1_c1 == bs2_l ); + assert( bc1_c2 == bs2_r ); + } + } // for c +} // test_rotate + + + + +template<size_t N,class T> +void +test_shift( char const * type_str ) +{ + std::cout << "Entering test_shift N= " << N << " type= " << type_str << "\n"; + + gen_random_bitset2<N,T> gen_rand; + t1<N,T> const empty1; + + constexpr size_t n_bts_m= sizeof(T) * CHAR_BIT - 1; + constexpr std::array<T,2> ce_arr1{{ T(2), T(5) }}; + constexpr std::array<T,2> ce_arr2{{ T(4), T(10) }}; + constexpr std::array<T,2> ce_arr3{{ T(1) + T(T(1) << n_bts_m), T(2) }}; + constexpr t1<74,T> ce_bs1( ce_arr1 ); + constexpr t1<74,T> ce_bs1_s1= ce_bs1 << 1; + constexpr t1<74,T> ce_bs1_s2= ce_bs1 >> 1; + constexpr t1<74,T> ce_bs2( ce_arr2 ); + constexpr t1<74,T> ce_bs3( ce_arr3 ); + static_assert( ce_bs1_s1 == ce_bs2, "" ); + static_assert( ce_bs1_s2 == ce_bs3, "" ); + + for( size_t c= 0; c < n_loops; ++c ) + { + auto const bs1= gen_rand(); + + for( size_t b_c= 0; b_c <= N + 5; ++b_c ) + { + auto const bs1_l= bs1 << b_c; + auto const bs1_r= bs1 >> b_c; + auto bs1_c1= bs1; + auto bs1_c2= bs1; + bs1_c1 <<= b_c; + bs1_c2 >>= b_c; + if( verbose ) + std::cout << bs1 << "\t" + << bs1_l << "\t" + << bs1_r << "\n"; + if( b_c < N ) + { + t2<N> const bs2{ bs1 }; + auto const bs2_l= bs2 << b_c; + auto const bs2_r= bs2 >> b_c; + assert( bs2_l == t2<N>( bs1_l ) ); + assert( bs2_r == t2<N>( bs1_r ) ); + assert( bs1_c1 == bs1_l ); + assert( bs1_c2 == bs1_r ); + } + else + { + assert( bs1_l == empty1 ); + assert( bs1_r == empty1 ); + assert( bs1_c1 == empty1 ); + assert( bs1_c2 == empty1 ); + } + } // for b_c + } // for c +} // test_shift + + + + +template<size_t N,class T> +void +test_add( const char * type_str ) +{ + std::cout << "Entering test_add N= " << N << " type= " << type_str << "\n"; + + gen_random_bitset2<N,T> gen_rand; + dummy_add<N,T> adder; + t1<N,T> const zero; + t1<N,T> const one{{ T(1) }}; + t1<N,T> const all= t1<N,T>().set(); + + auto const all_twice= all + all; + auto all_twice2= all; + all_twice2 += all; + auto a_m1= all; + a_m1--; + auto a_m2= a_m1; + a_m2--; + auto all_twice_m1= all + a_m1; + assert( all_twice == a_m1 ); + assert( all_twice2 == a_m1 ); + assert( all_twice_m1 == a_m2 ); + + constexpr t1<N,T> ce_one{{ T(1) }}; + constexpr t1<N,T> ce_empty; + constexpr t1<N,T> ce_all= ~ce_empty; + constexpr t1<N,T> ce_all_but_one= ~ce_one; + constexpr auto ce_all_twice= ce_all + ce_all; + static_assert( ce_all_twice == ce_all_but_one, "" ); + + for( size_t c= 0; c < n_loops; ++c ) + { + auto const bs1= gen_rand(); + auto const bs2= gen_rand(); + auto bs3= bs1; + auto bs4= bs1; + auto bs5= bs1; + ++bs3; --bs4; + bs5 += bs2; + + auto const add1= bs1 + bs2; + auto const add2= adder.add( bs1.data(), bs2.data() ); + auto const add3= adder.add( bs1.data(), one.data() ); + auto const add4= adder.add( bs1.data(), all.data() ); + if( verbose ) + std::cout << " " << bs1 << "\n+ " << bs2 + << "\n= " << add1 + << "\n, " << t1<N,T>(add2) << "\n\n"; + auto const cmp1= adder.compare( add2, add1.data() ); + auto const cmp2= adder.compare( add3, bs3.data() ); + auto const cmp3= adder.compare( add4, bs4.data() ); + auto const cmp4= adder.compare( add2, bs5.data() ); + + auto const exp_zero= bs1 + (~bs1 + one); + + assert( cmp1 ); + assert( cmp2 ); + assert( cmp3 ); + assert( cmp4 ); + assert( exp_zero == zero ); + } // for c +} // test_add + + + + +template<size_t N,class T> +void +test_difference( char const * type_str ) +{ + std::cout << "Entering test_difference N= " << N << " type= " << type_str << "\n"; + + constexpr std::array<T,2> ce_arr1{{ T(3), T(5) }}; + constexpr std::array<T,2> ce_arr2{{ T(6), T(1) }}; + constexpr t1<74,T> ce_bs1( ce_arr1 ); + constexpr t1<74,T> ce_bs2( ce_arr2 ); + constexpr auto ce_diff1= Bitset2::difference( ce_bs1, ce_bs2 ); + constexpr auto ce_ref1= ce_bs1 & ~ce_bs2; + static_assert( ce_diff1 == ce_ref1, "" ); + + gen_random_bitset2<N,T> gen_rand; + + for( size_t c= 0; c < n_loops; ++c ) + { + auto const bs1= gen_rand(); + auto const bs2= gen_rand(); + auto bs3= bs1; + + auto const d1= Bitset2::difference( bs1, bs2 ); + auto const d2= bs1 & ~bs2; + bs3.difference( bs2 ); + + assert( d2 == d1 ); + assert( bs3 == d1 ); + } // for c +} // test_difference + + + + + +template<size_t N,class T> +void +test_not( char const * type_str ) +{ + std::cout << "Entering test_not N= " << N << " type= " << type_str << "\n"; + + gen_random_bitset2<N,T> gen_rand; + + for( size_t c= 0; c < n_loops; ++c ) + { + auto const bs1= gen_rand(); + auto const bs2= ~bs1; + for( size_t b_c= 0; b_c < N; ++b_c ) + { + if( verbose ) std::cout << "~" << bs1 << "\n=" << bs2 << "\n"; + assert( bs1[b_c] != bs2[b_c] ); + } + } // for c +} // test_not + + +template<size_t N,class T> +std::vector<size_t> +idx_lst( t1<N,T> const &bs ) +{ + std::vector<size_t> ret_val; + for( size_t c= 0; c < N; ++c ) + if( bs[c] ) ret_val.push_back( c ); + return ret_val; +} // idx_lst + + + +template<size_t N,class T> +void +test_find( char const * type_str ) +{ + std::cout << "Entering test_find N= " << N << " type= " << type_str << "\n"; + + constexpr t1<N,T> ce_bs1( 12ull ); + static_assert( ce_bs1.find_first() == 2, "" ); + static_assert( ce_bs1.find_next( 2 ) == 3, "" ); + static_assert( ce_bs1.find_next( 3 ) == t1<N,T>::npos, "" ); + + gen_random_bitset2<N,T> gen_rand; + + for( size_t c= 0; c < N; ++ c) + { + auto bs1= t1<N,T>(); + + assert( bs1.find_first() == (Bitset2::bitset2<N,T>::npos) ); + assert( bs1.find_next(0) == (Bitset2::bitset2<N,T>::npos) ); + + bs1[c]= true; + assert( bs1.find_first() == c ); + if( c > 0 ) + { + assert( bs1.find_next( c - 1 ) == c ); + + bs1[0]= true; + bs1[N-1]= true; + assert( bs1.find_first() == 0 ); + auto idx= bs1.find_next( c ); + if( c < N - 1 ) assert( idx == N - 1 ); + else assert( idx == (Bitset2::bitset2<N,T>::npos) ); + + for( size_t b= 0; b < c; ++b ) bs1[b]= true; + idx= bs1.find_next( c ); + if( c < N - 1 ) assert( idx == N - 1 ); + else assert( idx == (Bitset2::bitset2<N,T>::npos) ); + } + } // for c + + for( size_t c= 0; c < n_loops; ++c ) + { + auto const bs1= gen_rand(); + auto const lst= idx_lst( bs1 ); + if( lst.empty() ) assert( bs1.find_first() == (Bitset2::bitset2<N,T>::npos) ); + else + { + auto b_it= lst.begin(); + auto e_it= lst.end(); + auto idx= bs1.find_first(); + assert( idx == *(b_it++) ); + for( ; b_it != e_it; ++b_it ) + { + idx= bs1.find_next( idx ); + assert( idx == *b_it ); + } + idx= bs1.find_next( idx ); + assert( idx == (Bitset2::bitset2<N,T>::npos) ); + } + } // for c + +} // test_find + + + + +template<size_t N,class T> +void +test_bitwise_ops( char const * type_str ) +{ + std::cout << "Entering test_bitwise_ops N= " << N << " type= " << type_str << "\n"; + + constexpr std::array<T,2> ce_arr1{{ T(3), T(5) }}; + constexpr std::array<T,2> ce_arr2{{ T(5), T(1) }}; + constexpr std::array<T,2> ce_e_or{{ T(7), T(5) }}; + constexpr std::array<T,2> ce_e_and{{ T(1), T(1) }}; + constexpr std::array<T,2> ce_e_xor{{ T(6), T(4) }}; + constexpr t1<74,T> ce_bs1( ce_arr1 ); + constexpr t1<74,T> ce_bs2( ce_arr2 ); + constexpr t1<74,T> ce_bs_e_or( ce_e_or ); + constexpr t1<74,T> ce_bs_e_and( ce_e_and ); + constexpr t1<74,T> ce_bs_e_xor( ce_e_xor ); + constexpr auto ce_or= ce_bs1 | ce_bs2; + constexpr auto ce_and= ce_bs1 & ce_bs2; + constexpr auto ce_xor= ce_bs1 ^ ce_bs2; + static_assert( ce_or == ce_bs_e_or, "" ); + static_assert( ce_and == ce_bs_e_and, "" ); + static_assert( ce_xor == ce_bs_e_xor, "" ); + + gen_random_bitset2<N,T> gen_rand; + + for( size_t c= 0; c < n_loops; ++c ) + { + auto const bs1= gen_rand(); + auto const bs2= gen_rand(); + auto const b_or= bs1 | bs2; + auto const b_and= bs1 & bs2; + auto const b_xor= bs1 ^ bs2; + + auto const sbs1= t2<N>( bs1 ); + auto const sbs2= t2<N>( bs2 ); + auto const sb_or= sbs1 | sbs2; + auto const sb_and= sbs1 & sbs2; + auto const sb_xor= sbs1 ^ sbs2; + + if( verbose ) + std::cout << " " << bs1 << " op " << bs2 + << "\nop= |: " << b_or + << "\nop= &: " << b_and + << "\nop= ^: " << b_xor << "\n"; + + assert( sb_or == t2<N>( b_or ) ); + assert( sb_and == t2<N>( b_and ) ); + assert( sb_xor == t2<N>( b_xor ) ); + } // for c +} // test_bitwise_ops + + + + +template<size_t N,class T> +void +test_reverse( char const * type_str ) +{ + std::cout << "Entering test_reverse N= " << N << " type= " << type_str << "\n"; + + constexpr t1<N,T> ce_bs1( 3ull ); + constexpr auto ce_bs1_rev= Bitset2::reverse( ce_bs1 ); + constexpr auto ce_bs1_rot= Bitset2::rotate_right( ce_bs1, 2 ); + static_assert( ce_bs1_rev == ce_bs1_rot, "" ); + + gen_random_bitset2<N,T> gen_rand; + + for( size_t c= 0; c < n_loops; ++c ) + { + auto const bs1= gen_rand(); + auto bs2= bs1; + auto const bs3= dummy_reverse( bs1 ); + auto const bs4= Bitset2::reverse( bs1 ); + bs2.reverse(); + if( verbose ) + std::cout << " " << bs1 + << "\n2 " << bs2 + << "\n3 " << bs3 << '\n'; + assert( bs2 == bs3 ); + assert( bs4 == bs3 ); + bs2.reverse(); + assert( bs2 == bs1 ); + } // for c +} // test_reverse + + + +template<size_t N,class T> +void +test_convert( char const * type_str ) +{ + std::cout << "Entering test_convert N= " << N << " type= " << type_str << "\n"; + + constexpr t1<N,T> ce_bs1( 0ull ); + constexpr auto ce_bs2= ~ce_bs1; + constexpr auto ce_bs2a= ce_bs2 >> 1; + constexpr auto ce_bs2b= Bitset2::convert_to<N-1>( ce_bs2 ); + constexpr auto ce_bs2c= Bitset2::convert_to<N>( ce_bs2b ); + constexpr auto ce_bs2d= Bitset2::convert_to<N+1>( ce_bs2 ); + constexpr auto ce_bs2e= Bitset2::convert_to<N>( ce_bs2d ); + static_assert( ce_bs2c == ce_bs2a, "" ); + static_assert( ce_bs2e == ce_bs2, "" ); + + gen_random_bitset2<N,T> gen_rand; + + for( size_t c= 0; c < n_loops; ++c ) + { + auto const bs1= gen_rand(); + auto const bs2a= bs1 & ce_bs2a; + auto const bs2b= Bitset2::convert_to<N-1>( bs1 ); + auto const bs2c= Bitset2::convert_to<N>( bs2b ); + auto const bs2d= Bitset2::convert_to<N+1>( bs1 ); + auto const bs2e= Bitset2::convert_to<N>( bs2d ); + assert( bs2c == bs2a ); + assert( bs2e == bs1 ); + + auto const bs3a= Bitset2::convert_to<N,uint8_t>( bs1 ); + auto const bs3b= Bitset2::convert_to<N,T>( bs3a ); + auto const bs3c= Bitset2::convert_to<N,uint32_t>( bs3a ); + auto const bs4a= Bitset2::convert_to<N,uint64_t>( bs1 ); + auto const bs4b= Bitset2::convert_to<N,T>( bs4a ); + auto const bs5a= Bitset2::convert_to<N,uint64_t>( bs3a ); + auto const bs5b= Bitset2::convert_to<N,T>( bs5a ); + auto const bs5c= Bitset2::convert_to<N,uint32_t>( bs5a ); + assert( bs3b == bs1 ); + assert( bs4b == bs1 ); + assert( bs5b == bs1 ); + assert( bs3c == bs5c ); + + const Bitset2::bitset2<N,uint8_t> bs_1a{ bs1.data() }; + const Bitset2::bitset2<N,uint64_t> bs_1b{ bs1.data() }; + assert( bs_1a == bs3a ); + assert( bs_1b == bs4a ); + } // for c +} // test_convert + + + + +template<size_t N,class T> +void +test_compare( char const * type_str ) +{ + std::cout << "Entering test_compare N= " << N << " type= " << type_str << "\n"; + + constexpr t1<N,T> ce_bs1( 0ull ); + constexpr auto ce_bs2= ~ce_bs1; + constexpr auto ce_bs2a= ce_bs2 >> 1; + constexpr auto ce_bs2b= ce_bs2a; + static_assert( ce_bs2a < ce_bs2, "" ); + static_assert( ce_bs2b <= ce_bs2a, "" ); + static_assert( ce_bs2 > ce_bs2a, "" ); + static_assert( ce_bs2a >= ce_bs2b, "" ); + static_assert( ce_bs2a != ce_bs2, "" ); + + gen_random_bitset2<N,T> gen_rand; + + for( size_t c= 0; c < n_loops; ++c ) + { + auto const bs1= gen_rand(); + auto bs2= bs1; + auto const bs3= bs1; + --bs2; + if( bs1 != ce_bs1 ) + { + assert( bs2 < bs1 ); + assert( bs2 <= bs1 ); + assert( bs1 > bs2 ); + assert( bs1 >= bs1 ); + } + else + { + assert( bs1 == ce_bs1 ); + } + assert( bs3 <= bs1 ); + assert( bs3 >= bs1 ); + } // for c +} // test_compare + + + + +template<size_t N,class T> +void +test_complement2( char const * type_str ) +{ + std::cout << "Entering test_complement2 N= " << N << " type= " << type_str << "\n"; + + constexpr t1<N,T> zero( 0ull ); + constexpr auto allset= ~zero; + auto one= zero; + ++one; + + constexpr auto ce_bs1= Bitset2::complement2( zero ); + constexpr auto ce_bs2= Bitset2::complement2( allset ); + auto bs1= zero; + auto bs2= allset; + bs1.complement2(); + bs2.complement2(); + static_assert( ce_bs1 == zero, "" ); + assert( bs1 == zero ); + assert( bs2 == one ); + assert( ce_bs2 == one ); + + gen_random_bitset2<N,T> gen_rand; + + for( size_t c= 0; c < n_loops; ++c ) + { + auto const bs_1a= gen_rand(); + auto bs_1b= bs_1a; + auto const bs_1c= ~bs_1a + one; + auto const bs_2a= Bitset2::complement2( bs_1a ); + bs_1b.complement2(); + assert( bs_1a + bs_2a == zero ); + assert( bs_1a + bs_1b == zero ); + assert( bs_1b == bs_1c ); + } // for c +} // test_complement2 + + + +template<size_t N> +void +test_hash() +{ + std::cout << "Entering test_hash N= " << N << "\n"; + + gen_random_bitset2<N,uint8_t> gen_rand8; + gen_random_bitset2<N,uint16_t> gen_rand16; + gen_random_bitset2<N,uint32_t> gen_rand32; + gen_random_bitset2<N,uint64_t> gen_rand64; + + for( size_t c= 0; c < n_loops; ++c ) + { + auto const bs1_8= gen_rand8(); + auto const bs1a_8= t2<N>( bs1_8 ); + auto const bs2_8= t1<N,uint16_t>( bs1a_8 ); + auto const bs3_8= t1<N,uint32_t>( bs1a_8 ); + auto const bs4_8= t1<N,uint64_t>( bs1a_8 ); + + auto const hs1_8= std::hash<std::remove_cv_t<decltype(bs1_8)> >{}( bs1_8 ); + auto const hs2_8= std::hash<std::remove_cv_t<decltype(bs2_8)> >{}( bs2_8 ); + auto const hs3_8= std::hash<std::remove_cv_t<decltype(bs3_8)> >{}( bs3_8 ); + auto const hs4_8= std::hash<std::remove_cv_t<decltype(bs4_8)> >{}( bs4_8 ); + assert( hs1_8 == hs2_8 ); + assert( hs1_8 == hs3_8 ); + assert( hs1_8 == hs4_8 ); + + + auto const bs1_16= gen_rand16(); + auto const bs1a_16= t2<N>( bs1_16 ); + auto const bs2_16= t1<N,uint8_t>( bs1a_16 ); + auto const bs3_16= t1<N,uint32_t>( bs1a_16 ); + auto const bs4_16= t1<N,uint64_t>( bs1a_16 ); + + auto const hs1_16= std::hash<std::remove_cv_t<decltype(bs1_16)> >{}( bs1_16 ); + auto const hs2_16= std::hash<std::remove_cv_t<decltype(bs2_16)> >{}( bs2_16 ); + auto const hs3_16= std::hash<std::remove_cv_t<decltype(bs3_16)> >{}( bs3_16 ); + auto const hs4_16= std::hash<std::remove_cv_t<decltype(bs4_16)> >{}( bs4_16 ); + assert( hs1_16 == hs2_16 ); + assert( hs1_16 == hs3_16 ); + assert( hs1_16 == hs4_16 ); + + + auto const bs1_32= gen_rand32(); + auto const bs1a_32= t2<N>( bs1_32 ); + auto const bs2_32= t1<N,uint8_t>( bs1a_32 ); + auto const bs3_32= t1<N,uint16_t>( bs1a_32 ); + auto const bs4_32= t1<N,uint64_t>( bs1a_32 ); + + auto const hs1_32= std::hash<std::remove_cv_t<decltype(bs1_32)> >{}( bs1_32 ); + auto const hs2_32= std::hash<std::remove_cv_t<decltype(bs2_32)> >{}( bs2_32 ); + auto const hs3_32= std::hash<std::remove_cv_t<decltype(bs3_32)> >{}( bs3_32 ); + auto const hs4_32= std::hash<std::remove_cv_t<decltype(bs4_32)> >{}( bs4_32 ); + assert( hs1_32 == hs2_32 ); + assert( hs1_32 == hs3_32 ); + assert( hs1_32 == hs4_32 ); + + + auto const bs1_64= gen_rand64(); + auto const bs1a_64= t2<N>( bs1_64 ); + auto const bs2_64= t1<N,uint8_t>( bs1a_64 ); + auto const bs3_64= t1<N,uint16_t>( bs1a_64 ); + auto const bs4_64= t1<N,uint32_t>( bs1a_64 ); + + auto const hs1_64= std::hash<std::remove_cv_t<decltype(bs1_64)> >{}( bs1_64 ); + auto const hs2_64= std::hash<std::remove_cv_t<decltype(bs2_64)> >{}( bs2_64 ); + auto const hs3_64= std::hash<std::remove_cv_t<decltype(bs3_64)> >{}( bs3_64 ); + auto const hs4_64= std::hash<std::remove_cv_t<decltype(bs4_64)> >{}( bs4_64 ); + assert( hs1_64 == hs2_64 ); + assert( hs1_64 == hs3_64 ); + assert( hs1_64 == hs4_64 ); + } // for c +} // test_hash + + + +int +main() +{ + std::cout << "sizeof( bitset2<8> )= " << sizeof( t1a<8> ) << '\n'; + std::cout << "sizeof( bitset2<16> )= " << sizeof( t1a<16> ) << '\n'; + std::cout << "sizeof( bitset2<32> )= " << sizeof( t1a<32> ) << '\n'; + std::cout << "sizeof( bitset2<64> )= " << sizeof( t1a<64> ) << '\n'; + std::cout << "sizeof( bitset2<65> )= " << sizeof( t1a<65> ) << '\n'; + + TESTMNY(test_complement2) + TESTMNY(test_convert) + TESTMNY(test_add) + TESTMNY(test_compare) + TESTMNY(test_reverse) + TESTMNY(test_find) + TESTMNY(test_difference) + TESTMNY(test_any_all_none) + TESTMNY(test_set_count_size) + TESTMNY(test_set) + TESTMNY(test_not) + TESTMNY(test_bitwise_ops) + TESTMNY(test_shift) + TESTMNY(test_rotate) + + TESTMANY(test_hash) +} // main -- GitLab