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\_&ast;
+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 &params=
+                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