[ RFC Patch ] GSoC 2019 Conclusion

JeanHeyd Meneide phdofthehouse@gmail.com
Mon Sep 2 16:55:00 GMT 2019


Dear libstdc++,

     This is a revision of the bit_ds.patch. The older patch didn't
include any of the tests because a pervasive amount of them depended
on <span> and <ranges> from subrange and make_subrange.

     While I implemented <span> (
https://gcc.gnu.org/ml/gcc-patches/2019-08/msg02109.html ), it would
have been quite a bit much to also commit to implementing ranges,
especially since someone was already working on a cmcstl2 port for
libstdc++ and for GCC.

     So, I implemented a span and ranges polyfill that just sit in the
same directory as the tests with this patch, so the tests can run. I
will remove the span_polyfill and ranges_polyfill when <span> and
<ranges> start making their way into libstdc++ proper! This should
also give later reviewers confidence that the thing actually can be
used and does, indeed, work.

     (The contents of the patch as the same as the last one, modulo a
few tweaks to have the tests run.)

     Tested on x86_64 Linux.

Sincerely,
JeanHeyd Meneide
-------------- next part --------------
diff --git a/libstdc++-v3/doc/xml/manual/bit_extensions.xml b/libstdc++-v3/doc/xml/manual/bit_extensions.xml
new file mode 100644
index 00000000000..ef94c33880d
--- /dev/null
+++ b/libstdc++-v3/doc/xml/manual/bit_extensions.xml
@@ -0,0 +1,943 @@
+<chapter
+		xmlns="http://docbook.org/ns/docbook"
+		xmlns:xlink="http://www.w3.org/1999/xlink"
+		xmlns:xi="http://www.w3.org/2001/XInclude"
+		version="5.0"
+		xml:id="ext.bit"
+		xreflabel="Bit Extensions">
+	<?dbhtml filename="bit_extensions.html" ?>
+
+	<info>
+		<title>
+			Bit Extensions - Fundamental Bit Utilities, Ranges and Container Extensions ("itsy.bitsy")
+		</title>
+		<keywordset>
+			<keyword>ISO C++</keyword>
+			<keyword>library</keyword>
+			<keyword>extension</keyword>
+			<keyword>bit</keyword>
+			<keyword>bit_value</keyword>
+			<keyword>bit_reference</keyword>
+			<keyword>bit_iterator</keyword>
+			<keyword>bit_range</keyword>
+			<keyword>dynamic_bitset</keyword>
+			<keyword>bit_sequence</keyword>
+			<keyword>sequence</keyword>
+			<keyword>range</keyword>
+			<keyword>container</keyword>
+			<keyword>algorithm</keyword>
+		</keywordset>
+	</info>
+
+	<para>
+		A collection of utilities, algorithmic improvements, view adaptors and container adaptors for working with 1-bit objects represented by
+		<literal>0</literal>
+		(
+		<literal>false</literal>
+		) or
+		<literal>1</literal>
+		(
+		<literal>true</literal>
+		). Affectionately, this library is referred to as "itsy.bitsy".
+	</para>
+
+	<para>
+		All of these iterators and structures can be accessed VIA including the following extension header in your code:
+		<code>
+			<![CDATA[#include <ext/bit>]]>
+		</code>
+		.
+		As stated previously, nothing about this design, its Application Programming Interface (API) or its Application Binary Interface (ABI) are at all stable or to be depended upon. Performance metrics for various algorithms and internal optimizations are still being contributed to make this the best library version possible. It will be more stable if and when these various structures and proposed for inclusion in -- hopefully -- C++23 or C++26.
+	</para>
+
+	<section
+			xml:id="ext.bit.design"
+			xreflabel="Design">
+		<info>
+			<title>Design</title>
+		</info>
+		<para>
+			The bit extensions abstract the smallest unit of information in C++ -- a bit -- in easy-to-use, easy-to-optimize, and highly flexible iterators and structures. This comes as proposals for bit manipulation have stacked up in the Standard C++ mailing archives but need both exploration and implementation to further them. In particular, these extensions focus on candidates likely for future standardization, including
+			<link xlink:href="https://wg21.link/n2050">N2050 - Proposal to Add a Dynamically Sizeable Bitset to the Standard Library Technical Report</link>
+			and the newer
+			<link xlink:href="https://wg21.link/p0237r10">P0237 - fundamental bit manipulation utilities</link>
+			.
+		</para>
+		<para>
+			The implementations provided here are not verbatim with either N2050's or P0237's work. While closely followed, a number of different design decisions were taken with the advent of
+			<link xlink:href="http://eel.is/c++draft/ranges">C++20's new Range machinery</link>
+			. Other operations were either added or removed to promote better safety in the type (e.g., removing arithmetic operations from
+			<code>
+				<![CDATA[bit_pointer<Iterator>]]>
+			</code>
+			to prevent crashes and overflow when the reference type does not have a contiguous store) or added for ease of use and clarity of API (e.g.,
+			<code>C++</code>
+			). Most notably,
+			<code>bit_sequence</code>
+			(a more flexible
+			<code>dynamic_bitset</code>
+			)
+			is implemented as a container adaptor rather than a concrete type or a type which only takes a single
+			<code>value_type</code>
+			template parameter.
+		</para>
+		<para>
+				There are small, mostly private implementations of the functionality provided by these extensions already in libstdc++ in various forms: these abstractions will hopefully pave the way for them to not only be in the standard but also exhibit dependable performance characteristics without requiring more hand-crafted optimization to be applied to individual use cases and specific types.
+		</para>
+		<para>
+			All abstractions treat values as a sequence of bits, with 0 being the least significant bit and N-1 being the most significant bit. The most significant bit, N-1, is determined by the binary digits N in the value's object representation. This is picked out of a template class,
+			<code>
+				<![CDATA[binary_digits_v<Type>]]>
+			</code>
+			. This generally computes
+			<code>
+				<![CDATA[sizeof(Type) * CHAR_BIT]]>
+			</code>
+			as the number of bits. For signed types, it computes the previous value but with a
+			<code>- 1</code>
+			to exclude observing the sign bit (this is reliable because C++20 has formalized a twos-complement integer model).
+		</para>
+		<section
+				xml:id="ext.bit.design.layers"
+				xreflabel="Layers">
+			<title>Abstraction Layers</title>
+			<para>There are 4 layers of functionality. Each layer provides increasingly more functionality, and depends on the last.</para>
+			<section
+					xml:id="ext.bit.design.layers.utilities"
+					xreflabel="bit_utilities">
+				<title>Abstraction Layer 0: bit_utilities</title>
+				<para>
+					A collection of fundamental utilites for properly and correctly working with the bits of integral and enumeration types. Includes
+					<code>
+						<![CDATA[binary_digits<IntegralOrEnumerationType>]]>
+					</code>
+					helper type,
+					<code>
+						<![CDATA[bit_value]]>
+					</code>
+					type as a "strong typedef" for a single bit,
+					<code>
+						<![CDATA[bit_reference<ReferenceType, MaskType>]]>
+					</code>
+					which wraps a Reference and presents a single bit interface to it,
+					<code>
+						<![CDATA[bit_iterator<Iterator>]]>
+					</code>
+					for enumering the individual bits of the
+					<code>Iterator</code>
+					's
+					<code>value_type</code>
+					, and
+					<code>
+						<![CDATA[bit_pointer<Iterator>]]>
+					</code>
+					as the pointer analogue of a single bit reference. All indices and bit positions are communicated with the least significant bit starting at 0 before progressing upwards towards the most significant bit at 1.
+				</para>
+			</section>
+
+			<section
+					xml:id="ext.bit.design.layers.algorithms"
+					xreflabel="bit_algorithms">
+				<title>Abstraction Layer 1: bit algorithims</title>
+				<para>
+					A collection of function template overloads which employ the bit utilities defined from before to provide optimized implementations of certain standard algorithms, including
+					<literal>std::find</literal>
+					,
+					<literal>std::equal</literal>
+					,
+					<literal>std::copy(_n)</literal>
+					, and more. See the performance section below for more details on the various improvements made to various algorithms.
+				</para>
+			</section>
+			<section
+					xml:id="ext.bit.design.layers.bit_view"
+					xreflabel="bit_view">
+				<title>
+					Abstraction Layer 2:
+					<code>
+						<![CDATA[bit_view<Range, Bounds>]]>
+					</code>
+				</title>
+				<para>
+					A range adaptor which takes a range and provides an easy interface to iterate over its bits in very specific sections through use of its
+					<code>
+						Bounds
+					</code>
+					. Includes a
+					<code>
+						<![CDATA[bit_view<Range, Bounds>]]>
+					</code>
+					type for viewing the
+					<code>[begin(), end())</code>
+					values of a range as a sequence of bits,
+					<code>
+						<![CDATA[word_bounds<Range>]]>
+					</code>
+					bounds type,
+					<code>
+						<![CDATA[dynamic_bounds]]>
+					</code>
+					bounds type for bounds determined at run time, and
+					<code>
+						<![CDATA[static_bounds<BeginBit, EndBit>]]>
+					</code>
+					bounds type for bounds determined at compile-time. It can be used on single values or multiple values. An example:
+					<programlisting>
+						<![CDATA[
+					#include <ext/bit>
+					#include <string_view>
+					#include <iostream>
+					
+					int main (int argc, char*[] argv) 
+					{
+						for (int i = 0; i < argc; ++i) 
+							{
+								const char* arg = argv[i];
+								__gnu_cxx::bit_view<std::string_view> arg_bits(arg);
+								std::cout << ""the first ASCII letter of the arg is ";
+								if (bits[6]) {
+									std::cout << "uppercase" << std::endl;
+								}
+								else {
+									std::cout << "lowercase" << std::endl;
+								}
+							}
+
+						return 0;
+					}
+					]]>
+					</programlisting>
+				</para>
+				<para>
+					Note that
+					<code>
+						<![CDATA[bit_view<Range, Bounds>]]>
+					</code>
+					also includes
+					<code>begin()</code>
+					and
+					<code>end()</code>
+					methods, as well as a suite of methods for checking bits (
+					<code>.test()</code>
+					) and more:
+					<programlisting>
+						<![CDATA[
+					#include <ext/bit>
+					#include <span>
+					#include <cstddef>
+					#include <algorithm>
+
+					int main (int argc, char*[] argv) 
+					{
+						std::uint64_t value{ std::numeric_limits<std::uint64_t>::max() };
+						__gnu_cxx::bit_view<std::span<std::uint64_t>> value_bits(&value, &value + 1);
+						// returns 0
+						return std::count(value_bits.cbegin(), value_bits.cend(), false);
+					}
+					]]>
+					</programlisting>
+				</para>
+			</section>
+
+			<section
+					xml:id="ext.bit.design.layers.bit_sequence"
+					xreflabel="bit_sequence">
+				<title>
+					Abstraction Layer 3:
+					<code>
+						<![CDATA[bit_sequence<Container>]]>
+					</code>
+				</title>
+				<para>
+					A container adaptor which takes a container and adapts its
+					<code>value_type</code>
+					to be a sequence of bits. It maintains the per-bit position as an invariant of the class. It can be constructed from its underlying container, but also maintains an easy-to-use interface that is identical to other Sequence Containers in the standard.
+				</para>
+			</section>
+		</section>
+	</section>
+	<section
+			xml:id="ext.bit.using"
+			xreflabel="Using">
+		<title>Using the Library</title>
+		<para>
+			Each higher layer of this library builds on top of the lower layers. We will start at the top -- with wrapping, owning containers -- and progress steadily downward. The library is also a header-only, linker-hassle free library.
+		</para>
+		<section
+				xml:id="ext.bit.using.bit_sequence"
+				xreflabel="Bit.Sequence">
+			<title>Bit Sequence</title>
+			<para>
+				<code>
+					<![CDATA[__gnu_cxx::bit_sequence<Container>]]>
+				</code>
+				is an owning sequence container adaptor. It can be used like so:
+				<programlisting>
+					<![CDATA[
+#include <ext/bit>
+
+#include <cassert>
+
+int main () {
+	// construct with initializer list
+	__gnu_cxx::bit_sequence<std::vector<std::size_t>> bits{
+		false, true, true, false, false
+	};
+	// construct from iterators just like other containers
+	__gnu_cxx::bit_sequence<std::vector<std::size_t>> other_bits(
+		bits.cbegin(), bits.cend();
+	);
+
+	// can compare
+	assert(bits == other_bits);
+	assert(!(bits != other_bits));
+
+	// insertion
+	bits.push_back(false);
+	bits.insert(bits.begin() + 2, {true, true});
+	assert(bits.size() == 8);
+	assert(bits.count(true) == 4);
+
+	// erasure
+	bits.erase(bits.begin() + 1, bits.begin() + 3);
+	assert(bits.size() == 6);
+	assert(bits.popcount() == 2);
+
+	// comparison works exactly the same
+	assert(bits != other_bits);
+	assert(!(bits == other_bits));
+
+	return 0;
+}
+]]>
+				</programlisting>
+			</para>
+
+			<para>
+				There is a convenience alias --
+				<code>
+					<![CDATA[__gnu_cxx::dynamic_bitset<T, Allocator>]]>
+				</code>
+				, which defaults to some
+				<code>
+					<![CDATA[std::vector<T, Allocator>]]>
+				</code>
+				-alike storage. See the below section on Future Work for additional containers for the hope of what the default choice of container for this convenience alias should use:
+				<programlisting>
+					<![CDATA[
+#include <ext/bit>
+
+int main () {
+	__gnu_cxx::dynamic_bitset<std::size_t> bits{false, true, true, false, false};
+
+	/* bit work here! */
+
+	return 0;
+}
+]]>
+				</programlisting>
+			</para>
+			<para>
+				Additionally, one can move storage directly into the bit sequence by using the
+				<code>
+					<![CDATA[std::in_place]]>
+				</code>
+				constructors:
+				<programlisting>
+					<![CDATA[
+#include <ext/bit>
+
+#include <cstdint>
+#include <cassert>
+
+int main () {
+	std::vector<std::uint32_t> words{ 0xff00ff00, 0xff00ff00 };
+	__gnu_cxx::bit_sequence<std::vector<std::uint32_t>> bits(std::in_place, std::move(words));
+
+	const std::size_t bits_size = bits.size();
+	
+	// size of the container is 2 words
+	assert(bits_size == __gnu_cxx::binary_digits_v<std::uint32_t> * 2);
+	assert(bits_size == 64);
+
+	// assert 16-bit pattern
+	for (std::size_t index = 0; index < bits_size; ++index) {
+		if ((index % 16) < 8) {
+			assert(!bits[index]);
+		}
+		else {
+			assert(bits[index]);
+		}
+	}
+
+	return 0;
+}
+]]>
+				</programlisting>
+			</para>
+		</section>
+		<section
+				xml:id="ext.bit.using.bit_view"
+				xreflabel="Bit.View">
+			<title>Bit View</title>
+
+			<para>
+				The types at this layer sit below
+				<code>
+					<![CDATA[bit_sequence]]>
+				</code>
+				in terms of abstraction power.
+				<code>
+					<![CDATA[bit_view<Range, Bounds>]]>
+				</code>
+				is the type which views a set of bits and provides a potentially mutable view of those bits. It cannot
+				<code>insert</code>
+				<code>erase</code>
+				into the underlying range, but supports in-place modifications and mutability. For example, if the
+				<code>
+					<![CDATA[Range]]>
+				</code>
+				is a
+				<code>
+					<![CDATA[std::span<T>]]>
+				</code>
+				, then the type is mutable:
+				<programlisting>
+					<![CDATA[
+#include <ext/bit>
+
+#include <string>
+#include <span>
+#include <cassert>
+
+int main () {
+	std::string str = "Howdy!";
+	std::cout << str << std::endl;
+	// arguments get forwarded directly
+	// to underlying range constructor
+	__gnu_cxx::bit_view<std::span<char>> str_bits(str);
+
+	// iterators
+	auto bits_it = str_bits.begin();
+	assert(bits_it.position() == 0);
+	assert(*bits_it == __gnu_cxx::bit0);
+	++bits_it;
+	assert(bits_it.position() == 1);
+	assert(*bits_it == __gnu_cxx::bit0);
+	bits_it += 4;
+	assert(bits_it.position() == 5);
+	assert(*bits_it == __gnu_cxx::bit0);
+	// flip a single bit
+	// pointed to by bits_it
+	bits_it->flip();
+	assert(*bits_it == __gnu_cxx::bit1);
+
+	// we flipped the ASCII bit
+	// for a capital letter!
+	std::cout << str << std::endl;
+	assert(str == "howdy!");
+
+	return 0;
+}
+]]>
+				</programlisting>
+			</para>
+			<para>
+				But if the
+				<code>
+					<![CDATA[Range]]>
+				</code>
+				is something like a
+				<code>
+					<![CDATA[std::string_view]]>
+				</code>
+				or a
+				<code>
+					<![CDATA[std::span<const T>]]>
+				</code>
+				, whose iterators and interface is immutable,
+				<code>
+					<![CDATA[bit_view]]>
+				</code>
+				becomes immutable as well:
+				<programlisting>
+					<![CDATA[
+#include <ext/bit>
+
+#include <cassert>
+
+#include <span>
+#include <cstdint>
+
+int main() {
+	std::vector<std::uint16_t> storage{ 0, 0, 0 };
+	__gnu_cxx::bit_view<std::span<const std::uint16_t>> bits(storage);
+
+	assert(bits.size() == 48);
+
+	// the below will trigger a compiler error,
+	// thus preserving const-safety
+	(*bits.begin()) = true;
+	bits[16] = __gnu_cxx::bit1;
+	bits.begin()->flip();
+
+	// can use auto, just showing the actual type
+	for (__gnu_cxx::bit_reference<const std::uint16_t&> bit_ref : bits) {
+		bit_value value = bit_ref;
+		assert(value.value()); // returns the bool value
+		// cannot use mutable methods: 
+		// compiler will error below!
+		bit_ref.flip();
+		bit_ref.set();
+		bit_ref.reset();
+	}
+
+	return 0;
+}
+]]>
+				</programlisting>
+			</para>
+			<para>
+				For
+				<code>
+					<![CDATA[bit_view<Range, Bounds>]]>
+				</code>
+				, the optional second
+				<code>
+					<![CDATA[Bounds]]>
+				</code>
+				template parameter can be used to specify very specific extents:
+				<programlisting>
+					<![CDATA[
+#include <ext/bit>
+
+#include <string_view>
+#include <cassert>
+
+int main () {
+	std::array<std::uint32_t, 2> storage{
+		// 0xFBFF;
+		// (MSB) 0b‭1111101111111111‬ (LSB)
+		0x0000FBFF, 
+		0xFFFFFFFF 
+	};
+	using range_t = std::basic_string_view<std::uint32_t>;
+	using bounds_t = __gnu_cxx::bit_bounds<10, 22>;
+	__gnu_cxx::bit_view<range_t, bounds_t> view_specific_bits(
+		storage.data(), storage.size()
+	);
+
+	assert(view_specific_bits.size() == 12);
+	// 0th bit of biew is 10th bit,
+	// 10th bit of 0xFBFF is false
+	assert(view_specific_bits[0] == __gnu_cxx::bit0);
+
+	return 0;
+}
+]]>
+				</programlisting>
+			</para>
+			<para>
+				And, as previously stated, it can be used at compile-time and in constant-evaluated contexts:
+				<programlisting>
+					<![CDATA[
+#include <ext/bit>
+
+#include <string_view>
+#include <cassert>
+
+int main () {
+	static constexpr unsigned data[] = { 0b0001, 0b0010 };
+	static constexpr __gnu_cxx::bit_view<std::basic_string_view<unsigned>> data_bits(&data[0], 2);
+
+	static_assert(data_bits[0], "First bit is not true (expected: true)!");
+	static_assert(!data_bits.test(1), "Second bit is true  (expected: false)!");
+	static_assert(*(data_bits.begin() + __gnu_cxx::binary_digits_v<unsigned> + 1),
+	  "Second bit in second word is not true (expected: true)!");
+	static_assert(data_bits.size() == (sizeof(unsigned) * CHAR_BIT * 2),
+	  "The size of the bit view is not 2 x unsigned");
+	static_assert(data_bits.size() == (__gnu_cxx::binary_digits_v<unsigned> * 2),
+	  "The size of the bit view is not 2 x unsigned");
+	static_assert(!data_bits[3].value(), "The bit is true (expected: false)!");
+
+	return 0;
+}
+]]>
+				</programlisting>
+			</para>
+			<para>
+				All methods found on a
+				<code>
+					<![CDATA[bit_view]]>
+				</code>
+				also exist on all variants of
+				<code>
+					<![CDATA[bit_sequence]]>
+				</code>
+				.
+			</para>
+		</section>
+		<section
+				xml:id="ext.bit.using.bit_iterator"
+				xreflabel="Bit.Iterator">
+			<title>Bit Iterator</title>
+			<para>
+				<code>
+					<![CDATA[__gnu_cxx::bit_iterator<Iterator>]]>
+				</code>
+				is a class template. It is considered the "low level" portion of this library. It takes an iterator to increment when it iterates from
+				<code>
+					<![CDATA[[0, __gnu_cxx::binary_digits_v<underlying_value_type>)]]>
+				</code>
+				. Generally, what that means is that a
+				<code>
+					<![CDATA[std::uint32_t]]>
+				</code>
+				will iterate from 0 to 31 inclusive, an
+				<code>
+					<![CDATA[unsigned long long]]>
+				</code>
+				(depending on platform specifics) might go from 0 to 63 inclusive, and so on and so forth. This can be inspected with the
+				<code>
+					<![CDATA[.position()]]>
+				</code>
+				and
+				<code>
+					<![CDATA[.mask()]]>
+				</code>
+				properties:
+				<programlisting>
+					<![CDATA[
+#include <ext/bit>
+
+#include <random>
+#include <limits>
+#include <algorithm>
+#include <iostream>
+
+int main() {
+	using sequence = std::list<int>;
+	sequence seq{ 100, 0 };
+	std::random_device rd{};
+	std::default_random_engine rand_engine(rd());
+	std::uniform_int_distribution<int> rand_distribution(
+		std::numeric_limits<int>::max() - 32, std::numeric_limits<int>::max());
+	std::generate_n(seq.begin(), seq.size(), [&]() { return rand_distribution(rand_engine); });
+
+	__gnu_cxx::bit_iterator<typename sequence::const_iterator> first(seq.cbegin(), 0);
+	__gnu_cxx::bit_iterator<typename sequence::const_iterator> last(seq.cend(), 0);
+
+	if (auto it = std::find(first, last, __gnu_cxx::bit0); it != last) {
+		__gnu_cxx::bit_reference<typename sequence::const_reference> ref = *it;
+		std::cout << "Found a 0 bit at the " << std::distance(it, last) << " element in the "
+							<< seq.size() << ", at bit position" << ref.position() << "( mask: " << ref.mask()
+							<< " | applied to value: " << *it.base() << ")" << std::endl;
+	}
+
+	return 0;
+}
+				]]>
+				</programlisting>
+			</para>
+			<para>
+				It's
+				<code>
+					<![CDATA[value_type]]>
+				</code>
+				is a
+				<code>
+					<![CDATA[bit_value]]>
+				</code>
+				, and its reference type is a
+				<code>
+					<![CDATA[bit_reference<WordType, MaskType>]]>
+				</code>
+				.
+				<code>
+					<![CDATA[bit_reference]]>
+				</code>
+				keeps on the reference and the position/mask value.
+				<code>
+					<![CDATA[bit_value]]>
+				</code>
+				discards that is only represents a single bit. As seen from the above example, using the basic
+				<code>
+					<![CDATA[bit_iterator]]>
+				</code>
+				API is incredibly verbose: it is highly encouraged to use the top-level ranges API or similar when possible, unless attempting to create your own ranges and containers that iterate over bits.
+			</para>
+		</section>
+	</section>
+	<section>
+		<title>Performance</title>
+		<para>
+			The bit iterators here have had select optimizations applied to certain algorithms which can handle it. Most of these include the non-predicate versions of functions present in the C++ algorithms. The reason the versions taking a predicate cannot be optimized is because predicates only have the requirement that they successfully pinpoint an element or partition a range: at no point does the standard require that the comparisons cater to any particular value in the sequence of bits, or respond in a predicable way to what amounts to a 0 bit or a 1 bit. That makes it impossible to optimize, say
+			<code>find_if</code>
+			, because there is no reasoning that can be applied to the predicate. Calling
+			<code>unary_predicate(false)</code>
+			one time and
+			<code>unary_predicate(false)</code>
+			another time can yield 2 different results. It could be based on the time of day, the number of times the predicate is called, some internal state, etc.: no matter what the case is, the predicate-taking versions of these functions cannot be optimized. It can't even be optimized if we detect e.g.
+			<code>
+				<![CDATA[std::less<T>]]>
+			</code>
+			because someone can create a specialization of that standard predicate and do crazy things with it. This is an unfortunate but fundamental truth to the predicate-taking algorithms.
+		</para>
+		<para>
+			This does not mean there are no optimization opportunities at all. In the current version of itsy.bitsy, we currently optimize the following:
+			<orderedlist>
+				<listitem>
+					<para>
+						<code>std::equal</code>
+						, 3-iterator and 4-iterator version
+					</para>
+				</listitem>
+				<listitem>
+					<para>
+						<code>std::find</code>
+					</para>
+				</listitem>
+				<listitem>
+					<para>
+						<code>std::find_first_of</code>
+					</para>
+				</listitem>
+				<listitem>
+					<para>
+						<code>std::lexicographic_compare</code>
+					</para>
+				</listitem>
+				<listitem>
+					<para>
+						<code>std::copy</code>
+					</para>
+				</listitem>
+				<listitem>
+					<para>
+						<code>std::copy_n</code>
+					</para>
+				</listitem>
+				<listitem>
+					<para>
+						<code>std::fill</code>
+					</para>
+				</listitem>
+				<listitem>
+					<para>
+						<code>std::fill_n</code>
+					</para>
+				</listitem>
+				<listitem>
+					<para>
+						<code>std::count</code>
+					</para>
+				</listitem>
+				<listitem>
+					<para>
+						<code>std::is_sorted</code>
+					</para>
+				</listitem>
+				<listitem>
+					<para>
+						<code>std::is_sorted_until</code>
+					</para>
+				</listitem>
+			</orderedlist>
+		</para>
+		<para>
+			Here is some of the example performance from a recent build of GCC:
+			<programlisting>
+				<![CDATA[----------------------------------------------------------------------
+Benchmark                            Time             CPU   Iterations
+----------------------------------------------------------------------
+noop                             0.000 ns        0.000 ns   1000000000
+is_sorted_by_hand                 2807 ns         2762 ns       248889
+is_sorted_base                   50573 ns        50223 ns        11200
+is_sorted_vector_bool           252820 ns       256696 ns         2800
+is_sorted_bitset                202140 ns       199507 ns         3446
+is_sorted_itsy_bitsy               839 ns          837 ns       746667
+is_sorted_until_by_hand           2812 ns         2825 ns       248889
+is_sorted_until_base             51320 ns        51562 ns        10000
+is_sorted_until_vector_bool     255426 ns       256696 ns         2800
+is_sorted_until_bitset          198101 ns       194972 ns         3446
+is_sorted_until_itsy_bitsy         712 ns          715 ns       896000
+find_by_hand                      2694 ns         2727 ns       263529
+find_base                        23847 ns        24065 ns        29867
+find_vector_bool                 89738 ns        89979 ns         7467
+find_bitset                      96646 ns        96257 ns         7467
+find_itsy_bitsy                   2718 ns         2727 ns       263529
+fill_by_hand                       272 ns          273 ns      2635294
+fill_base                         2796 ns         2787 ns       263529
+fill_vector_bool                   271 ns          270 ns      2488889
+fill_bitset                     137941 ns       139509 ns         5600
+fill_bitset_smart                  257 ns          257 ns      2488889
+fill_itsy_bitsy                    263 ns          268 ns      2800000
+fill_itsy_bitsy_smart              257 ns          257 ns      2800000
+sized_fill_by_hand                 257 ns          255 ns      2635294
+sized_fill_base                   2580 ns         2623 ns       280000
+sized_fill_vector_bool          127094 ns       128348 ns         5600
+sized_fill_bitset               125951 ns       125552 ns         4978
+sized_fill_bitset_smart            251 ns          251 ns      2800000
+sized_fill_itsy_bitsy              260 ns          262 ns      2800000
+sized_fill_itsy_bitsy_smart        267 ns          268 ns      2800000
+equal_by_hand                     1030 ns         1046 ns       746667
+equal_memcmp                     0.328 ns        0.312 ns   1000000000
+equal_base                       0.318 ns        0.312 ns   1000000000
+equal_vector_bool               242570 ns       239955 ns         2800
+equal_vector_bool_operator      270586 ns       272770 ns         2635
+equal_bitset                     0.000 ns        0.000 ns   1000000000
+equal_bitset_operator            0.000 ns        0.000 ns   1000000000
+equal_itsy_bitsy                   685 ns          684 ns      1120000
+equal_itsy_bitsy_operator        0.321 ns        0.328 ns   1000000000
+count_by_hand                     5085 ns         5156 ns       100000
+count_base                       46455 ns        46038 ns        11200
+count_vector_bool                98858 ns        97656 ns         6400
+count_bitset                    114628 ns       114746 ns         6400
+count_bitset_smart               10441 ns        10498 ns        64000
+count_itsy_bitsy                  5020 ns         5082 ns       144516
+count_itsy_bitsy_smart            5083 ns         5022 ns       112000
+copy_by_hand                       258 ns          255 ns      2635294
+copy_base                         3239 ns         3223 ns       213333
+copy_vector_bool                195930 ns       196725 ns         3733
+copy_bitset                     147936 ns       150663 ns         4978
+copy_bitset_operator               255 ns          257 ns      2800000
+copy_itsy_bitsy                    261 ns          261 ns      2635294
+copy_itsy_bitsy_operator           264 ns          261 ns      2635294
+sized_copy_by_hand                 262 ns          261 ns      2635294
+sized_copy_base                   3237 ns         3223 ns       213333
+sized_copy_vector_bool          212132 ns       209961 ns         3200
+sized_copy_bitset               147954 ns       146484 ns         4480
+sized_copy_itsy_bitsy              261 ns          261 ns      2635294]]>
+			</programlisting>
+		</para>
+		<para>
+			The code for these benchmarks is maintained externally (the GCC codebase is currently not ready to take on a hard dependency on a better benchmarking library and its own benchmarking and performance utilities are sprawling, non-uniform and a bit lacking in places). It was generated with Google Benchmarks on a recent build of GCC. There is still work to be done to improve the
+			<code>
+				<![CDATA[std::equal(...)]]>
+			</code>
+			performance to be exactly equivalent to a
+			<code>
+				<![CDATA[std::memcmp(...)]]>
+			</code>
+			. This would require using something like
+			<code>if constexpr</code>
+			to check if the iterators are pointers, and then dispatching to that call directly. It is surprising that
+			<code>
+				<![CDATA[std::equal(...)]]>
+			</code>
+			does not do this already, or is perhaps inhibited despite being handed iterators to a vector directly. This is, again, a place where optimizations can be applied to libstdc++ and where everyone would see benefits, rather than just the operators within a
+			<code>
+				<![CDATA[std::vector]]>
+			</code>
+			.
+		</para>
+	</section>
+	<section>
+		<title>Future Work</title>
+		<para>
+			There is absolutely more work that can be contributed here. From further optimizations, to better optimized containers, to further improved handling of bit values. There are at least 2 new important containers that should be developed, more optimizations to put into
+			<code>
+				<![CDATA[bit_sequence]]>
+			</code>
+			, and more algorithms that can have their speed improved for bit the bit iterators and overall. This work was originall done by ThePhD in the Summer of Code, 2019. Speaking more directly as the person who received the Work-Study stipend to work on this, it is my full expectation that someone else (perhaps you) will pick these up for the next Summer of Code or for a different grant. These structures represent an imperative need in the industry and even for a beginner can give good practice into writing resilient, fast code to be used directly by thousands and perhaps relied upon by millions. If you have the free time and the means, by all means take up the projects listed below. If you do, do not hesitate to
+		</para>
+		<para>
+			<orderedlist>
+				<listitem>
+					<para>
+						Algorithms which could be reasonably optimized include the following:
+						<itemizedlist>
+							<listitem>
+								<para>
+									<code>std::rotate</code>
+									, to shift an entire
+									<code>value_type</code>
+									's bits at a time rather than individual bits;
+								</para>
+							</listitem>
+							<listitem>
+								<para>
+									<code>std::swap_ranges</code>
+									, to exchange an entire
+									<code>value_type</code>
+									's bits at a time with another;
+								</para>
+							</listitem>
+						</itemizedlist>
+					</para>
+				</listitem>
+				<listitem>
+					<para>
+						There is a lot of places inside of
+						<code>
+							<![CDATA[bit_sequence<...>]]>
+						</code>
+						where insertion or erasure could be done even faster than it is now by implementing a better rotate or shift algorithm. There are also optimization opportunities for copying multiple bits at a time using masking rather than default to a one-by-one approach when the incoming iterators are not aligned on the word boundary. Search for
+						<code>
+							<![CDATA[// TODO]]>
+						</code>
+						comments in the code residing in
+						<code>
+							<![CDATA[include/ext/bit_ds]]>
+						</code>
+						.
+					</para>
+				</listitem>
+				<listitem>
+					<para>
+						Much of the insert and erase code for
+						<code>
+							<![CDATA[bit_sequence<...>]]>
+						</code>
+						does not grant the
+						<![CDATA["Strong Exception Guarantee"]]>
+						that is known and applied to all standard library containers. Increasing the exception guarantees of the type is an excellent advanced project for anyone interested in diving that deeply into making sure that the code is extremely resilient to insertion failures and allocation failures.
+					</para>
+				</listitem>
+				<listitem>
+					<para>
+						Another serious optimization potential are 2 classes:
+						<code>
+							<![CDATA[small_buffer<typename Type, std::size_t MaxInternallyBufferedTypes, typename Allocator>]]>
+						</code>
+						and
+						<code>
+							<![CDATA[small_bit_buffer<typename Type, std::size_t MaxInternallyBufferedTypes, typename Allocator>]]>
+						</code>
+						. The reason there need to be 2 of them is because it is a space loss to store a separate
+						<code>size_type</code>
+						to track the bit position within a word. This does not mean both cannot share the majority of their code: in fact, an implementation of these two types should share a large degree of their internals, but differ only in the implementation of their
+						<code>size()</code>
+						,
+						<code>insert(...)</code>
+						,
+						<code>assign(...)</code>
+						, and
+						<code>erase(...)</code>
+						calls. Note that The # of bits required to store the by-the-bit size of a container would be around
+						<code>
+							<![CDATA[std::floor(std::pow(2, std::log2(binary_digits<Type>))]]>
+						</code>
+						, which means that most containers concerned with storing and managing a sequence of bits can simply keep the word size in the upper bits and the current occupied count of the words in the lower bits. Implementing these two classes will allow for cases in both high performance and memory-intensive environments where certain nodes can generally fit e.g. sparse hash keys in 128 bits, which requires only a storage of 2
+						<code>std::uint64_t</code>
+						s in a private buffer. It also solves the problem for more than just these individuals, as the request for the
+						<![CDATA["Small Buffer Optimization"]]>
+						guarantees has appeared several times over from library and application developers. This makes it prime real estate. If someone chooses to tackle this work for a Summer of Code, it is highly suggested that this is the only thing they work on, as it will likely take all of their time to get it absolutely correct (and perhaps even
+						<code>constexpr</code>
+						-capable.
+					</para>
+				</listitem>
+			</orderedlist>
+		</para>
+	</section>
+	<section>
+		<title>Acknowledgements</title>
+		<para>A huge thanks to Dr. Vincent Reverdy for sponsoring and helping with this work. An enormous thank you to Jonathan Wakely, Thomas Rodgers, and Ville Voutilainen for watching over my work during the Summer of Code 2019 through the Free Software Foundation and GNU Compiler Collection project.</para>
+		<para>Many thanks to the Blessed Guardian, Morwenn, for watching over my commits and cautioning me of my occasional derps.</para>
+		<para>
+			Thank you to Corentin Jabot for changing the name "Extents" to "Bounds" to better represent the begin/end type for
+			<code>bit_view</code>
+			.
+		</para>
+	</section>
+</chapter>
\ No newline at end of file
diff --git a/libstdc++-v3/doc/xml/manual/extensions.xml b/libstdc++-v3/doc/xml/manual/extensions.xml
index 86e92beffd3..77b515bddea 100644
--- a/libstdc++-v3/doc/xml/manual/extensions.xml
+++ b/libstdc++-v3/doc/xml/manual/extensions.xml
@@ -577,4 +577,8 @@ int main()
 <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" parse="xml" href="concurrency_extensions.xml">
 </xi:include>
 
+<!-- Chapter 16 : Bit Data Structures -->
+<xi:include xmlns:xi="http://www.w3.org/2001/XInclude" parse="xml" href="bit_extensions.xml">
+</xi:include>
+
 </part>
diff --git a/libstdc++-v3/include/Makefile.am b/libstdc++-v3/include/Makefile.am
index 3fe80f32cc4..5aca6f6a5a1 100644
--- a/libstdc++-v3/include/Makefile.am
+++ b/libstdc++-v3/include/Makefile.am
@@ -267,6 +267,16 @@ backward_headers = \
 	${backward_srcdir}/hashtable.h \
 	${backward_srcdir}/strstream
 
+bit_ds_srcdir = ${glibcxx_srcdir}/include/ext/bit_ds
+bit_ds_builddir = ./ext/bit_ds
+bit_ds_headers = \
+	${bit_ds_srcdir}/bit_algorithm_std.h \
+	${bit_ds_srcdir}/bit_algorithm.h \
+	${bit_ds_srcdir}/bit_iterator.h \
+	${bit_ds_srcdir}/bit_operations.h \
+	${bit_ds_srcdir}/bit_sequence.h \
+	${bit_ds_srcdir}/bit_view.h
+
 pb_srcdir = ${glibcxx_srcdir}/include/ext/pb_ds
 pb_builddir = ./ext/pb_ds
 
@@ -566,6 +576,7 @@ ext_headers = \
 	${ext_srcdir}/aligned_buffer.h \
 	${ext_srcdir}/alloc_traits.h \
 	${ext_srcdir}/atomicity.h \
+	${ext_srcdir}/bit \
 	${ext_srcdir}/bitmap_allocator.h \
 	${ext_srcdir}/cast.h \
 	${ext_srcdir}/cmath \
@@ -1005,7 +1016,7 @@ endif
 # CLEANFILES and all-local are kept up-to-date.
 allstamped = \
 	stamp-std stamp-bits stamp-bits-sup stamp-pstl stamp-c_base stamp-c_compatibility \
-	stamp-backward stamp-ext stamp-pb stamp-tr1 stamp-tr2 stamp-decimal \
+	stamp-backward stamp-bit_ds stamp-ext stamp-pb stamp-tr1 stamp-tr2 stamp-decimal \
 	stamp-experimental stamp-experimental-bits stamp-debug stamp-parallel \
 	stamp-host
 
@@ -1064,6 +1075,11 @@ stamp-backward: ${backward_headers}
 	@-cd ${backward_builddir} && $(LN_S) $? . 2>/dev/null
 	@$(STAMP) stamp-backward
 
+stamp-bit_ds: ${bit_ds_headers}
+	@-mkdir -p ${bit_ds_builddir}
+	@-cd ${bit_ds_builddir} && $(LN_S) $? . 2>/dev/null
+	@$(STAMP) stamp-bit_ds
+
 stamp-ext: ${ext_headers}
 	@-mkdir -p ${ext_builddir}
 	@-cd ${ext_builddir} && $(LN_S) $? . 2>/dev/null
@@ -1385,6 +1401,9 @@ install-headers:
 	$(mkinstalldirs) $(DESTDIR)${gxx_include_dir}/${backward_builddir}
 	for file in ${backward_headers}; do \
 	  $(INSTALL_DATA) $${file} $(DESTDIR)${gxx_include_dir}/${backward_builddir}; done
+	$(mkinstalldirs) $(DESTDIR)${gxx_include_dir}/${bit_ds_builddir}
+	for file in ${bit_ds_headers}; do \
+	  $(INSTALL_DATA) $${file} $(DESTDIR)${gxx_include_dir}/${bit_ds_builddir}; done
 	$(mkinstalldirs) $(DESTDIR)${gxx_include_dir}/${ext_builddir}
 	for file in ${ext_headers}; do \
 	  $(INSTALL_DATA) $${file} $(DESTDIR)${gxx_include_dir}/${ext_builddir}; done
diff --git a/libstdc++-v3/include/Makefile.in b/libstdc++-v3/include/Makefile.in
index b675d356cd4..545e113f392 100644
--- a/libstdc++-v3/include/Makefile.in
+++ b/libstdc++-v3/include/Makefile.in
@@ -612,6 +612,16 @@ backward_headers = \
 	${backward_srcdir}/hashtable.h \
 	${backward_srcdir}/strstream
 
+bit_ds_srcdir = ${glibcxx_srcdir}/include/ext/bit_ds
+bit_ds_builddir = ./ext/bit_ds
+bit_ds_headers = \
+	${bit_ds_srcdir}/bit_algorithm_std.h \
+	${bit_ds_srcdir}/bit_algorithm.h \
+	${bit_ds_srcdir}/bit_iterator.h \
+	${bit_ds_srcdir}/bit_operations.h \
+	${bit_ds_srcdir}/bit_sequence.h \
+	${bit_ds_srcdir}/bit_view.h
+
 pb_srcdir = ${glibcxx_srcdir}/include/ext/pb_ds
 pb_builddir = ./ext/pb_ds
 pb_subdirs = \
@@ -909,6 +919,7 @@ ext_headers = \
 	${ext_srcdir}/aligned_buffer.h \
 	${ext_srcdir}/alloc_traits.h \
 	${ext_srcdir}/atomicity.h \
+	${ext_srcdir}/bit \
 	${ext_srcdir}/bitmap_allocator.h \
 	${ext_srcdir}/cast.h \
 	${ext_srcdir}/cmath \
@@ -1336,7 +1347,7 @@ PCHFLAGS = -x c++-header -nostdinc++ $(CXXFLAGS) $(VTV_PCH_CXXFLAGS)
 # CLEANFILES and all-local are kept up-to-date.
 allstamped = \
 	stamp-std stamp-bits stamp-bits-sup stamp-pstl stamp-c_base stamp-c_compatibility \
-	stamp-backward stamp-ext stamp-pb stamp-tr1 stamp-tr2 stamp-decimal \
+	stamp-backward stamp-bit_ds stamp-ext stamp-pb stamp-tr1 stamp-tr2 stamp-decimal \
 	stamp-experimental stamp-experimental-bits stamp-debug stamp-parallel \
 	stamp-host
 
@@ -1565,6 +1576,11 @@ stamp-backward: ${backward_headers}
 	@-cd ${backward_builddir} && $(LN_S) $? . 2>/dev/null
 	@$(STAMP) stamp-backward
 
+stamp-bit_ds: ${bit_ds_headers}
+	@-mkdir -p ${bit_ds_builddir}
+	@-cd ${bit_ds_builddir} && $(LN_S) $? . 2>/dev/null
+	@$(STAMP) stamp-bit_ds
+
 stamp-ext: ${ext_headers}
 	@-mkdir -p ${ext_builddir}
 	@-cd ${ext_builddir} && $(LN_S) $? . 2>/dev/null
@@ -1859,6 +1875,9 @@ install-headers:
 	$(mkinstalldirs) $(DESTDIR)${gxx_include_dir}/${backward_builddir}
 	for file in ${backward_headers}; do \
 	  $(INSTALL_DATA) $${file} $(DESTDIR)${gxx_include_dir}/${backward_builddir}; done
+	$(mkinstalldirs) $(DESTDIR)${gxx_include_dir}/${bit_ds_builddir}
+	for file in ${bit_ds_headers}; do \
+	  $(INSTALL_DATA) $${file} $(DESTDIR)${gxx_include_dir}/${bit_ds_builddir}; done
 	$(mkinstalldirs) $(DESTDIR)${gxx_include_dir}/${ext_builddir}
 	for file in ${ext_headers}; do \
 	  $(INSTALL_DATA) $${file} $(DESTDIR)${gxx_include_dir}/${ext_builddir}; done
diff --git a/libstdc++-v3/include/ext/bit b/libstdc++-v3/include/ext/bit
new file mode 100644
index 00000000000..5c214b89848
--- /dev/null
+++ b/libstdc++-v3/include/ext/bit
@@ -0,0 +1,288 @@
+// bit data structures extension -*- C++ -*-
+
+// Copyright (C) 2019-2019 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// Under Section 7 of GPL version 3, you are granted additional
+// permissions described in the GCC Runtime Library Exception, version
+// 3.1, as published by the Free Software Foundation.
+
+// You should have received a copy of the GNU General Public License and
+// a copy of the GCC Runtime Library Exception along with this program;
+// see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+// <http://www.gnu.org/licenses/>.
+
+/** @file ext/bit
+ *  This file is a GNU extension to the Standard C++ Library.
+ *  It provides a suite of bit iterators, bit references,
+ *  bit values, algorithmic improvements
+ */
+
+#pragma once
+
+#ifndef _EXT_BIT_DS_H
+#define _EXT_BIT_DS_H 1
+
+#if (defined(__cplusplus) && __cplusplus >= 201703L)
+
+#include <ext/bit_ds/bit_operations.h>
+#include <ext/bit_ds/bit_iterator.h>
+#include <ext/bit_ds/bit_algorithm.h>
+#include <ext/bit_ds/bit_algorithm_std.h>
+#include <ext/bit_ds/bit_view.h>
+#include <ext/bit_ds/bit_sequence.h>
+
+#include <cstddef>
+#include <vector>
+#include <version>
+#if defined(__cpp_lib_span)
+#include <span>
+#endif // C++20 span
+
+#define _GLIBCXX_BIT_DS 201909L
+
+namespace __gnu_cxx _GLIBCXX_VISIBILITY(default)
+{
+  _GLIBCXX_BEGIN_NAMESPACE_VERSION
+
+  // helper structures
+  template <typename _Type>
+  using binary_digits = ::__gnu_cxx::__binary_digits<_Type>;
+
+  template <typename _Type>
+  inline constexpr bool binary_digits_v = binary_digits<_Type>::value;
+
+  // core structures
+  using bit_value = ::__gnu_cxx::__bit_value;
+
+  inline constexpr bit_value bit0 = ::__gnu_cxx::__bit0;
+  inline constexpr bit_value bit1 = ::__gnu_cxx::__bit1;
+
+  template<typename _Type>
+  using bit_mask_type = ::__gnu_cxx::__bit_mask_type<_Type>;
+
+  template<typename _Type>
+  using bit_mask_type_t = typename bit_mask_type<_Type>::type;
+
+  template<typename _Ref, typename _Mask = bit_mask_type_t<_Ref>>
+  using bit_reference = ::__gnu_cxx::__bit_reference<_Ref, _Mask>;
+
+  template<typename _Iterator>
+  using bit_pointer = ::__gnu_cxx::__bit_pointer<_Iterator>;
+
+  template<typename _It>
+  using bit_iterator = ::__gnu_cxx::__bit_iterator<_It>;
+
+  template<typename _Range>
+  using word_bit_bounds = ::__gnu_cxx::__word_bit_bounds<_Range>;
+
+  template<::std::size_t _First, ::std::size_t _Last>
+  using bit_bounds = ::__gnu_cxx::__bit_bounds<_First, _Last>;
+
+  using dynamic_bit_bounds = ::__gnu_cxx::__dynamic_bit_bounds;
+
+  template<typename _Range>
+  using dynamic_bit_bounds_for = ::__gnu_cxx::__dynamic_bit_bounds_for<_Range>;
+
+  template<typename _Range, typename _Bounds = word_bit_bounds<_Range>>
+  using bit_view = ::__gnu_cxx::__bit_view<_Range, _Bounds>;
+
+#if defined(__cpp_lib_span)
+  template<typename _Type,
+    typename _Bounds = word_bit_bounds<::std::span<_Type>>>
+  using bit_span = ::__gnu_cxx::__bit_view<::std::span<_Type>, _Bounds>;
+#endif // C++20 span
+
+  template<typename _Container>
+  using bit_sequence = ::__gnu_cxx::__bit_sequence<_Container>;
+
+  template<typename _Type, typename _Allocator = ::std::allocator<_Type>>
+  using dynamic_bitset =
+    ::__gnu_cxx::__bit_sequence<::std::vector<_Type, _Allocator>>;
+
+  // bit intrinsic functions, extended functionality
+  namespace detail
+  {
+    template<typename _Type>
+    using any_to_underlying_t = __gnu_cxx::__any_to_underlying_t<_Type>;
+
+    template<typename _Integralish>
+    auto
+    to_underlying_if_enum_or_char_t(_Integralish __val)
+    {
+      return __gnu_cxx::__to_underlying_if_enum_or_char_t(__val);
+    }
+  } // namespace detail
+
+  template<typename Integralish>
+  constexpr int countl_zero(Integralish value)
+  {
+    return __gnu_cxx::__bit_countl_zero(value);
+  }
+
+  template<typename Integralish>
+  constexpr int countl_one(Integralish value)
+  {
+    return __gnu_cxx::__bit_countl_one(value);
+  }
+
+  template<typename Integralish>
+  constexpr int countr_zero(Integralish value)
+  {
+    return __gnu_cxx::__bit_countr_zero(value);
+  }
+
+  template<typename Integralish>
+  constexpr int countr_one(Integralish value)
+  {
+    return __gnu_cxx::__bit_countr_one(value);
+  }
+
+  template<typename Integralish>
+  constexpr int firstl_zero(Integralish value)
+  {
+    return __gnu_cxx::__bit_firstl_zero(value);
+  }
+
+  template<typename Integralish>
+  constexpr int firstl_one(Integralish value)
+  {
+    return __gnu_cxx::__bit_firstl_one(value);
+  }
+
+  template<typename Integralish>
+  constexpr int firstr_zero(Integralish value)
+  {
+    return __gnu_cxx::__bit_firstr_zero(value);
+  }
+
+  template<typename Integralish>
+  constexpr int firstr_one(Integralish value)
+  {
+    return __gnu_cxx::__bit_firstr_one(value);
+  }
+
+  template<typename Integralish>
+  constexpr int popcount(Integralish value)
+  {
+    return __gnu_cxx::__bit_popcount(value);
+  }
+
+  // algorithms
+  template<typename _It, typename _Type>
+  constexpr bit_iterator<_It> bit_find(
+    bit_iterator<_It> __first, bit_iterator<_It> __last, const _Type& __val)
+  {
+    return ::__gnu_cxx::__bit_find(
+      ::std::move(__first), ::std::move(__last), __val);
+  }
+
+  template<typename _InputIt, typename _ForwardIt>
+  constexpr bit_iterator<_InputIt> bit_find_first_of(
+    bit_iterator<_InputIt> __first, bit_iterator<_InputIt> __last,
+    _ForwardIt __search_first, _ForwardIt __search_last)
+  {
+    return ::__gnu_cxx::__bit_find_first_of(::std::move(__first),
+      ::std::move(__last), ::std::move(__search_first),
+      ::std::move(__search_last));
+  }
+
+  template<typename _It0, typename _It1>
+  constexpr bool bit_equal(bit_iterator<_It0> __first0,
+    bit_iterator<_It0> __last0, bit_iterator<_It1> __first1,
+    bit_iterator<_It1> __last1)
+  {
+    return ::__gnu_cxx::__bit_equal(::std::move(__first0), ::std::move(__last0),
+      ::std::move(__first1), ::std::move(__last1));
+  }
+
+  template<typename _It0, typename _It1>
+  constexpr bool bit_equal(bit_iterator<_It0> __first0,
+    bit_iterator<_It0> __last0, bit_iterator<_It1> __first1)
+  {
+    return ::__gnu_cxx::__bit_equal(
+      ::std::move(__first0), ::std::move(__last0), ::std::move(__first1));
+  }
+
+  template<typename _InputIt0, typename _InputIt1>
+  constexpr bool bit_lexicographical_compare(bit_iterator<_InputIt0> __first0,
+    bit_iterator<_InputIt0> __last0, bit_iterator<_InputIt1> __first1,
+    bit_iterator<_InputIt1> __last1)
+  {
+    return ::__gnu_cxx::__bit_lexicographical_compare(::std::move(__first0),
+      ::std::move(__last0), ::std::move(__first1), ::std::move(__last1));
+  }
+
+  template<typename _ForwardIt>
+  constexpr bit_iterator<_ForwardIt> bit_is_sorted_until(
+    bit_iterator<_ForwardIt> __first, bit_iterator<_ForwardIt> __last)
+  {
+    return ::__gnu_cxx::__bit_is_sorted_until(
+      ::std::move(__first), ::std::move(__last));
+  }
+
+  template<typename _ForwardIt>
+  constexpr bool bit_is_sorted(
+    bit_iterator<_ForwardIt> __first, bit_iterator<_ForwardIt> __last)
+  {
+    return ::__gnu_cxx::__bit_is_sorted(
+      ::std::move(__first), ::std::move(__last));
+  }
+
+  template<typename _It, typename _Type>
+  constexpr typename std::iterator_traits<bit_iterator<_It>>::difference_type
+  bit_count(
+    bit_iterator<_It> __first, bit_iterator<_It> __last, const _Type& __value)
+  {
+    return ::__gnu_cxx::__bit_count(
+      ::std::move(__first), ::std::move(__last), __value);
+  }
+
+  template<typename _It, typename _OutputIt>
+  constexpr _OutputIt bit_copy(
+    bit_iterator<_It> __first, bit_iterator<_It> __last, _OutputIt __out_first)
+  {
+    return ::__gnu_cxx::__bit_copy(
+      ::std::move(__first), ::std::move(__last), ::std::move(__out_first));
+  }
+
+  template<typename _It, typename _Size, typename _OutputIt>
+  constexpr _OutputIt bit_copy_n(
+    bit_iterator<_It> __first, _Size __count, _OutputIt __out_first)
+  {
+    return ::__gnu_cxx::__bit_copy_n(
+      ::std::move(__first), __count, ::std::move(__out_first));
+  }
+
+  template<typename _ForwardIt, typename _Type>
+  constexpr bit_iterator<_ForwardIt> bit_fill(bit_iterator<_ForwardIt> __first,
+    bit_iterator<_ForwardIt> __last, const _Type& __value)
+  {
+    return ::__gnu_cxx::__bit_fill(
+      ::std::move(__first), ::std::move(__last), __value);
+  }
+
+  template<typename _OutputIt, typename _Size, typename _Type>
+  constexpr bit_iterator<_OutputIt> bit_fill_n(
+    bit_iterator<_OutputIt> __first, _Size __count, const _Type& __value)
+  {
+    return ::__gnu_cxx::__bit_fill_n(
+      ::std::move(__first), ::std::move(__count), __value);
+  }
+
+  _GLIBCXX_END_NAMESPACE_VERSION
+} // namespace __gnu_cxx_GLIBCXX_VISIBILITY(default)
+
+#endif // __cplusplus is on 20/2a or better
+
+#endif
diff --git a/libstdc++-v3/include/ext/bit_ds/bit_algorithm.h b/libstdc++-v3/include/ext/bit_ds/bit_algorithm.h
new file mode 100644
index 00000000000..313780f20c2
--- /dev/null
+++ b/libstdc++-v3/include/ext/bit_ds/bit_algorithm.h
@@ -0,0 +1,1033 @@
+
+// bit iterator-specific algorithmic optimizations -*- C++ -*-
+
+// Copyright (C) 2019-2019 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// Under Section 7 of GPL version 3, you are granted additional
+// permissions described in the GCC Runtime Library Exception, version
+// 3.1, as published by the Free Software Foundation.
+
+// You should have received a copy of the GNU General Public License and
+// a copy of the GCC Runtime Library Exception along with this program;
+// see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+// <http://www.gnu.org/licenses/>.
+
+/** @file ext/bit_ds/bit_algorithm.h
+ *  This file is a GNU extension to the Standard C++ Library.
+ *  It's goal is to provide enhanced algorithms for which
+ *  optimizations can be made for the underlying value type
+ *  and some basic awareness of the used __bit_iterator.
+ *  Vastly improves performance metrics of several algorithms,
+ *  especially those whose data can fit in L1/L2 cache.
+ */
+
+#pragma once
+
+#ifndef _EXT_BIT_DS_BIT_ALGORITHM_H
+#define _EXT_BIT_DS_BIT_ALGORITHM_H 1
+
+#if (defined(__cplusplus) && __cplusplus >= 201703L)
+
+#include <bits/c++config.h>
+
+#include <ext/bit_ds/bit_operations.h>
+#include <ext/bit_ds/bit_iterator.h>
+
+#include <algorithm>
+#include <iterator>
+#include <utility>
+
+namespace __gnu_cxx _GLIBCXX_VISIBILITY(default)
+{
+  _GLIBCXX_BEGIN_NAMESPACE_VERSION
+
+  template<bool _Value, typename _It>
+  constexpr __bit_iterator<_It> __bit_find_value(
+    __bit_iterator<_It> __first, __bit_iterator<_It> __last)
+  {
+    using __iterator      = __bit_iterator<_It>;
+    using __base_iterator = typename __bit_iterator<_It>::iterator_type;
+    using __base_reference =
+      typename ::std::iterator_traits<__base_iterator>::reference;
+
+    for (; __first != __last && __first.position() != 0; ++__first)
+      {
+        if constexpr (_Value)
+          {
+            if (static_cast<bool>(*__first))
+              {
+                return __first;
+              }
+          }
+        else
+          {
+            if (!static_cast<bool>(*__first))
+              {
+                return __first;
+              }
+          }
+      }
+    __base_iterator __first_base = ::std::move(__first).base();
+    auto __last_position         = __last.position();
+    __base_iterator __last_base  = ::std::move(__last).base();
+    for (; __first_base != __last_base; ++__first_base)
+      {
+        __base_reference __ref_base = *__first_base;
+        if constexpr (_Value)
+          {
+            int __first_lsb = __bit_firstr_one(__ref_base);
+            if (__first_lsb != 0)
+              {
+                return __iterator(::std::move(__first_base), __first_lsb - 1);
+              }
+          }
+        else
+          {
+            int __first_lsb = __bit_firstr_zero(__ref_base);
+            if (__first_lsb != 0)
+              {
+                return __iterator(::std::move(__first_base), __first_lsb - 1);
+              }
+          }
+      }
+    if (__last_position == 0)
+      {
+        return __last;
+      }
+    __first = __iterator(::std::move(__first_base), 0);
+    __last  = __iterator(::std::move(__last_base), __last_position);
+    for (; __first != __last; ++__first)
+      {
+        if constexpr (_Value)
+          {
+            if (static_cast<bool>(*__first))
+              {
+                return __first;
+              }
+          }
+        else
+          {
+            if (!static_cast<bool>(*__first))
+              {
+                return __first;
+              }
+          }
+      }
+    return __last;
+  }
+
+  template<typename _It, typename _Type>
+  constexpr __bit_iterator<_It> __bit_find(
+    __bit_iterator<_It> __first, __bit_iterator<_It> __last, const _Type& __val)
+  {
+    if (__first == __last)
+      {
+        return __first;
+      }
+    if (__val)
+      {
+        return __bit_find_value<true>(
+          ::std::move(__first), ::std::move(__last));
+      }
+    else
+      {
+        return __bit_find_value<false>(
+          ::std::move(__first), ::std::move(__last));
+      }
+  }
+
+  template<typename _InputIt, typename _ForwardIt>
+  constexpr __bit_iterator<_InputIt> __bit_find_first_of(
+    __bit_iterator<_InputIt> __first, __bit_iterator<_InputIt> __last,
+    _ForwardIt __search_first, _ForwardIt __search_last)
+  {
+    if (__first == __last || __search_first == __search_last)
+      {
+        return __last;
+      }
+    // we note that the value space here is literally 2,
+    // and thusly know that, in advance,
+    // we can make quite a few hard optimizations
+    // we if know in totally what we are looking for
+    bool __find_false = false;
+    bool __find_true  = false;
+    for (; __search_first != __search_last; ++__search_first)
+      {
+        if (static_cast<bool>(*__search_first))
+          {
+            __find_true = true;
+          }
+        else
+          {
+            __find_false = true;
+          }
+      }
+    if (__find_false && __find_true)
+      {
+        // literally any value is good enough!
+        return __first;
+      }
+    if (__find_true)
+      {
+        return __bit_find_value<true>(
+          ::std::move(__first), ::std::move(__last));
+      }
+    else
+      {
+        return __bit_find_value<false>(
+          ::std::move(__first), ::std::move(__last));
+      }
+  }
+
+  template<typename _It0, typename _It1>
+  constexpr bool __bit_equal(__bit_iterator<_It0> __first0,
+    __bit_iterator<_It0> __last0, __bit_iterator<_It1> __first1)
+  {
+    using __iterator0 = __bit_iterator<_It0>;
+    using __iterator1 = __bit_iterator<_It1>;
+    using __difference_type0 =
+      typename ::std::iterator_traits<__iterator0>::difference_type;
+    using __iterator_category0 = typename __iterator0::iterator_category;
+    using __iterator_category1 = typename __iterator1::iterator_category;
+    using __base_iterator0     = typename __iterator0::iterator_type;
+    using __base_iterator1     = typename __iterator1::iterator_type;
+    using __base_value_type0 =
+      typename ::std::iterator_traits<__base_iterator0>::value_type;
+    using __base_value_type1 =
+      typename ::std::iterator_traits<__base_iterator1>::value_type;
+    if constexpr (::std::is_unsigned_v<__base_value_type0> &&
+                  ::std::is_unsigned_v<__base_value_type1> &&
+                  ::std::is_same_v<__base_value_type0, __base_value_type1>)
+      {
+        if constexpr (__is_iterator_category_or_better_v<
+                        ::std::forward_iterator_tag, __iterator_category0> &&
+                      __is_iterator_category_or_better_v<
+                        ::std::forward_iterator_tag, __iterator_category1>)
+          {
+            if (__first0.position() == __first1.position())
+              {
+                // can compare base items
+                if (__first0.position() != 0)
+                  {
+                    // align to word boundary
+                    for (; __first0 != __last0 && __first0.position() != 0;
+                         ++__first0, (void)++__first1)
+                      {
+                        if (!(*__first0 == *__first1))
+                          {
+                            return false;
+                          }
+                      }
+                  }
+                auto __last0_position          = __last0.position();
+                __base_iterator0 __first_base0 = ::std::move(__first0).base();
+                __base_iterator0 __last_base0  = ::std::move(__last0).base();
+                __base_iterator1 __first_base1 = ::std::move(__first1).base();
+                bool __base_equal =
+                  ::std::equal(__first_base0, __last_base0, __first_base1);
+                if (__last0_position == 0)
+                  {
+                    return __base_equal;
+                  }
+                else if (!__base_equal)
+                  {
+                    return false;
+                  }
+                // FIXME: this is not efficient, maybe just
+                // write out the std::equal here?
+                // we do lose any potential memcmp or optimizations
+                // made by the original, though...
+                // FIXME: optimize stdlib internals to give us a version which
+                // takes
+                // __first1 as a reference, so that we can access its value?
+                __difference_type0 __first1_dist =
+                  ::std::distance(__first_base0, __last_base0);
+                __first0 = __iterator0(::std::move(__last_base0), 0);
+                __first1 = __iterator1(
+                  ::std::next(::std::move(__first_base1), __first1_dist), 0);
+              }
+          }
+        else
+          {
+            if (__first0.position() == 0 && __first1.position() == 0 &&
+                __last0.position() == 0)
+              {
+                // can compare base items
+                __base_iterator0 __first_base0 = ::std::move(__first0).base();
+                __base_iterator0 __last_base0  = ::std::move(__last0).base();
+                __base_iterator1 __first_base1 = ::std::move(__first1).base();
+                return ::std::equal(::std::move(__first_base0),
+                  ::std::move(__last_base0), ::std::move(__first_base1));
+              }
+          }
+      }
+    for (; __first0 != __last0; ++__first0, (void)++__first1)
+      {
+        if (!(*__first0 == *__first1))
+          {
+            return false;
+          }
+      }
+    return __first0 == __last0;
+  }
+
+  template<typename _It0, typename _It1>
+  constexpr bool __bit_equal(__bit_iterator<_It0> __first0,
+    __bit_iterator<_It0> __last0, __bit_iterator<_It1> __first1,
+    __bit_iterator<_It1> __last1)
+  {
+    using __iterator0          = __bit_iterator<_It0>;
+    using __iterator1          = __bit_iterator<_It1>;
+    using __iterator_category0 = typename __iterator0::iterator_category;
+    using __iterator_category1 = typename __iterator1::iterator_category;
+    using __base_iterator0     = typename __iterator0::iterator_type;
+    using __base_iterator1     = typename __iterator1::iterator_type;
+    using __base_value_type0 =
+      typename ::std::iterator_traits<__base_iterator0>::value_type;
+    using __base_value_type1 =
+      typename ::std::iterator_traits<__base_iterator1>::value_type;
+    if constexpr (__is_iterator_category_or_better_v<
+                    ::std::random_access_iterator_tag, __iterator_category0> &&
+                  __is_iterator_category_or_better_v<
+                    ::std::random_access_iterator_tag, __iterator_category1>)
+      {
+        auto __dist0 = ::std::distance(__first0, __last0);
+        auto __dist1 = ::std::distance(__first1, __last1);
+        if (__dist0 != __dist1)
+          {
+            return false;
+          }
+      }
+    if constexpr (::std::is_unsigned_v<__base_value_type0> &&
+                  ::std::is_unsigned_v<__base_value_type1> &&
+                  ::std::is_same_v<__base_value_type0, __base_value_type1>)
+      {
+        if constexpr (__is_iterator_category_or_better_v<
+                        ::std::forward_iterator_tag, __iterator_category0> &&
+                      __is_iterator_category_or_better_v<
+                        ::std::forward_iterator_tag, __iterator_category1>)
+          {
+            if (__first0.position() == __first1.position())
+              {
+                // align to word boundary
+                for (; __first0 != __last0 && __first1 != __last1 &&
+                       __first0.position() != 0;
+                     ++__first0, (void)++__first1)
+                  {
+                    if (!(*__first0 == *__first1))
+                      {
+                        return false;
+                      }
+                  }
+                auto __last0_position          = __last0.position();
+                auto __last1_position          = __last1.position();
+                __base_iterator0 __first_base0 = ::std::move(__first0).base();
+                __base_iterator0 __last_base0  = ::std::move(__last0).base();
+                __base_iterator1 __first_base1 = ::std::move(__first1).base();
+                __base_iterator1 __last_base1  = ::std::move(__last1).base();
+                bool __base_equal              = ::std::equal(
+                  __first_base0, __last_base0, __first_base1, __last_base1);
+                if (__last0_position == 0 && __last1_position == 0)
+                  {
+                    return __base_equal;
+                  }
+                else if (!__base_equal)
+                  {
+                    return false;
+                  }
+                __first0 = __iterator0(::std::move(__last_base0), 0);
+                __first1 = __iterator1(::std::move(__last_base1), 0);
+              }
+          }
+        else
+          {
+            if (__first0.position() == 0 && __first1.position() == 0 &&
+                __last0.position() == 0 && __last1.position() == 0)
+              {
+                // can compare base items
+                __base_iterator0 __first_base0 = ::std::move(__first0).base();
+                __base_iterator0 __last_base0  = ::std::move(__last0).base();
+                __base_iterator1 __first_base1 = ::std::move(__first1).base();
+                __base_iterator1 __last_base1  = ::std::move(__last1).base();
+                return ::std::equal(::std::move(__first_base0),
+                  ::std::move(__last_base0), ::std::move(__first_base1),
+                  ::std::move(__last_base1));
+              }
+          }
+      }
+    for (; __first0 != __last0 && __first1 != __last1;
+         ++__first0, (void)++__first1)
+      {
+        if (!(*__first0 == *__first1))
+          {
+            return false;
+          }
+      }
+    return __first0 == __last0 && __first1 == __last1;
+  }
+
+  template<typename _InputIt0, typename _InputIt1>
+  constexpr bool __bit_lexicographical_compare(
+    __bit_iterator<_InputIt0> __first0, __bit_iterator<_InputIt0> __last0,
+    __bit_iterator<_InputIt1> __first1, __bit_iterator<_InputIt1> __last1)
+  {
+    using __iterator0 = __bit_iterator<_InputIt0>;
+    using __iterator1 = __bit_iterator<_InputIt1>;
+    using __reference0 =
+      typename ::std::iterator_traits<__iterator0>::reference;
+    using __reference1 =
+      typename ::std::iterator_traits<__iterator1>::reference;
+    using __iterator_category0 =
+      typename ::std::iterator_traits<__iterator0>::iterator_category;
+    using __iterator_category1 =
+      typename ::std::iterator_traits<__iterator1>::iterator_category;
+    using __base_iterator0 = typename __iterator0::iterator_type;
+    using __base_iterator1 = typename __iterator1::iterator_type;
+    using __base_value_type0 =
+      typename ::std::iterator_traits<__base_iterator0>::value_type;
+    using __base_value_type1 =
+      typename ::std::iterator_traits<__base_iterator1>::value_type;
+    if constexpr (::std::is_unsigned_v<__base_value_type0> &&
+                  ::std::is_unsigned_v<__base_value_type1> &&
+                  ::std::is_same_v<__base_value_type0, __base_value_type1>)
+      {
+        if constexpr (__is_iterator_category_or_better_v<
+                        ::std::forward_iterator_tag, __iterator_category0> &&
+                      __is_iterator_category_or_better_v<
+                        ::std::forward_iterator_tag, __iterator_category1>)
+          {
+            if (__first0.position() == __first1.position())
+              {
+                if (__first0.position() != 0)
+                  {
+                    for (; __first0 != __last0 && __first1 != __last1 &&
+                           __first0.position() != 0;
+                         ++__first0, (void)++__first1)
+                      {
+                        __reference0 __ref_base0 = *__first0;
+                        __reference1 __ref_base1 = *__first1;
+                        if (__ref_base0 < __ref_base1)
+                          {
+                            return true;
+                          }
+                        if (__ref_base1 < __ref_base0)
+                          {
+                            return false;
+                          }
+                      }
+                  }
+                auto __last0_position          = __last0.position();
+                auto __last1_position          = __last1.position();
+                __base_iterator0 __first_base0 = ::std::move(__first0).base();
+                __base_iterator0 __last_base0  = ::std::move(__last0).base();
+                __base_iterator1 __first_base1 = ::std::move(__first1).base();
+                __base_iterator1 __last_base1  = ::std::move(__last1).base();
+                bool __base_lexicographic_compare =
+                  ::std::lexicographical_compare(::std::move(__first_base0),
+                    __last_base0, ::std::move(__first_base1), __last_base1);
+
+                if (__last0_position == 0 && __last1_position == 0)
+                  {
+                    return __base_lexicographic_compare;
+                  }
+                else if (!__base_lexicographic_compare)
+                  {
+                    return false;
+                  }
+                __first0 = __iterator0(::std::move(__last_base0), 0);
+                __first1 = __iterator1(::std::move(__last_base1), 0);
+              }
+          }
+        else
+          {
+            if (__first0.position() == 0 && __first1.position() == 0 &&
+                __last0.position() == 0 && __last1.position() == 0)
+              {
+                __base_iterator0 __first_base0 = ::std::move(__first0).base();
+                __base_iterator0 __last_base0  = ::std::move(__last0).base();
+                __base_iterator1 __first_base1 = ::std::move(__first1).base();
+                __base_iterator1 __last_base1  = ::std::move(__last1).base();
+                return ::std::lexicographical_compare(
+                  ::std::move(__first_base0), ::std::move(__last_base0),
+                  ::std::move(__first_base1), ::std::move(__last_base1));
+              }
+          }
+      }
+
+    // base case
+    for (; __first0 != __last0 && __first1 != __last1;
+         ++__first0, (void)++__first1)
+      {
+        __reference0 __ref_base0 = *__first0;
+        __reference1 __ref_base1 = *__first1;
+        if (__ref_base0 < __ref_base1)
+          {
+            return true;
+          }
+        if (__ref_base1 < __ref_base0)
+          {
+            return false;
+          }
+      }
+    return __first0 == __last0 && __first1 != __last1;
+  }
+
+  template<bool _CheckPosition, typename _ForwardIt>
+  constexpr bool __bit_is_sorted_until_single_bit_position(
+    __bit_iterator<_ForwardIt> & __first, __bit_iterator<_ForwardIt> & __it,
+    __bit_iterator<_ForwardIt> & __last)
+  {
+    while (__it != __first && (!_CheckPosition || __it.position() != 0))
+      {
+        if (__it == __last)
+          {
+            // reached end, we're okay
+            return true;
+          }
+        if (*__it < *__first)
+          {
+            return true;
+          }
+        __first = __it;
+        ++__it;
+      }
+    //__first = __it;
+    return false;
+  }
+
+  template<typename _ForwardIt>
+  constexpr __bit_iterator<_ForwardIt> __bit_is_sorted_until_unsigned(
+    __bit_iterator<_ForwardIt> __first, __bit_iterator<_ForwardIt> __last)
+  {
+    if (__first == __last)
+      {
+        return __last;
+      }
+
+    using __iterator      = __bit_iterator<_ForwardIt>;
+    using __base_iterator = typename __iterator::iterator_type;
+
+    // advance all the bits first
+    __iterator __it = __first;
+    ++__it;
+    if (__it == __last)
+      {
+        return __it;
+      }
+    if (__bit_is_sorted_until_single_bit_position<true>(__first, __it, __last))
+      {
+        return __it;
+      }
+    auto __last_position        = __last.position();
+    __base_iterator __it_base   = __it.base();
+    __base_iterator __last_base = __last.base();
+    if (__it_base != __last_base)
+      {
+        // now we can work on individual words and use
+        // popcount optimization
+        using __value_type = typename __bit_iterator<_ForwardIt>::value_type;
+        using __base_reference =
+          typename ::std::iterator_traits<__base_iterator>::reference;
+        using __base_value_type =
+          typename ::std::iterator_traits<__base_iterator>::value_type;
+        __value_type __first_val = *__first;
+        if (!__first_val)
+          {
+            // we are currently at zero
+            for (; __it_base != __last_base; ++__it_base)
+              {
+                __base_reference __ref_base = *__it_base;
+                if (__ref_base == static_cast<__base_value_type>(0))
+                  {
+                    continue;
+                  }
+                ::std::size_t __first_lsb_bit = __bit_firstr_one(__ref_base) - 1;
+                const int __all_set_bits      = __bit_popcount(__ref_base);
+                const int __expected_set_bits = static_cast<int>(
+                  __binary_digits_v<__base_value_type> - __first_lsb_bit);
+                if (__expected_set_bits == __all_set_bits)
+                  {
+                    // still sorted, go to next section
+                    ++__it_base;
+                    break;
+                  }
+                __iterator __it_tail(__it_base, __first_lsb_bit);
+                for (; __first_lsb_bit < __binary_digits_v<__base_value_type>;
+                     ++__first_lsb_bit, (void)++__it_tail)
+                  {
+                    bool __tail_bit_val = *__it_tail;
+                    if (!__tail_bit_val)
+                      {
+                        // found the last sorted position
+                        return __it_tail;
+                      }
+                  }
+              }
+          }
+
+        // we encountered our first 1
+        // and it was still sorted
+        // now we count all the trues
+        // until we get a false
+        while (__it_base != __last_base)
+          {
+            __base_reference __ref_base = *__it_base;
+            const int __first_zero      = __bit_firstr_zero(__ref_base);
+            if (__first_zero != 0)
+              {
+                // we found the anamoly
+                return __iterator(__it_base, __first_zero - 1);
+              }
+          }
+      }
+    if (__last_position == 0)
+      {
+        return __last;
+      }
+    if (__it == __last)
+      {
+        return __it;
+      }
+    if (__bit_is_sorted_until_single_bit_position<true>(__first, __it, __last))
+      {
+        return __it;
+      }
+    return __last;
+  }
+
+  template<typename _ForwardIt>
+  constexpr __bit_iterator<_ForwardIt> __bit_is_sorted_until(
+    __bit_iterator<_ForwardIt> __first, __bit_iterator<_ForwardIt> __last)
+  {
+    using __iterator      = __bit_iterator<_ForwardIt>;
+    using __base_iterator = typename __iterator::iterator_type;
+    using __base_value_type =
+      typename ::std::iterator_traits<__base_iterator>::value_type;
+    if constexpr (::std::is_unsigned_v<__base_value_type>)
+      {
+        return __bit_is_sorted_until_unsigned(
+          ::std::move(__first), ::std::move(__last));
+      }
+    else
+      {
+        using __value_type = typename __iterator::value_type;
+
+        return ::std::is_sorted_until(::std::move(__first), ::std::move(__last),
+          ::std::less<__value_type>());
+      }
+  }
+
+  template<typename _ForwardIt>
+  constexpr bool __bit_is_sorted(
+    __bit_iterator<_ForwardIt> __first, __bit_iterator<_ForwardIt> __last)
+  {
+    return __bit_is_sorted_until(__first, __last) == __last;
+  }
+
+  template<bool _Value, typename _InputIt>
+  constexpr
+    typename ::std::iterator_traits<__bit_iterator<_InputIt>>::difference_type
+    __bit_count_value(
+      __bit_iterator<_InputIt> __first, __bit_iterator<_InputIt> __last)
+  {
+    using __iterator      = __bit_iterator<_InputIt>;
+    using __base_iterator = typename __iterator::iterator_type;
+    using __base_value_type =
+      typename ::std::iterator_traits<__base_iterator>::value_type;
+    using __difference_type =
+      typename ::std::iterator_traits<__iterator>::difference_type;
+
+    __difference_type __count = 0;
+    if (__first == __last)
+      {
+        return __count;
+      }
+    while (__first.position() != 0)
+      {
+        if (__first == __last)
+          {
+            return __count;
+          }
+        if constexpr (_Value)
+          {
+            __count +=
+              static_cast<__difference_type>(static_cast<bool>(*__first));
+          }
+        else
+          {
+            __count +=
+              static_cast<__difference_type>(!static_cast<bool>(*__first));
+          }
+        ++__first;
+      }
+
+    auto __last_position         = __last.position();
+    __base_iterator __first_base = ::std::move(__first).base();
+    __base_iterator __last_base  = ::std::move(__last).base();
+    while (__first_base != __last_base)
+      {
+        if constexpr (_Value)
+          {
+            __count += __bit_popcount(*__first_base);
+          }
+        else
+          {
+            __count += (__binary_digits_v<__base_value_type> -
+                        __bit_popcount(*__first_base));
+          }
+        ++__first_base;
+      }
+    if (__last_position == 0)
+      {
+        return __count;
+      }
+    __first = __iterator(::std::move(__first_base), 0);
+    while (__first != __last)
+      {
+        if constexpr (_Value)
+          {
+            __count +=
+              static_cast<__difference_type>(static_cast<bool>(*__first));
+          }
+        else
+          {
+            __count +=
+              static_cast<__difference_type>(!static_cast<bool>(*__first));
+          }
+        ++__first;
+      }
+
+    return __count;
+  }
+
+  template<typename _InputIt, typename _Type>
+  constexpr
+    typename ::std::iterator_traits<__bit_iterator<_InputIt>>::difference_type
+    __bit_count(__bit_iterator<_InputIt> __first,
+      __bit_iterator<_InputIt> __last, const _Type& __value)
+  {
+    if (static_cast<bool>(__value))
+      {
+        return __bit_count_value<true>(
+          ::std::move(__first), ::std::move(__last));
+      }
+    else
+      {
+        return __bit_count_value<false>(
+          ::std::move(__first), ::std::move(__last));
+      }
+  }
+
+  template<typename _It, typename _OutputIt>
+  constexpr __bit_iterator<_OutputIt> __bit_copy_same(
+    __bit_iterator<_It> __first, __bit_iterator<_It> __last,
+    __bit_iterator<_OutputIt> __out_first)
+  {
+    using __iterator          = __bit_iterator<_It>;
+    using __out_iterator      = __bit_iterator<_OutputIt>;
+    using __out_base_iterator = typename __out_iterator::iterator_type;
+
+    // align to 0 boundary
+    // we already checked __out_first's position
+    // is equal to this one,
+    // so this is okay to do for both
+    for (; __first != __last && __first.position() != 0;
+         ++__first, (void)++__out_first)
+      {
+        *__out_first = *__first;
+      }
+
+    auto __last_position              = __last.position();
+    __out_base_iterator __out_it_base = ::std::copy(::std::move(__first).base(),
+      __last.base(), ::std::move(__out_first).base());
+    __out_iterator __out_it(::std::move(__out_it_base), 0);
+    if (__last_position == 0)
+      {
+        return __out_it;
+      }
+    // copy the last bits
+    __iterator __last_it(::std::move(__last).base(), 0);
+    for (; __last_position > 0;
+         --__last_position, (void)++__out_it, (void)__last_it)
+      {
+        *__out_it = *__last_it;
+      }
+    return __out_it;
+  }
+
+  template<typename _It, typename _OutputIt>
+  constexpr _OutputIt __bit_copy(__bit_iterator<_It> __first,
+    __bit_iterator<_It> __last, _OutputIt __out_first)
+  {
+    if (__first == __last)
+      {
+        return __out_first;
+      }
+    if constexpr (__is_bit_iterator_v<_OutputIt>)
+      {
+        using __base_iterator     = typename __bit_iterator<_It>::iterator_type;
+        using __out_base_iterator = typename _OutputIt::iterator_type;
+        using __base_value_type =
+          typename ::std::iterator_traits<__base_iterator>::value_type;
+        using __out_base_value_type =
+          typename ::std::iterator_traits<__out_base_iterator>::value_type;
+        if constexpr (::std::is_same_v<__base_value_type,
+                        __out_base_value_type> ||
+                      ::std::is_assignable_v<__out_base_value_type,
+                        __base_value_type>)
+          {
+            if (__first.position() == __out_first.position())
+              {
+                return __bit_copy_same(::std::move(__first),
+                  ::std::move(__last), ::std::move(__out_first));
+              }
+          }
+      }
+    for (; __first != __last; ++__first, (void)++__out_first)
+      {
+        *__out_first = *__first;
+      }
+    return __out_first;
+  }
+
+  template<typename _It, typename _Size, typename _OutputIt>
+  constexpr __bit_iterator<_OutputIt> __bit_copy_n_same(
+    __bit_iterator<_It> __first, _Size __count,
+    __bit_iterator<_OutputIt> __out_first)
+  {
+    using __iterator      = __bit_iterator<_It>;
+    using __base_iterator = typename __iterator::iterator_type;
+    using __base_value_type =
+      typename ::std::iterator_traits<__base_iterator>::value_type;
+    using __out_iterator      = __bit_iterator<_OutputIt>;
+    using __out_base_iterator = typename __out_iterator::iterator_type;
+
+    // align to 0 boundary
+    // we already checked __out_first's position
+    // is equal to this one,
+    // so this is okay to do for both
+    for (; __count > 0 && __first.position() != 0;
+         ++__first, (void)++__out_first, (void)--__count)
+      {
+        *__out_first = *__first;
+      }
+
+    _Size __n_base = __count / __binary_digits_v<__base_value_type>;
+    __out_base_iterator __out_it_base =
+      ::std::copy_n(__first.base(), __n_base, ::std::move(__out_first).base());
+    __out_iterator __out_it(::std::move(__out_it_base), 0);
+    _Size __last_pos = __count % __binary_digits_v<__base_value_type>;
+    if (__last_pos == 0)
+      {
+        return __out_it;
+      }
+
+    // copy the last bits
+    // FIXME: this is technically inefficient,
+    // (incrementing the iterator if it's not a
+    // random access iterator or better)
+    // but then we'd have to re-implement copy_n
+    // so we can get the last iterator properly
+    // from the copy operation
+    // FIXME: optimize std lib to have
+    // internal __copy_n_ref op that takes
+    // first by reference
+    __base_iterator __last_it_base =
+      ::std::next(::std::move(__first).base(), __n_base);
+    __iterator __last_it(::std::move(__last_it_base), 0);
+    for (; __last_pos > 0; --__last_pos, (void)++__out_it, (void)++__last_it)
+      {
+        *__out_it = *__last_it;
+      }
+
+    return __out_it;
+  }
+
+  template<typename _It, typename _Size, typename _OutputIt>
+  constexpr _OutputIt __bit_copy_n(
+    __bit_iterator<_It> __first, _Size __count, _OutputIt __out_first)
+  {
+    if (__count < static_cast<_Size>(1))
+      {
+        return __out_first;
+      }
+    if constexpr (__is_bit_iterator_v<_OutputIt>)
+      {
+        using __base_iterator     = typename __bit_iterator<_It>::iterator_type;
+        using __out_base_iterator = typename _OutputIt::iterator_type;
+        using __base_value_type =
+          typename ::std::iterator_traits<__base_iterator>::value_type;
+        using __out_base_value_type =
+          typename ::std::iterator_traits<__out_base_iterator>::value_type;
+        if constexpr (::std::is_same_v<__base_value_type,
+                        __out_base_value_type> ||
+                      ::std::is_assignable_v<__out_base_value_type,
+                        __base_value_type>)
+          {
+            if (__first.position() == __out_first.position())
+              {
+                return __bit_copy_n_same(::std::move(__first),
+                  ::std::move(__count), ::std::move(__out_first));
+              }
+          }
+      }
+    for (; __count > 0; ++__first, (void)++__out_first, (void)--__count)
+      {
+        *__out_first = *__first;
+      }
+    return __out_first;
+  }
+
+  template<bool _Value, typename _ForwardIt>
+  constexpr __bit_iterator<_ForwardIt> __bit_fill_value(
+    __bit_iterator<_ForwardIt> __first, __bit_iterator<_ForwardIt> __last)
+  {
+    using __iterator      = __bit_iterator<_ForwardIt>;
+    using __base_iterator = typename __iterator::iterator_type;
+    using __base_value_type =
+      typename ::std::iterator_traits<__base_iterator>::value_type;
+    using __base_underlying_value_type =
+      __any_to_underlying_t<__base_value_type>;
+
+    for (; __first != __last && __first.position() != 0; ++__first)
+      {
+        if constexpr (_Value)
+          {
+            (*__first).set();
+          }
+        else
+          {
+            (*__first).reset();
+          }
+      }
+    auto __last_position         = __last.position();
+    __base_iterator __first_base = ::std::move(__first).base();
+    __base_iterator __last_base  = ::std::move(__last).base();
+    for (; __first_base != __last_base; ++__first_base)
+      {
+        if constexpr (_Value)
+          {
+            *__first_base = static_cast<__base_value_type>(
+              ::std::numeric_limits<__base_underlying_value_type>::max());
+          }
+        else
+          {
+            *__first_base = static_cast<__base_value_type>(0);
+          }
+      }
+    __first = __iterator(::std::move(__first_base), 0);
+    for (; __last_position > 0; --__last_position, (void)++__first)
+      {
+        if constexpr (_Value)
+          {
+            (*__first).set();
+          }
+        else
+          {
+            (*__first).reset();
+          }
+      }
+    return __first;
+  }
+
+  template<typename _ForwardIt, typename _Type>
+  constexpr __bit_iterator<_ForwardIt> __bit_fill(
+    __bit_iterator<_ForwardIt> __first, __bit_iterator<_ForwardIt> __last,
+    const _Type& __value)
+  {
+    if (static_cast<bool>(__value))
+      {
+        return __bit_fill_value<true>(
+          ::std::move(__first), ::std::move(__last));
+      }
+    else
+      {
+        return __bit_fill_value<false>(
+          ::std::move(__first), ::std::move(__last));
+      }
+  }
+
+  template<bool _Value, typename _ForwardIt, typename _Size>
+  constexpr __bit_iterator<_ForwardIt> __bit_fill_n_value(
+    __bit_iterator<_ForwardIt> __first, _Size __count)
+  {
+    using __iterator      = __bit_iterator<_ForwardIt>;
+    using __base_iterator = typename __iterator::iterator_type;
+    using __base_value_type =
+      typename ::std::iterator_traits<__base_iterator>::value_type;
+    using __base_underlying_value_type =
+      __any_to_underlying_t<__base_value_type>;
+
+    for (; __count > 0 && __first.position() != 0; ++__first, (void)--__count)
+      {
+        if constexpr (_Value)
+          {
+            (*__first).set();
+          }
+        else
+          {
+            (*__first).reset();
+          }
+      }
+    __base_iterator __first_base = ::std::move(__first).base();
+    for (; __count >= __binary_digits_v<__base_value_type>; ++__first_base,
+         (void)(__count -= __binary_digits_v<__base_value_type>))
+      {
+        if constexpr (_Value)
+          {
+            *__first_base = static_cast<__base_value_type>(
+              ::std::numeric_limits<__base_underlying_value_type>::max());
+          }
+        else
+          {
+            *__first_base = static_cast<__base_value_type>(0);
+          }
+      }
+    __first = __iterator(::std::move(__first_base), 0);
+    for (; __count > 0; ++__first, (void)--__count)
+      {
+        if constexpr (_Value)
+          {
+            (*__first).set();
+          }
+        else
+          {
+            (*__first).reset();
+          }
+      }
+    return __first;
+  }
+
+  template<typename _OutputIt, typename _Size, typename _Type>
+  constexpr __bit_iterator<_OutputIt> __bit_fill_n(
+    __bit_iterator<_OutputIt> __first, _Size __count, const _Type& __value)
+  {
+    if (static_cast<bool>(__value))
+      {
+        return __bit_fill_n_value<true>(
+          ::std::move(__first), ::std::move(__count));
+      }
+    else
+      {
+        return __bit_fill_n_value<false>(
+          ::std::move(__first), ::std::move(__count));
+      }
+  }
+
+  _GLIBCXX_END_NAMESPACE_VERSION
+} // namespace __gnu_cxx_GLIBCXX_VISIBILITY(default)
+
+#endif // __cplusplus is on 20/2a or better
+
+#endif
diff --git a/libstdc++-v3/include/ext/bit_ds/bit_algorithm_std.h b/libstdc++-v3/include/ext/bit_ds/bit_algorithm_std.h
new file mode 100644
index 00000000000..d78894bff0e
--- /dev/null
+++ b/libstdc++-v3/include/ext/bit_ds/bit_algorithm_std.h
@@ -0,0 +1,167 @@
+// std algorithm overloads for bit iterators -*- C++ -*-
+
+// Copyright (C) 2019-2019 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// Under Section 7 of GPL version 3, you are granted additional
+// permissions described in the GCC Runtime Library Exception, version
+// 3.1, as published by the Free Software Foundation.
+
+// You should have received a copy of the GNU General Public License and
+// a copy of the GCC Runtime Library Exception along with this program;
+// see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+// <http://www.gnu.org/licenses/>.
+
+/** @file ext/bit_ds/bit_algorithm_std.h
+ *  This file is a GNU extension to the Standard C++ Library.
+ *  It provides overloads to the standard to catch
+ *  these algorithmic improvements without having to
+ *  explicitly access the Bit Datastructure namespace or
+ *  extension name. Considered safe, as this is also done
+ *  for vector_bool implementation-defined iterators in
+ *  a handful of cases.
+ */
+
+#pragma once
+
+#ifndef _EXT_BIT_DS_BIT_ALGORITHM_H
+#define _EXT_BIT_DS_BIT_ALGORITHM_H 1
+
+#if (defined(__cplusplus) && __cplusplus >= 201703L)
+
+#include <ext/bit_ds/bit_iterator.h>
+#include <ext/bit_ds/bit_algorithm.h>
+
+#include <utility>
+
+namespace std _GLIBCXX_VISIBILITY(default)
+{
+  _GLIBCXX_BEGIN_NAMESPACE_VERSION
+
+  template<typename _It, typename _Type>
+  constexpr ::__gnu_cxx::__bit_iterator<_It> find(
+    ::__gnu_cxx::__bit_iterator<_It> __first,
+    ::__gnu_cxx::__bit_iterator<_It> __last, const _Type& __val)
+  {
+    return ::__gnu_cxx::__bit_find(
+      ::std::move(__first), ::std::move(__last), __val);
+  }
+
+  template<typename _InputIt, typename _ForwardIt>
+  constexpr ::__gnu_cxx::__bit_iterator<_InputIt> find_first_of(
+    ::__gnu_cxx::__bit_iterator<_InputIt> __first,
+    ::__gnu_cxx::__bit_iterator<_InputIt> __last, _ForwardIt __search_first,
+    _ForwardIt __search_last)
+  {
+    return ::__gnu_cxx::__bit_find_first_of(::std::move(__first),
+      ::std::move(__last), ::std::move(__search_first),
+      ::std::move(__search_last));
+  }
+
+  template<typename _It0, typename _It1>
+  constexpr bool equal(::__gnu_cxx::__bit_iterator<_It0> __first0,
+    ::__gnu_cxx::__bit_iterator<_It0> __last0,
+    ::__gnu_cxx::__bit_iterator<_It1> __first1,
+    ::__gnu_cxx::__bit_iterator<_It1> __last1)
+  {
+    return ::__gnu_cxx::__bit_equal(::std::move(__first0), ::std::move(__last0),
+      ::std::move(__first1), ::std::move(__last1));
+  }
+
+  template<typename _It0, typename _It1>
+  constexpr bool equal(::__gnu_cxx::__bit_iterator<_It0> __first0,
+    ::__gnu_cxx::__bit_iterator<_It0> __last0,
+    ::__gnu_cxx::__bit_iterator<_It1> __first1)
+  {
+    return ::__gnu_cxx::__bit_equal(
+      ::std::move(__first0), ::std::move(__last0), ::std::move(__first1));
+  }
+
+  template<typename _InputIt0, typename _InputIt1>
+  constexpr bool lexicographical_compare(
+    ::__gnu_cxx::__bit_iterator<_InputIt0> __first0,
+    ::__gnu_cxx::__bit_iterator<_InputIt0> __last0,
+    ::__gnu_cxx::__bit_iterator<_InputIt1> __first1,
+    ::__gnu_cxx::__bit_iterator<_InputIt1> __last1)
+  {
+    return ::__gnu_cxx::__bit_lexicographical_compare(::std::move(__first0),
+      ::std::move(__last0), ::std::move(__first1), ::std::move(__last1));
+  }
+
+  template<typename _It, typename _Type>
+  constexpr typename std::iterator_traits<
+    ::__gnu_cxx::__bit_iterator<_It>>::difference_type
+  count(::__gnu_cxx::__bit_iterator<_It> __first,
+    ::__gnu_cxx::__bit_iterator<_It> __last, const _Type& __value)
+  {
+    return ::__gnu_cxx::__bit_count(
+      ::std::move(__first), ::std::move(__last), __value);
+  }
+
+  template<typename _ForwardIt>
+  constexpr ::__gnu_cxx::__bit_iterator<_ForwardIt> is_sorted_until(
+    ::__gnu_cxx::__bit_iterator<_ForwardIt> __first,
+    ::__gnu_cxx::__bit_iterator<_ForwardIt> __last)
+  {
+    return ::__gnu_cxx::__bit_is_sorted_until(
+      ::std::move(__first), ::std::move(__last));
+  }
+
+  template<typename _ForwardIt>
+  constexpr bool is_sorted(::__gnu_cxx::__bit_iterator<_ForwardIt> __first,
+    ::__gnu_cxx::__bit_iterator<_ForwardIt> __last)
+  {
+    return ::__gnu_cxx::__bit_is_sorted(
+      ::std::move(__first), ::std::move(__last));
+  }
+
+  template<typename _It, typename _OutputIt>
+  constexpr _OutputIt copy(::__gnu_cxx::__bit_iterator<_It> __first,
+    ::__gnu_cxx::__bit_iterator<_It> __last, _OutputIt __out_first)
+  {
+    return ::__gnu_cxx::__bit_copy(
+      ::std::move(__first), ::std::move(__last), ::std::move(__out_first));
+  }
+
+  template<typename _It, typename _Size, typename _OutputIt>
+  constexpr _OutputIt copy_n(::__gnu_cxx::__bit_iterator<_It> __first,
+    _Size __count, _OutputIt __out_first)
+  {
+    return ::__gnu_cxx::__bit_copy_n(
+      ::std::move(__first), __count, ::std::move(__out_first));
+  }
+
+  template<typename _ForwardIt, typename _Type>
+  constexpr ::__gnu_cxx::__bit_iterator<_ForwardIt> fill(
+    ::__gnu_cxx::__bit_iterator<_ForwardIt> __first,
+    ::__gnu_cxx::__bit_iterator<_ForwardIt> __last, const _Type& __value)
+  {
+    return ::__gnu_cxx::__bit_fill(
+      ::std::move(__first), ::std::move(__last), __value);
+  }
+
+  template<typename _OutputIt, typename _Size, typename _Type>
+  constexpr ::__gnu_cxx::__bit_iterator<_OutputIt> fill_n(
+    ::__gnu_cxx::__bit_iterator<_OutputIt> __first, _Size __count,
+    const _Type& __value)
+  {
+    return ::__gnu_cxx::__bit_fill_n(
+      ::std::move(__first), ::std::move(__count), __value);
+  }
+
+  _GLIBCXX_END_NAMESPACE_VERSION
+} // namespace std_GLIBCXX_VISIBILITY(default)
+
+#endif // __cplusplus is on 20/2a or better
+
+#endif
diff --git a/libstdc++-v3/include/ext/bit_ds/bit_iterator.h b/libstdc++-v3/include/ext/bit_ds/bit_iterator.h
new file mode 100644
index 00000000000..2a991109f74
--- /dev/null
+++ b/libstdc++-v3/include/ext/bit_ds/bit_iterator.h
@@ -0,0 +1,1106 @@
+
+// common bit iteration abstraction -*- C++ -*-
+
+// Copyright (C) 2019-2019 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// Under Section 7 of GPL version 3, you are granted additional
+// permissions described in the GCC Runtime Library Exception, version
+// 3.1, as published by the Free Software Foundation.
+
+// You should have received a copy of the GNU General Public License and
+// a copy of the GCC Runtime Library Exception along with this program;
+// see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+// <http://www.gnu.org/licenses/>.
+
+/** @file ext/bit_ds/bit_iterator.h
+ *  This file is a GNU extension to the Standard C++ Library.
+ *  It's goal is to provide basic value, reference, and
+ *  iterator abstractions for the C++ standard library.
+ *  __bit_iterator is the most important class defined here,
+ *  as it provides a unified iterator type for speaking
+ *  with all bit-style data structures. The rest are in
+ *  support of this single wrapping, abstracting
+ *  iterator type.
+ */
+
+#pragma once
+
+#ifndef _EXT_BIT_DS_BIT_ITERATOR_H
+#define _EXT_BIT_DS_BIT_ITERATOR_H 1
+
+#if (defined(__cplusplus) && __cplusplus >= 201703L)
+
+#include <ext/bit_ds/bit_operations.h>
+
+#include <cstddef>
+#include <type_traits>
+#include <cassert>
+#include <limits>
+#include <climits>
+#include <utility>
+#include <iterator>
+
+namespace __gnu_cxx _GLIBCXX_VISIBILITY(default)
+{
+  _GLIBCXX_BEGIN_NAMESPACE_VERSION
+
+  class __bit_value
+  {
+  private:
+    using __mask_type = ::std::size_t;
+
+    bool __bval;
+
+  public:
+    // types
+    using size_type = ::std::size_t;
+
+    // constructors
+    __bit_value() noexcept = default;
+
+    constexpr __bit_value(const __bit_value&) noexcept = default;
+
+    constexpr __bit_value(bool __val) noexcept : __bval(__val)
+    {
+    }
+
+    template<typename _WordRef, typename _Mask>
+    constexpr __bit_value(
+      const __bit_reference<_WordRef, _Mask>& __ref) noexcept
+    : __bval(static_cast<bool>(__ref))
+    {
+    }
+
+    template<typename _WordRef,
+      ::std::enable_if_t<!__is_same_no_cvref_v<_WordRef, __bit_value> &&
+                         !__is_same_no_cvref_v<_WordRef, bool>>* = nullptr>
+    explicit constexpr __bit_value(_WordRef&& __val) noexcept
+    : __bit_value(::std::forward<_WordRef>(__val), 0)
+    {
+    }
+
+    template<typename _WordRef>
+    constexpr __bit_value(_WordRef&& __val, size_type __pos) noexcept
+    : __bval((::std::forward<_WordRef>(__val) &
+               __pos_to_mask<__mask_type>(__pos)) != 0)
+    {
+    }
+
+    // assignment
+    constexpr __bit_value&
+    operator=(const __bit_value&) noexcept = default;
+
+    template<typename _WordRef, typename _Mask>
+    constexpr __bit_value&
+    operator=(const __bit_reference<_WordRef, _Mask>& __ref) noexcept
+    {
+      __bval = static_cast<bool>(__ref);
+      return *this;
+    }
+
+    template<typename _RightWordRef>
+    constexpr __bit_value&
+    assign(_RightWordRef __val) noexcept
+    {
+      assign(__val, 0);
+      return *this;
+    }
+
+    template<typename _RightWordRef>
+    constexpr __bit_value&
+    assign(_RightWordRef __val, size_type __pos) noexcept
+    {
+      __bval = (__val & __pos_to_mask<__mask_type>(__pos)) != 0;
+      return *this;
+    }
+
+    // compound assignment
+    constexpr __bit_value&
+    operator&=(__bit_value __right) noexcept
+    {
+      __bval &= __right.__bval;
+      return *this;
+    }
+
+    constexpr __bit_value&
+    operator|=(__bit_value __right) noexcept
+    {
+      __bval |= __right.__bval;
+      return *this;
+    }
+    constexpr __bit_value&
+    operator^=(__bit_value __right) noexcept
+    {
+      __bval ^= __right.__bval;
+      return *this;
+    }
+
+    // observers
+    constexpr bool
+    value() const noexcept
+    {
+      return __bval;
+    }
+
+    explicit constexpr operator bool() const noexcept
+    {
+      return value();
+    }
+
+    // modifiers
+    constexpr __bit_value&
+    set(bool __val = true) noexcept
+    {
+      __bval = __val;
+      return *this;
+    }
+
+    constexpr __bit_value&
+    reset() noexcept
+    {
+      __bval = false;
+      return *this;
+    }
+
+    constexpr __bit_value&
+    flip() noexcept
+    {
+      __bval = !__bval;
+      return *this;
+    }
+
+    // swap
+    friend void
+    swap(__bit_value& __left, __bit_value& __right) noexcept
+    {
+      __adl_swap(__left.__bval, __right.__bval);
+    }
+
+    friend constexpr bool
+    operator==(const __bit_value& __left, const __bit_value& __right) noexcept
+    {
+      return __left.__bval == __right.__bval;
+    }
+    friend constexpr bool
+    operator!=(const __bit_value& __left, const __bit_value& __right) noexcept
+    {
+      return __left.__bval != __right.__bval;
+    }
+    friend constexpr bool
+    operator<(const __bit_value& __left, const __bit_value& __right) noexcept
+    {
+      return __left.__bval < __right.__bval;
+    }
+    friend constexpr bool
+    operator<=(const __bit_value& __left, const __bit_value& __right) noexcept
+    {
+      return __left.__bval <= __right.__bval;
+    }
+    friend constexpr bool
+    operator>(const __bit_value& __left, const __bit_value& __right) noexcept
+    {
+      return __left.__bval > __right.__bval;
+    }
+    friend constexpr bool
+    operator>=(const __bit_value& __left, const __bit_value& __right) noexcept
+    {
+      return __left.__bval >= __right.__bval;
+    }
+  };
+
+  inline constexpr __bit_value __bit0(0u);
+  inline constexpr __bit_value __bit1(1u);
+
+  template<typename _WordRef, typename _Mask = __bit_mask_type_t<_WordRef>>
+  class __bit_reference
+  {
+  private:
+    template<typename, typename>
+    friend class __bit_reference;
+
+    using __mask_type    = _Mask;
+    using __cv_word_type = ::std::remove_reference_t<__unwrap_t<_WordRef>>;
+    using __word_type    = ::std::remove_cv_t<__cv_word_type>;
+    using __integral_word_type = __any_to_underlying_t<__word_type>;
+
+  public:
+    using value_type = bool;
+    using mask_type  = __mask_type;
+    using size_type  = ::std::size_t;
+
+    // constructors
+    constexpr __bit_reference(bool __val) noexcept = delete;
+
+    constexpr explicit __bit_reference(_WordRef __val) noexcept
+    : __bit_reference(__val, 0)
+    {
+    }
+
+    constexpr __bit_reference(_WordRef __val, size_type __pos) noexcept
+    : _M_word(__val), _M_mask(__pos_to_mask<mask_type>(__pos))
+    {
+    }
+
+    // assignment
+    constexpr __bit_reference&
+    operator=(const __bit_reference& __right) noexcept
+    {
+      return this->set(__right.value());
+    }
+
+    template<typename _RightWordRef, typename _RightMask,
+      ::std::enable_if_t<!::std::is_same_v<_RightWordRef, _WordRef> ||
+                         !::std::is_same_v<_RightMask, _Mask>>* = nullptr>
+    constexpr __bit_reference&
+    operator=(
+      const __bit_reference<_RightWordRef, _RightMask>& __right) noexcept
+    {
+      return this->set(__right.value());
+    }
+
+    constexpr __bit_reference&
+    operator=(__bit_value __val) noexcept
+    {
+      return this->set(__val.value());
+    }
+
+    constexpr __bit_reference&
+    operator=(bool __val) noexcept
+    {
+      return this->set(__val);
+    }
+
+    // compound assignment
+    constexpr __bit_reference&
+    operator&=(__bit_value __right) noexcept
+    {
+      return this->set(value() && __right.value());
+    }
+
+    constexpr __bit_reference&
+    operator|=(__bit_value __right) noexcept
+    {
+      return this->set(value() || __right.value());
+    }
+
+    constexpr __bit_reference&
+    operator^=(__bit_value __right) noexcept
+    {
+      return this->set(value() ^ __right.value());
+    }
+
+    // conversions
+    constexpr operator bool() const noexcept
+    {
+      return this->value();
+    }
+
+    // observers
+    constexpr size_type
+    position() const noexcept
+    {
+      return __mask_to_pos<size_type>(_M_mask);
+    }
+
+    constexpr mask_type
+    mask() const noexcept
+    {
+      return _M_mask;
+    }
+
+    constexpr bool
+    value() const noexcept
+    {
+      return (_M_word & _M_mask) != static_cast<mask_type>(0);
+    }
+
+    constexpr ::std::add_pointer_t<__cv_word_type>
+    address() const noexcept
+    {
+      return std::addressof(this->_M_word);
+    }
+
+    // modifiers
+    constexpr __bit_reference&
+    set(__bit_value __val) noexcept
+    {
+      return this->set(__val.value());
+    }
+
+    constexpr __bit_reference&
+    set(bool __val) noexcept
+    {
+      // must cast to integral type to
+      // use unary minus, otherwise math falls apart
+      // with enums like std::byte!
+      __word_type __bit_val = static_cast<__word_type>(
+        -static_cast<::std::make_signed_t<__word_type>>(
+          __val ? static_cast<__integral_word_type>(1)
+                : static_cast<__integral_word_type>(0)));
+      this->_M_word ^= (__bit_val ^ this->_M_word) & this->_M_mask;
+      return *this;
+    }
+
+    constexpr __bit_reference&
+    set() noexcept
+    {
+      this->_M_word |= this->_M_mask;
+      return *this;
+    }
+
+    constexpr __bit_reference&
+    reset() noexcept
+    {
+      this->_M_word &= ~(this->_M_mask);
+      return *this;
+    }
+
+    constexpr __bit_reference&
+    flip() noexcept
+    {
+      this->_M_word ^= this->_M_mask;
+      return *this;
+    }
+
+    // swap
+    constexpr friend void
+    swap(__bit_reference& __left, __bit_reference& __right) noexcept(
+      ::std::is_nothrow_swappable_v<
+        __word_type>&& ::std::is_nothrow_swappable_v<__mask_type>)
+    {
+      if (__left.value() == __right.value())
+        {
+          return;
+        }
+      __left.flip();
+      __right.flip();
+    }
+
+  private:
+    _WordRef _M_word;
+    mask_type _M_mask;
+  };
+
+  template<typename _Pointer>
+  class __bit_pointer
+  {
+  private:
+    template<typename>
+    friend class __bit_pointer;
+
+    using __base_iterator = __unwrap_t<_Pointer>;
+    using __difference_type =
+      typename ::std::iterator_traits<__base_iterator>::difference_type;
+    using __size_type = ::std::make_unsigned_t<__difference_type>;
+    using __word_type =
+      typename ::std::iterator_traits<__base_iterator>::value_type;
+    using __base_reference =
+      typename ::std::iterator_traits<__base_iterator>::reference;
+
+  public:
+    // types
+    using iterator_type = _Pointer;
+    using value_type    = __bit_value;
+    using reference =
+      __bit_reference<__base_reference, __bit_mask_type_t<__word_type>>;
+    using pointer         = reference*;
+    using size_type       = __size_type;
+    using difference_type = __difference_type;
+
+    // constructors
+    constexpr __bit_pointer() noexcept
+    : _M_base_it(), _M_bit_ref_storage(__dummy_tag())
+    {
+    }
+
+    constexpr __bit_pointer(const __bit_pointer& __right) noexcept
+    : _M_base_it(__right._M_base_it), _M_bit_ref_storage(__right._M_base_it)
+    {
+    }
+
+    constexpr __bit_pointer(__bit_pointer&& __right) noexcept
+    : _M_base_it(::std::move(__right._M_base_it))
+    , _M_bit_ref_storage(::std::move(__right._M_base_it))
+    {
+    }
+
+    template<typename _RightPointer,
+      ::std::enable_if_t<!std::is_same_v<_Pointer, _RightPointer>>* = nullptr>
+    constexpr __bit_pointer(
+      const __bit_pointer<_RightPointer>& __right) noexcept
+    : _M_base_it(static_cast<_Pointer>(__right._M_base_it))
+    , _M_bit_ref_storage(_M_create_storage(
+        this->_M_is_alive(), this->_M_base_it, __right.position()))
+    {
+    }
+
+    constexpr __bit_pointer(::std::nullptr_t) noexcept : __bit_pointer()
+    {
+    }
+
+    explicit constexpr __bit_pointer(iterator_type __pointer) noexcept
+    : __bit_pointer(::std::move(__pointer), 0)
+    {
+    }
+
+    constexpr __bit_pointer(
+      iterator_type __pointer, size_type __position) noexcept
+    : _M_base_it(::std::move(__pointer))
+    , _M_bit_ref_storage(
+        _M_create_storage(this->_M_is_alive(), this->_M_base_it, __position))
+    {
+    }
+
+    // destructor
+    ~__bit_pointer()
+    {
+      this->_M_destroy_if_present();
+    }
+
+    // assignment
+    constexpr __bit_pointer&
+    operator=(const __bit_pointer& __right) noexcept
+    {
+      this->_M_destroy_if_present();
+      this->_M_base_it = __right._M_base_it;
+      this->_M_construct_if_present(__right.position());
+      return *this;
+    }
+
+    constexpr __bit_pointer&
+    operator=(__bit_pointer&& __right) noexcept
+    {
+      this->_M_destroy_if_present();
+      this->_M_base_it = ::std::move(__right._M_base_it);
+      this->_M_construct_if_present(__right.position());
+      return *this;
+    }
+
+    constexpr __bit_pointer& operator=(::std::nullptr_t) noexcept
+    {
+      this->_M_destroy_if_present();
+      this->_M_base_it = _Pointer{};
+      return *this;
+    }
+
+    template<typename _RightPointer,
+      ::std::enable_if_t<!::std::is_same_v<_Pointer, _RightPointer> &&
+                         ::std::is_convertible_v<_RightPointer, _Pointer>>* =
+        nullptr>
+    __bit_pointer&
+    operator=(const __bit_pointer<_RightPointer>& __right) noexcept
+    {
+      this->_M_destroy_if_present();
+      this->_M_base_it = static_cast<_Pointer>(__right._M_base_it);
+      this->_M_construct_if_present(__right.position());
+      return *this;
+    }
+
+    template<typename _RightPointer,
+      ::std::enable_if_t<!::std::is_same_v<_Pointer, _RightPointer> &&
+                         ::std::is_convertible_v<_RightPointer, _Pointer>>* =
+        nullptr>
+    constexpr __bit_pointer&
+    operator=(__bit_pointer<_RightPointer>&& __right) noexcept
+    {
+      this->_M_destroy_if_present();
+      this->_M_base_it = ::std::move(__right._M_base_it);
+      this->_M_construct_if_present(__right.position());
+      return *this;
+    }
+
+    // observers
+    constexpr iterator_type&
+    base() &
+    {
+      return this->_M_base_it;
+    }
+
+    constexpr const iterator_type&
+    base() const&
+    {
+      return this->_M_base_it;
+    }
+
+    constexpr iterator_type&&
+    base() &&
+    {
+      return ::std::move(this->_M_base_it);
+    }
+
+    explicit constexpr operator bool() const noexcept
+    {
+      return this->_M_is_alive();
+    }
+
+    constexpr reference operator*() const noexcept
+    {
+      return this->_M_bit_ref_storage._M_value;
+    }
+
+    constexpr pointer operator->() const noexcept
+    {
+      return std::addressof(
+        const_cast<__bit_pointer*>(this)->_M_bit_ref_storage._M_value);
+    }
+
+    // swap
+    friend constexpr void
+    swap(__bit_pointer& __left, __bit_pointer& __right) noexcept(
+      ::std::is_nothrow_swappable_v<_Pointer>&& ::std::is_nothrow_swappable_v<
+        size_type>)
+    {
+      const bool __left_alive  = __left._M_is_alive();
+      const bool __right_alive = __right._M_is_alive();
+      if (__left_alive && __right_alive)
+        {
+          __adl_swap(__left._M_base_it, __right._M_base_it);
+          __adl_swap(__left._M_bit_ref_storage._M_value,
+            __right._M_bit_ref_storage._M_value);
+        }
+      else if (__left_alive && !__right_alive)
+        {
+          __adl_swap(__left._M_base_it, __right._M_base_it);
+          __right._M_destroy_dummy();
+          __right._M_construct(__left.position());
+          __left._M_destroy();
+        }
+      else if (!__left_alive && __right_alive)
+        {
+          __adl_swap(__left._M_base_it, __right._M_base_it);
+          __left._M_destroy_dummy();
+          __left._M_construct(__right.position());
+          __right._M_destroy();
+        }
+      else
+        {
+          __adl_swap(__left._M_base_it, __right._M_base_it);
+        }
+    }
+
+    // comparison
+    template<typename __RightIt>
+    friend constexpr bool
+    operator==(const __bit_pointer& __left,
+      const __bit_pointer<__RightIt>& __right) noexcept
+    {
+      return __left.base() == __right.base() &&
+             __left.position() == __left.position();
+    }
+
+    template<typename __RightIt>
+    friend constexpr bool
+    operator!=(const __bit_pointer& __left,
+      const __bit_pointer<__RightIt>& __right) noexcept
+    {
+      return __left.base() != __right.base() ||
+             __left.position() != __left.position();
+    }
+
+    template<typename __RightIt>
+    friend constexpr bool
+    operator<(const __bit_pointer& __left,
+      const __bit_pointer<__RightIt>& __right) noexcept
+    {
+      if (__left.base() < __right.base())
+        {
+          return true;
+        }
+      if (__left.base() > __right.base())
+        {
+          return false;
+        }
+      return __left.position() < __left.position();
+    }
+
+    template<typename __RightIt>
+    friend constexpr bool
+    operator<=(const __bit_pointer& __left,
+      const __bit_pointer<__RightIt>& __right) noexcept
+    {
+      if (__left.base() <= __right.base())
+        {
+          return true;
+        }
+      if (__left.base() > __right.base())
+        {
+          return false;
+        }
+      return __left.position() <= __left.position();
+    }
+
+    template<typename __RightIt>
+    friend constexpr bool
+    operator>(const __bit_pointer& __left,
+      const __bit_pointer<__RightIt>& __right) noexcept
+    {
+      if (__left.base() > __right.base())
+        {
+          return true;
+        }
+      if (__left.base() < __right.base())
+        {
+          return false;
+        }
+      return __left.position() > __left.position();
+    }
+
+    template<typename __RightIt>
+    friend constexpr bool
+    operator>=(const __bit_pointer& __left,
+      const __bit_pointer<__RightIt>& __right) noexcept
+    {
+      if (__left.base() >= __right.base())
+        {
+          return true;
+        }
+      if (__left.base() < __right.base())
+        {
+          return false;
+        }
+      return __left.position() >= __left.position();
+    }
+
+  private:
+    // well, this wasn't a good use of my
+    // time figuring out... maybe one day
+    // this stuff will go in the language :B
+    union _Constexpr_storage
+    {
+      char _M_dummy;
+      reference _M_value;
+
+      constexpr _Constexpr_storage(__dummy_tag) noexcept : _M_dummy(){};
+
+      template<typename... _Args>
+      constexpr _Constexpr_storage(_Args&&... __args)
+      : _M_value(::std::forward<_Args>(__args)...)
+      {
+      }
+
+      ~_Constexpr_storage()
+      {
+      }
+    };
+
+    constexpr bool
+    _M_is_alive() const
+    {
+      if constexpr (::std::is_pointer_v<pointer>)
+        {
+          return this->_M_base_it != nullptr;
+        }
+      else
+        {
+          return this->_M_base_it != pointer{};
+        }
+    }
+
+    constexpr void
+    _M_destroy_if_present()
+    {
+      if (this->_M_is_alive())
+        {
+          this->_M_destroy();
+        }
+      else
+        {
+          this->_M_destroy_dummy();
+        }
+    }
+
+    constexpr void
+    _M_destroy()
+    {
+      this->_M_bit_ref_storage._M_value.~reference();
+    }
+
+    constexpr void
+    _M_destroy_dummy()
+    {
+      // nothing to do
+    }
+
+    constexpr void
+    _M_construct_if_present(size_type __position)
+    {
+      if (this->_M_is_alive())
+        {
+          this->_M_construct(__position);
+        }
+    }
+
+    constexpr void
+    _M_construct(size_type __position)
+    {
+      // TODO: wait for new construct_at constexpr magic stuff
+      new (std::addressof(this->_M_bit_ref_storage._M_value))
+        reference(*(this->_M_base_it), __position);
+    }
+
+    static constexpr _Constexpr_storage
+    _M_create_storage(
+      bool __is_alive, iterator_type& __base_it, size_type __position)
+    {
+      if (__is_alive)
+        {
+          return _Constexpr_storage(*__unwrap_ref(__base_it), __position);
+        }
+      else
+        {
+          return _Constexpr_storage(__dummy_tag{});
+        }
+    }
+
+    iterator_type _M_base_it;
+    _Constexpr_storage _M_bit_ref_storage;
+  };
+
+  template<typename _It>
+  class __bit_iterator
+  {
+  private:
+    template<typename>
+    friend class __bit_iterator;
+
+    using __base_iterator = __unwrap_t<_It>;
+    using __pointer = typename ::std::iterator_traits<__base_iterator>::pointer;
+    using __word_type =
+      typename ::std::iterator_traits<__base_iterator>::value_type;
+    using __mask_type = __bit_mask_type_t<__word_type>;
+    using __difference_type =
+      typename ::std::iterator_traits<__base_iterator>::difference_type;
+    using __size_type = ::std::make_unsigned_t<__difference_type>;
+    using __word_ref_type =
+      typename ::std::iterator_traits<__base_iterator>::reference;
+
+  public:
+    using iterator_type = __base_iterator;
+    using iterator_category =
+      typename ::std::iterator_traits<iterator_type>::iterator_category;
+    using value_type      = __bit_value;
+    using pointer         = __bit_pointer<iterator_type>;
+    using reference       = __bit_reference<__word_ref_type, __mask_type>;
+    using size_type       = __size_type;
+    using difference_type = __difference_type;
+
+    // constructors
+    constexpr __bit_iterator() noexcept                      = default;
+    constexpr __bit_iterator(const __bit_iterator&) noexcept = default;
+    constexpr __bit_iterator(__bit_iterator&&) noexcept      = default;
+    explicit constexpr __bit_iterator(iterator_type __i) noexcept
+    : __bit_iterator(::std::move(__i), 0)
+    {
+    }
+    constexpr __bit_iterator(iterator_type __i, size_type __pos) noexcept
+    : _M_base_it(::std::move(__i)), _M_pos(__pos)
+    {
+    }
+
+    template<typename _RightIt,
+      ::std::enable_if_t<!std::is_same_v<_It, _RightIt>>* = nullptr>
+    constexpr __bit_iterator(__bit_iterator<_RightIt>&& __right) noexcept;
+    template<typename _RightIt,
+      ::std::enable_if_t<!std::is_same_v<_It, _RightIt>>* = nullptr>
+    constexpr __bit_iterator(const __bit_iterator<_RightIt>& __right) noexcept;
+
+    // assignment
+    constexpr __bit_iterator&
+    operator=(const __bit_iterator& __right) noexcept = default;
+    constexpr __bit_iterator&
+    operator=(__bit_iterator&& __right) noexcept = default;
+
+    // observers
+    constexpr reference operator*() const noexcept
+    {
+      return reference(*_M_base_it, _M_pos);
+    }
+
+    constexpr pointer operator->() const noexcept
+    {
+      return pointer(_M_base_it, _M_pos);
+    }
+
+    constexpr reference operator[](difference_type n) const
+    {
+      __bit_iterator __shifted = *this + n;
+      return *__shifted;
+    }
+
+    constexpr iterator_type
+    base() const noexcept
+    {
+      return _M_base_it;
+    }
+
+    constexpr size_type
+    position() const noexcept
+    {
+      return _M_pos;
+    }
+
+    constexpr __mask_type
+    mask() const noexcept
+    {
+      return __pos_to_mask<__mask_type>(_M_pos);
+    }
+
+    // arithmetic
+    constexpr __bit_iterator&
+    operator++()
+    {
+      ++_M_pos;
+      if (_M_pos == __binary_digits_v<__word_type>)
+        {
+          _M_pos = 0;
+          ++_M_base_it;
+        }
+
+      return *this;
+    }
+
+    constexpr __bit_iterator&
+    operator--()
+    {
+      if (_M_pos == 0)
+        {
+          _M_pos = __max_binary_index_v<__word_type>;
+          --_M_base_it;
+        }
+      else
+        {
+          --_M_pos;
+        }
+
+      return *this;
+    }
+
+    constexpr __bit_iterator
+    operator++(int)
+    {
+      auto __saved = *this;
+      ++__saved;
+      return __saved;
+    }
+
+    constexpr __bit_iterator
+    operator--(int)
+    {
+      auto __saved = *this;
+      --__saved;
+      return __saved;
+    }
+
+    constexpr __bit_iterator
+    operator+(difference_type __n) const
+    {
+      auto __saved = *this;
+      __saved += __n;
+      return __saved;
+    }
+
+    constexpr __bit_iterator
+    operator-(difference_type __n) const
+    {
+      auto __saved = *this;
+      __saved -= __n;
+      return __saved;
+    }
+
+    constexpr __bit_iterator&
+    operator+=(difference_type __n)
+    {
+      if (__n < 0)
+        {
+          return this->operator-=(-__n);
+        }
+      if (__n == 0)
+        {
+          return *this;
+        }
+      __size_type __bit_advancement = __n % __binary_digits_v<__word_type>;
+      _M_pos += __bit_advancement;
+      if (_M_pos > __binary_digits_v<__word_type>)
+        {
+          // put it back in the proper range
+          _M_pos -= __binary_digits_v<__word_type>;
+          // going forward by one extra since we
+          // overflow binary digit count
+          ::std::advance(_M_base_it, (__n / __binary_digits_v<__word_type>)+1);
+          return *this;
+        }
+
+      ::std::advance(_M_base_it, __n / __binary_digits_v<__word_type>);
+      return *this;
+    }
+
+    constexpr __bit_iterator&
+    operator-=(difference_type __n)
+    {
+      if (__n < 0)
+        {
+          return this->operator+=(-__n);
+        }
+      if (__n == 0)
+        {
+          return *this;
+        }
+      __size_type __bit_advancement    = __n % __binary_digits_v<__word_type>;
+      difference_type __it_advancement = __n / __binary_digits_v<__word_type>;
+      if (__bit_advancement > _M_pos)
+        {
+          // put it back in the proper range
+          _M_pos = __binary_digits_v<__word_type> - __bit_advancement;
+          // going forward by one extra since we
+          // overflow binary digit count
+          ++__it_advancement;
+          ::std::advance(_M_base_it, -__it_advancement);
+          return *this;
+        }
+
+      _M_pos -= __bit_advancement;
+      ::std::advance(_M_base_it,
+        -static_cast<difference_type>(__n / __binary_digits_v<__word_type>));
+      return *this;
+    }
+
+    friend constexpr difference_type
+    operator-(const __bit_iterator& __left, const __bit_iterator& __right)
+    {
+      return (::std::distance(__right._M_base_it, __left._M_base_it) *
+              __binary_digits_v<__word_type>)+(__left._M_pos - __right._M_pos);
+    }
+
+    // comparison
+    template<typename __RightIt>
+    friend constexpr bool
+    operator==(const __bit_iterator& __left,
+      const __bit_iterator<__RightIt>& __right) noexcept
+    {
+      return __left.base() == __right.base() &&
+             __left.position() == __right.position();
+    }
+
+    template<typename __RightIt>
+    friend constexpr bool
+    operator!=(const __bit_iterator& __left,
+      const __bit_iterator<__RightIt>& __right) noexcept
+    {
+      return __left.base() != __right.base() ||
+             __left.position() != __right.position();
+    }
+
+    template<typename __RightIt>
+    friend constexpr bool
+    operator<(const __bit_iterator& __left,
+      const __bit_iterator<__RightIt>& __right) noexcept
+    {
+      if (__left.base() < __right.base())
+        {
+          return true;
+        }
+      if (__left.base() > __right.base())
+        {
+          return false;
+        }
+      return __left.position() < __right.position();
+    }
+
+    template<typename __RightIt>
+    friend constexpr bool
+    operator<=(const __bit_iterator& __left,
+      const __bit_iterator<__RightIt>& __right) noexcept
+    {
+      if (__left.base() <= __right.base())
+        {
+          return true;
+        }
+      if (__left.base() > __right.base())
+        {
+          return false;
+        }
+      return __left.position() <= __right.position();
+    }
+
+    template<typename __RightIt>
+    friend constexpr bool
+    operator>(const __bit_iterator& __left,
+      const __bit_iterator<__RightIt>& __right) noexcept
+    {
+      if (__left.base() > __right.base())
+        {
+          return true;
+        }
+      if (__left.base() < __right.base())
+        {
+          return false;
+        }
+      return __left.position() > __right.position();
+    }
+
+    template<typename __RightIt>
+    friend constexpr bool
+    operator>=(const __bit_iterator& __left,
+      const __bit_iterator<__RightIt>& __right) noexcept
+    {
+      if (__left.base() >= __right.base())
+        {
+          return true;
+        }
+      if (__left.base() < __right.base())
+        {
+          return false;
+        }
+      return __left.position() >= __right.position();
+    }
+
+    // swap
+    friend constexpr void
+    swap(__bit_iterator& __left, __bit_iterator& __right) noexcept(
+      ::std::is_nothrow_swappable_v<
+        iterator_type>&& ::std::is_nothrow_swappable_v<size_type>)
+    {
+      __adl_swap(__left._M_base_it, __right._M_base_it);
+      __adl_swap(__left._M_pos, __right._M_pos);
+    }
+
+  private:
+    iterator_type _M_base_it;
+    size_type _M_pos;
+  };
+
+  template<typename _It>
+  template<typename _RightIt,
+    ::std::enable_if_t<!std::is_same_v<_It, _RightIt>>*>
+  constexpr __bit_iterator<_It>::__bit_iterator(
+    __bit_iterator<_RightIt> && __right) noexcept
+  : __bit_iterator(::std::move(__right).base(), ::std::move(__right).position())
+  {
+  }
+
+  template<typename _It>
+  template<typename _RightIt,
+    ::std::enable_if_t<!std::is_same_v<_It, _RightIt>>*>
+  constexpr __bit_iterator<_It>::__bit_iterator(
+    const __bit_iterator<_RightIt>& __right) noexcept
+  : __bit_iterator(__right.base(), __right.position())
+  {
+  }
+
+  _GLIBCXX_END_NAMESPACE_VERSION
+} // namespace __gnu_cxx_GLIBCXX_VISIBILITY(default)
+
+#endif // __cplusplus is on 20/2a or better
+
+#endif
diff --git a/libstdc++-v3/include/ext/bit_ds/bit_operations.h b/libstdc++-v3/include/ext/bit_ds/bit_operations.h
new file mode 100644
index 00000000000..cc33dbd8e6a
--- /dev/null
+++ b/libstdc++-v3/include/ext/bit_ds/bit_operations.h
@@ -0,0 +1,1465 @@
+
+// Core bit operations -*- C++ -*-
+
+// Copyright (C) 2019-2019 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// Under Section 7 of GPL version 3, you are granted additional
+// permissions described in the GCC Runtime Library Exception, version
+// 3.1, as published by the Free Software Foundation.
+
+// You should have received a copy of the GNU General Public License and
+// a copy of the GCC Runtime Library Exception along with this program;
+// see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+// <http://www.gnu.org/licenses/>.
+
+/** @file ext/bit_ds/bit_operations.h
+ *  This file is a GNU extension to the Standard C++ Library.
+ *  It's goal is to provide low-level, platform-independent operations that
+ *  are usable by the rest of the abstractions in the Bit Data Structures
+ *  library. This includes a few type traits-like checkers,
+ *  some forward declarations, and additional low-level
+ *  utilities for manipulating bits.
+ */
+
+#pragma once
+
+#ifndef _EXT_BIT_DS_BIT_OPERATIONS_H
+#define _EXT_BIT_DS_BIT_OPERATIONS_H 1
+
+#if (defined(__cplusplus) && __cplusplus >= 201703L)
+
+#include <bits/c++config.h>
+
+#include <cstddef>
+#include <cstdint>
+#include <climits>
+#include <iterator>
+#include <type_traits>
+#include <utility>
+#include <version>
+#if defined(__cpp_lib_bitops)
+#include <bit>
+#endif // C++20 Bit Operations
+
+namespace __gnu_cxx _GLIBCXX_VISIBILITY(default)
+{
+  _GLIBCXX_BEGIN_NAMESPACE_VERSION
+
+  // forward declarations
+  class __bit_value;
+  template<typename, typename>
+  class __bit_reference;
+  template<typename>
+  class __bit_pointer;
+  template<typename>
+  class __bit_iterator;
+
+  template<typename>
+  struct __dependent_false : std::false_type
+  {
+  };
+
+  template<typename _Type>
+  inline constexpr bool __dependent_false_v = __dependent_false<_Type>::value;
+
+  template<typename _Type,
+    typename _UType = ::std::remove_cv_t<::std::remove_reference_t<_Type>>>
+  struct __is_code_unit
+  : ::std::integral_constant<bool,
+      ::std::is_same_v<_UType, char> || ::std::is_same_v<_UType, wchar_t> ||
+        ::std::is_same_v<_UType, char16_t> || ::std::is_same_v<_UType, char32_t>
+#if defined(__cpp_char8_t)
+        || ::std::is_same_v<_UType, char8_t>
+#endif
+      >
+  {
+  };
+
+  template<typename _Type>
+  inline constexpr bool __is_code_unit_v = __is_code_unit<_Type>::value;
+
+  template<template<typename...> typename _Op, typename... _Args>
+  using __is_detected =
+    typename ::std::__detector<::std::__nonesuch, void, _Op, _Args...>::value_t;
+
+  template<template<typename...> typename _Op, typename... _Args>
+  using __detected_t =
+    typename ::std::__detector<::std::__nonesuch, void, _Op, _Args...>::type;
+
+  template<class Default, template<typename...> typename _Op, typename... _Args>
+  using __detected_or = ::std::__detector<Default, void, _Op, _Args...>;
+
+  template<template<typename...> typename _Op, typename... _Args>
+  inline constexpr bool __is_detected_v = __is_detected<_Op, _Args...>::value;
+
+  template<typename _Type>
+  using __unwrap = ::std::__inv_unwrap<_Type>;
+
+  template<typename _Type>
+  using __unwrap_t = typename __unwrap<_Type>::type;
+
+  struct __dummy_tag
+  {
+  };
+
+  template<typename _Type, typename = void>
+  class __un_binary_digits
+  {
+  };
+
+  template<typename _Type>
+  class __un_binary_digits<_Type,
+    ::std::enable_if_t<::std::is_integral_v<_Type>>>
+  : public ::std::integral_constant<::std::size_t,
+      ::std::numeric_limits<_Type>::digits>
+  {
+  };
+
+  template<typename _Type>
+  class __un_binary_digits<_Type, ::std::enable_if_t<::std::is_enum_v<_Type>>>
+  : public ::std::integral_constant<::std::size_t,
+      ::std::numeric_limits<::std::underlying_type_t<_Type>>::digits>
+  {
+  };
+
+  template<typename _Type>
+  class __binary_digits
+  : public __un_binary_digits<
+      ::std::remove_cv_t<::std::remove_reference_t<_Type>>>
+  {
+  };
+
+  template<typename _Type>
+  inline constexpr auto __binary_digits_v = __binary_digits<_Type>::value;
+
+  template<typename _Type>
+  inline constexpr auto __max_binary_index_v = __binary_digits_v<_Type> - 1;
+
+  template<typename, typename = void>
+  class __un_bit_mask_type
+  {
+  };
+
+  template<typename _Type>
+  class __un_bit_mask_type<_Type,
+    std::enable_if_t<std::is_integral_v<_Type> || std::is_enum_v<_Type>>>
+  {
+  public:
+    using type = _Type;
+  };
+
+  template<typename _Type>
+  class __bit_mask_type
+  : public __un_bit_mask_type<
+      ::std::remove_cv_t<::std::remove_reference_t<_Type>>>
+  {
+  };
+
+  template<typename T>
+  using __bit_mask_type_t = typename __bit_mask_type<T>::type;
+
+  template<typename _Arg>
+  constexpr decltype(auto) __unwrap_ref(_Arg && __arg)
+  {
+    return static_cast<__unwrap_t<_Arg>>(::std::forward<_Arg>(__arg));
+  }
+
+  template<typename _Container>
+  constexpr decltype(auto) __adl_begin(_Container && __container)
+  {
+    using ::std::begin;
+    return begin(::std::forward<_Container>(__container));
+  }
+
+  template<typename _Container>
+  constexpr decltype(auto) __adl_end(_Container && __container)
+  {
+    using ::std::end;
+    return end(::std::forward<_Container>(__container));
+  }
+
+  template<typename _Container>
+  constexpr decltype(auto) __adl_cbegin(_Container && __container)
+  {
+    using ::std::cbegin;
+    return cbegin(::std::forward<_Container>(__container));
+  }
+
+  template<typename _Container>
+  constexpr decltype(auto) __adl_cend(_Container && __container)
+  {
+    using ::std::cend;
+    return cend(::std::forward<_Container>(__container));
+  }
+
+  template<typename _Container>
+  constexpr decltype(auto) __adl_empty(_Container && __container)
+  {
+    using ::std::empty;
+    return empty(::std::forward<_Container>(__container));
+  }
+
+  template<typename _Container>
+  constexpr decltype(auto) __adl_size(_Container && __container)
+  {
+    using ::std::size;
+    return size(::std::forward<_Container>(__container));
+  }
+
+  template<typename _Left, typename _Right>
+  constexpr void __adl_swap(_Left & __left, _Right & __right)
+  {
+    using ::std::swap;
+    return swap(__left, __right);
+  }
+
+  template<typename _It>
+  struct __is_bit_iterator : ::std::false_type
+  {
+  };
+
+  template<typename _It>
+  struct __is_bit_iterator<__bit_iterator<_It>> : ::std::true_type
+  {
+  };
+
+  template<typename _It>
+  inline constexpr bool __is_bit_iterator_v = __is_bit_iterator<_It>::value;
+
+  template<typename _Target, typename _Actual>
+  using __is_iterator_category_or_better = ::std::is_base_of<_Target, _Actual>;
+
+  template<typename _Target, typename _Actual>
+  inline constexpr bool __is_iterator_category_or_better_v =
+    __is_iterator_category_or_better<_Target, _Actual>::value;
+
+  template<typename _LeftType, typename _RightType>
+  inline constexpr bool __is_same_no_cvref_v =
+    ::std::is_same_v<::std::remove_cv_t<::std::remove_reference_t<_LeftType>>,
+      ::std::remove_cv_t<::std::remove_reference_t<_RightType>>>;
+
+  template<typename _Enumish, typename = void>
+  struct __any_to_underlying
+  {
+    using type = _Enumish;
+  };
+
+  template<typename _Enumish>
+  struct __any_to_underlying<_Enumish,
+    ::std::enable_if_t<::std::is_enum_v<_Enumish>>>
+  {
+    using type = ::std::underlying_type_t<_Enumish>;
+  };
+
+  template<typename _Enumish>
+  using __any_to_underlying_t = typename __any_to_underlying<_Enumish>::type;
+
+  template<typename _Integralish>
+  inline constexpr auto __to_underlying_if_enum(_Integralish __val) noexcept
+  {
+    if constexpr (::std::is_enum_v<_Integralish>)
+      {
+        return static_cast<::std::underlying_type_t<_Integralish>>(__val);
+      }
+    else
+      {
+        return __val;
+      }
+  }
+
+  template<typename _Integralish>
+  inline constexpr auto __to_underlying_if_enum_or_char_t(
+    _Integralish __val) noexcept
+  {
+    if constexpr (::std::is_same_v<_Integralish, char>)
+      {
+        using _UTy = ::std::conditional_t<::std::is_signed_v<char>,
+          ::std::int_least8_t, ::std::uint_least8_t>;
+        return static_cast<_UTy>(__val);
+      }
+    else if constexpr (::std::is_same_v<_Integralish, wchar_t>)
+      {
+        if constexpr (::std::is_signed_v<wchar_t>)
+          {
+            if constexpr (sizeof(wchar_t) <= sizeof(::std::uint_least8_t))
+              {
+                using _UTy = ::std::conditional_t<::std::is_signed_v<wchar_t>,
+                  ::std::int_least8_t, ::std::uint_least8_t>;
+                return static_cast<_UTy>(__val);
+              }
+            else if constexpr (sizeof(wchar_t) <= sizeof(::std::uint_least16_t))
+              {
+                using _UTy = ::std::conditional_t<::std::is_signed_v<wchar_t>,
+                  ::std::int_least16_t, ::std::uint_least16_t>;
+                return static_cast<_UTy>(__val);
+              }
+            else if constexpr (sizeof(wchar_t) <= sizeof(::std::uint_least32_t))
+              {
+                using _UTy = ::std::conditional_t<::std::is_signed_v<wchar_t>,
+                  ::std::int_least32_t, ::std::uint_least32_t>;
+                return static_cast<_UTy>(__val);
+              }
+            else
+              {
+                using _UTy = ::std::conditional_t<::std::is_signed_v<wchar_t>,
+                  ::std::int_least64_t, ::std::uint_least64_t>;
+                return static_cast<_UTy>(__val);
+              }
+          }
+        else
+          {
+            return static_cast<uint_least8_t>(__val);
+          }
+      }
+#if defined(__cpp_char8_t)
+    else if constexpr (::std::is_same_v<_Integralish, char8_t>)
+      {
+        return static_cast<unsigned char>(__val);
+      }
+#endif // char8_t
+    else if constexpr (::std::is_same_v<_Integralish, char16_t>)
+      {
+        return static_cast<uint_least16_t>(__val);
+      }
+    else if constexpr (::std::is_same_v<_Integralish, char32_t>)
+      {
+        return static_cast<uint_least32_t>(__val);
+      }
+    else
+      {
+        return __to_underlying_if_enum(__val);
+      }
+  }
+
+  template<typename _Type>
+  using __has_size_function_test = decltype(::std::declval<_Type&>().size());
+
+  template<typename _Left, typename _Right = _Left>
+  using __equal_to_test =
+    decltype(::std::declval<_Left&>() == ::std::declval<_Right&>());
+
+  template<typename _Left, typename _Right = _Left>
+  using __not_equal_to_test =
+    decltype(::std::declval<_Left&>() != ::std::declval<_Right&>());
+
+  template<typename _Left, typename _Right = _Left>
+  using __less_than_test =
+    decltype(::std::declval<_Left&>() < ::std::declval<_Right&>());
+
+  template<typename _Left, typename _Right = _Left>
+  using __less_equal_to_test =
+    decltype(::std::declval<_Left&>() <= ::std::declval<_Right&>());
+
+  template<typename _Left, typename _Right = _Left>
+  using __greater_than_test =
+    decltype(::std::declval<_Left&>() > ::std::declval<_Right&>());
+
+  template<typename _Left, typename _Right = _Left>
+  using __greater_equal_to_test =
+    decltype(::std::declval<_Left&>() >= ::std::declval<_Right&>());
+
+  template<typename _Container>
+  using __has_value_type_test = decltype(_Container::value_type);
+
+  template<typename _Type>
+  using __has_pair_iterator_insert_test = decltype(
+    ::std::declval<_Type&>().insert(__adl_cbegin(::std::declval<_Type&>()),
+      __adl_cbegin(::std::declval<_Type&>()),
+      __adl_cend(::std::declval<_Type&>())));
+
+  template<typename _Container, typename = void>
+  class __is_bit_container_test : public ::std::false_type
+  {
+  };
+
+  template<typename _Container>
+  class __is_bit_container_test<_Container,
+    ::std::enable_if_t<__is_detected_v<__has_value_type_test, _Container>>>
+  : public ::std::integral_constant<bool,
+      ::std::is_same_v<typename _Container::value_type, __bit_value>>
+  {
+  };
+
+  template<typename _Container>
+  class __is_bit_container
+  : ::std::integral_constant<bool, __is_bit_container_test<_Container>::value>
+  {
+  };
+
+  template<typename _Container>
+  inline constexpr bool __is_bit_container_v =
+    __is_bit_container<_Container>::value;
+
+  template<typename __Iter>
+  using __invoke_iter_as_mutable_test =
+    decltype(__iter_as_mutable(::std::declval<__Iter>()));
+
+  template<typename __Iter>
+  using __is_iter_as_mutable_invokable =
+    __is_detected<__invoke_iter_as_mutable_test, __Iter>;
+
+  template<typename __Iter>
+  inline constexpr bool __is_iter_as_mutable_invokable_v =
+    __is_iter_as_mutable_invokable<__Iter>::value;
+
+  template<typename _FromIt, typename _Container>
+  constexpr auto __iter_as_mutable_from_begin(
+    _FromIt & __from_it, _Container & __source) noexcept
+  {
+    using _ToIt = decltype(__adl_begin(__source));
+
+    if constexpr (::std::is_same_v<
+                    ::std::remove_cv_t<::std::remove_reference_t<_ToIt>>,
+                    _FromIt>)
+      {
+        (void)__source;
+        return _ToIt(__from_it);
+      }
+    else if constexpr (__is_iter_as_mutable_invokable_v<_FromIt&>)
+      {
+        (void)__source;
+        return __iter_as_mutable(__from_it);
+      }
+    else if constexpr (__is_detected_v<__has_pair_iterator_insert_test,
+                         _Container>)
+      {
+        // http://eel.is/c++draft/container.requirements#sequence.reqmts-8
+        // "The iterator returned from a.insert(p, i, j)
+        // points to the copy of the first element inserted into a,
+        // or p if i == j."
+        // in other words, this is our cheat code to avoid
+        // hitting the worst-case-scenario here
+        return __source.insert(
+          __from_it, __adl_cend(__source), __adl_cend(__source));
+      }
+    else if constexpr (::std::is_invocable_r_v<bool, ::std::not_equal_to<>,
+                         _ToIt, _FromIt> &&
+                       (::std::is_same_v<typename ::std::iterator_traits<
+                                           _FromIt>::iterator_category,
+                          ::std::forward_iterator_tag> ||
+                         ::std::is_same_v<typename ::std::iterator_traits<
+                                            _FromIt>::iterator_category,
+                           ::std::bidirectional_iterator_tag>))
+      {
+        // we can avoid 2N walk of iterators
+        // by just moving up by them if they're
+        // comparable to one another
+        auto __begin_it = __adl_begin(__source);
+        while (__begin_it != __from_it)
+          {
+            ++__begin_it;
+          }
+        return __begin_it;
+      }
+    else
+      {
+        // either this is random access and O(1),
+        // or this is some other weird iterator and it's O(2N)
+        auto __begin_it = __adl_begin(__source);
+        auto __it_dist  = ::std::distance(_FromIt(__begin_it), __from_it);
+        std::advance(__begin_it, __it_dist);
+        return __begin_it;
+      }
+  }
+
+  template<typename _FromIt, typename _Container>
+  constexpr auto __iter_as_mutable_from_end(
+    _FromIt & __from_it, _Container & __source) noexcept
+  {
+    using _ToIt = decltype(__adl_end(__source));
+
+    if constexpr (::std::is_same_v<
+                    ::std::remove_cv_t<::std::remove_reference_t<_ToIt>>,
+                    _FromIt>)
+      {
+        (void)__source;
+        return _ToIt(__from_it);
+      }
+    else if constexpr (__is_iter_as_mutable_invokable_v<_FromIt&>)
+      {
+        (void)__source;
+        return __iter_as_mutable(__from_it);
+      }
+    else if constexpr (__is_detected_v<__has_pair_iterator_insert_test,
+                         _Container>)
+      {
+        // http://eel.is/c++draft/container.requirements#sequence.reqmts-8
+        // "The iterator returned from a.insert(p, i, j)
+        // points to the copy of the first element inserted into a,
+        // or p if i == j."
+        // in other words, this is our cheat code to avoid
+        // hitting the worst-case-scenario here
+        return __source.insert(
+          __from_it, __adl_cend(__source), __adl_cend(__source));
+      }
+    else if constexpr (::std::is_invocable_r_v<bool, ::std::not_equal_to<>,
+                         _ToIt, _FromIt> &&
+                       (::std::is_same_v<typename ::std::iterator_traits<
+                                           _FromIt>::iterator_category,
+                         ::std::bidirectional_iterator_tag>))
+      {
+        // we can avoid 2N walk of iterators
+        // by just moving up by them if they're
+        // comparable to one another
+        auto __begin_it = __adl_end(__source);
+        while (__begin_it != __from_it)
+          {
+            --__begin_it;
+          }
+        return __begin_it;
+      }
+    else if constexpr (::std::is_invocable_r_v<bool, ::std::not_equal_to<>,
+                         _ToIt, _FromIt> &&
+                       (::std::is_same_v<typename ::std::iterator_traits<
+                                           _FromIt>::iterator_category,
+                         ::std::forward_iterator_tag>))
+      {
+        // we can avoid 2N walk of iterators
+        // by just moving up by them if they're
+        // comparable to one another
+        auto __begin_it = __adl_begin(__source);
+        while (__begin_it != __from_it)
+          {
+            ++__begin_it;
+          }
+        return __begin_it;
+      }
+    else
+      {
+        // either this is random access and O(1),
+        // or this is some other weird iterator and it's O(2N)
+        auto __end_it  = __adl_end(__source);
+        auto __it_dist = ::std::distance(__from_it, _FromIt(__end_it));
+        std::advance(__end_it, __it_dist);
+        return __end_it;
+      }
+  }
+
+  // the following functions provide
+  // a more complete set of operations
+  // than is provided by the actual <bit>
+  // header, and supports more types too
+  // (e.g., enumerations, character types)
+  // these are fundametnally useful and thus
+  // included here
+
+  template<typename _Integralish>
+  constexpr int __bit_basic_countl_zero(_Integralish __val) noexcept
+  {
+    int __num = 0;
+    for (::std::size_t __bit_index = __binary_digits_v<_Integralish>;
+         __bit_index-- > 0;)
+      {
+        bool __not_is_set =
+          (__val & static_cast<_Integralish>(
+                     static_cast<_Integralish>(1) << __bit_index)) ==
+          static_cast<_Integralish>(0);
+        if (__not_is_set)
+          {
+            __num += 1;
+          }
+        else
+          {
+            break;
+          }
+      }
+    return __num;
+  }
+
+  template<typename _Integralish>
+  constexpr int __bit_basic_countl_one(_Integralish __val) noexcept
+  {
+    int __num = 0;
+    for (::std::size_t __bit_index = __binary_digits_v<_Integralish>;
+         __bit_index-- > 0;)
+      {
+        bool __is_set =
+          (__val & static_cast<_Integralish>(
+                     static_cast<_Integralish>(1) << __bit_index)) !=
+          static_cast<_Integralish>(0);
+        if (__is_set)
+          {
+            __num += 1;
+          }
+        else
+          {
+            break;
+          }
+      }
+    return __num;
+  }
+
+  template<typename _Integralish>
+  constexpr int __bit_basic_countr_zero(_Integralish __val) noexcept
+  {
+    int __num = 0;
+    for (::std::size_t __bit_index = 0;
+         __bit_index < __binary_digits_v<_Integralish>; ++__bit_index)
+      {
+        bool __not_is_set =
+          (__val & static_cast<_Integralish>(
+                     static_cast<_Integralish>(1) << __bit_index)) ==
+          static_cast<_Integralish>(0);
+        if (__not_is_set)
+          {
+            __num += 1;
+          }
+        else
+          {
+            break;
+          }
+      }
+    return __num;
+  }
+
+  template<typename _Integralish>
+  constexpr int __bit_basic_countr_one(_Integralish __val) noexcept
+  {
+    int __num = 0;
+    for (::std::size_t __bit_index = 0;
+         __bit_index < __binary_digits_v<_Integralish>; ++__bit_index)
+      {
+        bool __is_set =
+          (__val & static_cast<_Integralish>(
+                     static_cast<_Integralish>(1) << __bit_index)) !=
+          static_cast<_Integralish>(0);
+        if (__is_set)
+          {
+            __num += 1;
+          }
+        else
+          {
+            break;
+          }
+      }
+    return __num;
+  }
+
+  template<typename _Integralish>
+  constexpr int __bit_basic_firstr_one(_Integralish __val) noexcept
+  {
+    for (::std::size_t __bit_index = 0;
+         __bit_index < __binary_digits_v<_Integralish>; ++__bit_index)
+      {
+        bool __is_set =
+          (__val & static_cast<_Integralish>(
+                     static_cast<_Integralish>(1) << __bit_index)) !=
+          static_cast<_Integralish>(0);
+        if (__is_set)
+          {
+            return static_cast<int>(__bit_index + 1);
+          }
+      }
+    return 0;
+  }
+
+  template<typename _Integralish>
+  constexpr int __bit_basic_firstr_zero(_Integralish __val) noexcept
+  {
+    for (::std::size_t __bit_index = 0;
+         __bit_index < __binary_digits_v<_Integralish>; ++__bit_index)
+      {
+        bool __is_not_set =
+          (__val & static_cast<_Integralish>(
+                     static_cast<_Integralish>(1) << __bit_index)) ==
+          static_cast<_Integralish>(0);
+        if (__is_not_set)
+          {
+            return static_cast<int>(__bit_index + 1);
+          }
+      }
+    return 0;
+  }
+
+  template<typename _Integralish>
+  constexpr int __bit_basic_firstl_one(_Integralish __val) noexcept
+  {
+    for (::std::size_t __bit_index = __binary_digits_v<_Integralish>;
+         __bit_index-- > 0;)
+      {
+        bool __is_set =
+          (__val & static_cast<_Integralish>(
+                     static_cast<_Integralish>(1) << __bit_index)) !=
+          static_cast<_Integralish>(0);
+        if (__is_set)
+          {
+            return static_cast<int>(
+              __binary_digits_v<_Integralish> - __bit_index);
+          }
+      }
+    return 0;
+  }
+
+  template<typename _Integralish>
+  constexpr int __bit_basic_firstl_zero(_Integralish __val) noexcept
+  {
+    for (::std::size_t __bit_index = __binary_digits_v<_Integralish>;
+         __bit_index-- > 0;)
+      {
+        bool __is_not_set =
+          (__val & static_cast<_Integralish>(
+                     static_cast<_Integralish>(1) << __bit_index)) ==
+          static_cast<_Integralish>(0);
+        if (__is_not_set)
+          {
+            return static_cast<int>(__bit_index + 1);
+          }
+        else
+          {
+            break;
+          }
+      }
+    return 0;
+  }
+
+  template<typename _Integralish>
+  constexpr int __bit_basic_popcount(_Integralish __val) noexcept
+  {
+    if constexpr (__binary_digits_v<_Integralish> <= 128)
+      {
+        __val = __val - ((__val >> 1) & (_Integralish) ~(_Integralish)0 / 3);
+        __val = (__val & (_Integralish) ~(_Integralish)0 / 15 * 3) +
+                ((__val >> 2) & (_Integralish) ~(_Integralish)0 / 15 * 3);
+        __val =
+          (__val + (__val >> 4)) & (_Integralish) ~(_Integralish)0 / 255 * 15;
+        return (_Integralish)(
+                 __val * ((_Integralish) ~(_Integralish)0 / 255)) >>
+               (sizeof(_Integralish) - 1) * CHAR_BIT; // count
+      }
+    else
+      {
+        int __num = 0;
+        for (::std::size_t __bit_index = 0;
+             __bit_index < __binary_digits_v<_Integralish>; ++__bit_index)
+          {
+            bool __is_set =
+              (__val & (static_cast<_Integralish>(1) << __bit_index)) !=
+              static_cast<_Integralish>(0);
+            __num += static_cast<int>(__is_set);
+          }
+        return __num;
+      }
+  }
+
+  template<typename _Integralish>
+  constexpr int __bit_unsigned_countl_zero(_Integralish __val) noexcept
+  {
+    int __bit_countl_zero_val;
+#if defined(__cpp_lib_bitops)
+    __bit_countl_zero_val = ::std::countl_zero(__val);
+#elif defined(_MSC_VER)
+#if ITSY_BITSY_MSVC_HAS_ACHIEVED_CONSTEXPR_ENLIGHTENMENT != 0
+    if constexpr (__binary_digits_v<_Integralish> <= 32)
+      {
+        unsigned long __index;
+        auto __scanval = _BitScanReverse(&__index, __val);
+        if (__scanval == 0)
+          {
+            return __binary_digits_v<_Integralish>;
+          }
+        __bit_countl_zero_val = static_cast<int>(__index);
+      }
+#if INTPTR_MAX >= INT64_MAX
+    else if constexpr (__binary_digits_v<_Integralish> <= 64)
+      {
+        unsigned long __index;
+        auto __scanval = _BitScanReverse64(&__index, __val);
+        if (__scanval == 0)
+          {
+            return __binary_digits_v<_Integralish>;
+          }
+        __bit_countl_zero_val = __index);
+      }
+#endif // 64-bit MSVC only
+    else
+      {
+        __bit_countl_zero_val = __bit_basic_countl_zero(__val);
+      }
+#else
+    __bit_countl_zero_val = __bit_basic_countl_zero(__val);
+#endif // MSVC lacks constexpr
+#else
+    if (__val == 0)
+      {
+        (void)__bit_countl_zero_val;
+        return static_cast<int>(__binary_digits_v<_Integralish>);
+      }
+    if constexpr (__binary_digits_v<_Integralish> <=
+                  __binary_digits_v<unsigned int>)
+      {
+        __bit_countl_zero_val =
+          __builtin_clz(__val) -
+          (__binary_digits_v<unsigned int> - __binary_digits_v<_Integralish>);
+      }
+    else if constexpr (__binary_digits_v<_Integralish> <=
+                       __binary_digits_v<unsigned long>)
+      {
+        __bit_countl_zero_val =
+          __builtin_clzl(__val) -
+          (__binary_digits_v<unsigned long> - __binary_digits_v<_Integralish>);
+      }
+    else if constexpr (__binary_digits_v<_Integralish> <=
+                       __binary_digits_v<unsigned long long>)
+      {
+        __bit_countl_zero_val =
+          __builtin_clzll(__val) - (__binary_digits_v<unsigned long long> -
+                                     __binary_digits_v<_Integralish>);
+      }
+    else
+      {
+        __bit_countl_zero_val = __bit_basic_countl_zero(__val);
+      }
+#endif
+    return __bit_countl_zero_val;
+  }
+
+  template<typename _Integralish>
+  constexpr int __bit_unsigned_countl_one(_Integralish __val) noexcept
+  {
+    return __bit_unsigned_countl_zero(static_cast<_Integralish>(~__val));
+  }
+
+  template<typename _Integralish>
+  constexpr int __bit_unsigned_countr_zero(_Integralish __val) noexcept
+  {
+    int __bit_countr_zero_val;
+#if defined(__cpp_lib_bitops)
+    __bit_countr_zero_val = ::std::countr_zero(__val);
+#elif defined(_MSC_VER)
+#if ITSY_BITSY_MSVC_HAS_ACHIEVED_CONSTEXPR_ENLIGHTENMENT
+    if constexpr (__binary_digits_v<_Integralish> <= 32)
+      {
+        unsigned long __index;
+        auto __scanval = _BitScanForward(&__index, __val);
+        if (__scanval == 0)
+          {
+            return __binary_digits_v<_Integralish>;
+          }
+        __bit_countr_zero_val = static_cast<int>(__index);
+      }
+#if INTPTR_MAX >= INT64_MAX
+    else if constexpr (__binary_digits_v<_Integralish> <= 64)
+      {
+        // _BitScanX64 does not exist in 32-bit
+        unsigned long __index;
+        auto __scanval = _BitScanForward64(&__index, __val);
+        if (__scanval == 0)
+          {
+            return __binary_digits_v<_Integralish>;
+          }
+        __bit_countr_zero_val = static_cast<int>(__index);
+      }
+#endif // 64-bit MSVC only
+    else
+      {
+        __bit_countr_zero_val = __bit_basic_countr_zero(__val);
+      }
+#else
+    __bit_countr_zero_val = __bit_basic_countr_zero(__val);
+#endif // MSVC lacks constexpr
+#else
+    if (__val == 0)
+      {
+        (void)__bit_countr_zero_val;
+        return static_cast<int>(__binary_digits_v<_Integralish>);
+      }
+    if constexpr (__binary_digits_v<_Integralish> <=
+                  __binary_digits_v<unsigned int>)
+      {
+        __bit_countr_zero_val = __builtin_ctz(__val);
+      }
+    else if constexpr (__binary_digits_v<_Integralish> <=
+                       __binary_digits_v<unsigned long>)
+      {
+        __bit_countr_zero_val = __builtin_ctzl(__val);
+      }
+    else if constexpr (__binary_digits_v<_Integralish> <=
+                       __binary_digits_v<unsigned long long>)
+      {
+        __bit_countr_zero_val = __builtin_ctzll(__val);
+      }
+    else
+      {
+        __bit_countr_zero_val = __bit_basic_countr_zero(__val);
+      }
+#endif
+    return __bit_countr_zero_val;
+  }
+
+  template<typename _Integralish>
+  constexpr int __bit_unsigned_countr_one(_Integralish __val) noexcept
+  {
+    return __bit_unsigned_countr_zero(static_cast<_Integralish>(~__val));
+  }
+
+  template<typename _Integralish>
+  constexpr int __bit_unsigned_firstr_one(_Integralish __val) noexcept
+  {
+    int __bit_firstr_one_val;
+#if defined(_MSC_VER)
+#if ITSY_BITSY_MSVC_HAS_ACHIEVED_CONSTEXPR_ENLIGHTENMENT
+    if constexpr (__binary_digits_v<_Integralish> <= 32)
+      {
+        unsigned long __index;
+        auto __scanval = _BitScanForward(&__index, __val);
+        if (__scanval == 0)
+          {
+            return 0;
+          }
+        __bit_firstr_one_val = static_cast<int>(__index + 1);
+      }
+#if INTPTR_MAX >= INT64_MAX
+    else if constexpr (__binary_digits_v<_Integralish> <= 64)
+      {
+        unsigned long __index;
+        auto __scanval = _BitScanForward64(&__index, __val);
+        if (__scanval == 0)
+          {
+            return 0;
+          }
+        __bit_firstr_one_val = static_cast<int>(__index + 1);
+      }
+#endif // 64-bit MSVC only
+    else
+      {
+        __bit_firstr_one_val = __bit_basic_firstr_one(__val);
+      }
+#else
+    __bit_firstr_one_val = __bit_basic_firstr_one(__val);
+#endif // MSVC lacks constexpr
+#else
+    if constexpr (__binary_digits_v<_Integralish> <=
+                  __binary_digits_v<unsigned int>)
+      {
+        __bit_firstr_one_val = __builtin_ffs(__val);
+      }
+    else if constexpr (__binary_digits_v<_Integralish> <=
+                       __binary_digits_v<unsigned long>)
+      {
+        __bit_firstr_one_val = __builtin_ffsl(__val);
+      }
+    else if constexpr (__binary_digits_v<_Integralish> <=
+                       __binary_digits_v<unsigned long long>)
+      {
+        __bit_firstr_one_val = __builtin_ffsll(__val);
+      }
+    else
+      {
+        __bit_firstr_one_val = __bit_basic_firstr_one(__val);
+      }
+#endif
+    return __bit_firstr_one_val;
+  }
+
+  template<typename _Integralish>
+  constexpr int __bit_unsigned_firstr_zero(_Integralish __val) noexcept
+  {
+    return __bit_unsigned_firstr_one(static_cast<_Integralish>(~__val));
+  }
+
+  template<typename _Integralish>
+  constexpr int __bit_unsigned_firstl_one(_Integralish __val) noexcept
+  {
+    int __bit_firstl_one_val;
+#if defined(_MSC_VER)
+#if ITSY_BITSY_MSVC_HAS_ACHIEVED_CONSTEXPR_ENLIGHTENMENT
+    if constexpr (__binary_digits_v<_Integralish> <= 32)
+      {
+        unsigned long __index;
+        auto __scanval = _BitScanReverse(&__index, __val);
+        if (__scanval == 0)
+          {
+            return 0;
+          }
+        __bit_firstl_one_val = static_cast<int>(__index);
+      }
+#if INTPTR_MAX >= INT64_MAX
+    else if constexpr (__binary_digits_v<_Integralish> <= 64)
+      {
+        unsigned long __index;
+        auto __scanval = _BitScanReverse64(&__index, __val);
+        if (__scanval == 0)
+          {
+            return 0;
+          }
+        __bit_firstl_one_val = static_cast<int>(__index);
+      }
+#endif // 64-bit MSVC only
+    else
+      {
+        __bit_firstl_one_val = __bit_basic_firstl_one(__val);
+      }
+#else
+    __bit_firstl_one_val = __bit_basic_firstl_one(__val);
+#endif // MSVC lacks constexpr
+#else
+    if (__val == 0)
+      {
+        (void)__bit_firstl_one_val;
+        return static_cast<int>(0);
+      }
+    if constexpr (__binary_digits_v<_Integralish> <=
+                  __binary_digits_v<unsigned int>)
+      {
+        __bit_firstl_one_val =
+          __builtin_clz(__val) + 1 -
+          (__binary_digits_v<unsigned int> - __binary_digits_v<_Integralish>);
+      }
+    else if constexpr (__binary_digits_v<_Integralish> <=
+                       __binary_digits_v<unsigned long>)
+      {
+        __bit_firstl_one_val =
+          __builtin_clzl(__val) + 1 -
+          (__binary_digits_v<unsigned long> - __binary_digits_v<_Integralish>);
+      }
+    else if constexpr (__binary_digits_v<_Integralish> <=
+                       __binary_digits_v<unsigned long long>)
+      {
+        __bit_firstl_one_val = __builtin_clzll(__val) + 1 -
+                               (__binary_digits_v<unsigned long long> -
+                                 __binary_digits_v<_Integralish>);
+      }
+    else
+      {
+        __bit_firstl_one_val = __bit_basic_firstl_one(__val);
+      }
+#endif
+    return __bit_firstl_one_val;
+  }
+
+  template<typename _Integralish>
+  constexpr int __bit_unsigned_firstl_zero(_Integralish __val) noexcept
+  {
+    return __bit_unsigned_firstl_one(static_cast<_Integralish>(~__val));
+  }
+
+  template<typename _Integralish>
+  constexpr int __bit_unsigned_popcount(_Integralish __val) noexcept
+  {
+    int __bit_popcount_val;
+#if defined(__cpp_liBb_bitops)
+    __bit_popcount_val = ::std::popcount(__val);
+#elif defined(_MSC_VER)
+#if defined(ITSY_BITSY_NONPORTABLE_MSVC_INTRINSICS)
+    // WARNING
+    // THESE INSTRUCTIONS ARE NOT PORTABLE
+    // FIXME: REPLACE WITH SOMETHING MORE PORTABLE,
+    // TEST CPUID AND FRIENDS FOR THESE FUNCTIONS,
+    // ETC.
+    if constexpr (__binary_digits_v<_Integralish> <= 16)
+      {
+        __bit_popcount_val = static_cast<int>(__popcnt16(__val));
+      }
+    else if constexpr (__binary_digits_v<_Integralish> <= 32)
+      {
+        __bit_popcount_val = static_cast<int>(__popcnt(__val));
+      }
+    else if constexpr (__binary_digits_v<_Integralish> <= 64)
+      {
+        __bit_popcount_val = static_cast<int>(__popcnt64(__val));
+      }
+    else
+      {
+        __bit_popcount_val = __bit_basic_popcount(__val);
+      }
+#else
+    __bit_popcount_val    = __bit_basic_popcount(__val);
+#endif
+#else
+    if constexpr (__binary_digits_v<_Integralish> <=
+                  __binary_digits_v<unsigned int>)
+      {
+        __bit_popcount_val = __builtin_popcountl(__val);
+      }
+    else if constexpr (__binary_digits_v<_Integralish> <=
+                       __binary_digits_v<unsigned long>)
+      {
+        __bit_popcount_val = __builtin_popcountl(__val);
+      }
+    else if constexpr (__binary_digits_v<_Integralish> <=
+                       __binary_digits_v<unsigned long long>)
+      {
+        __bit_popcount_val = __builtin_popcountll(__val);
+      }
+    else
+      {
+        __bit_popcount_val = __bit_basic_popcount(__val);
+      }
+#endif // Standard C++20 vs. VC++ vs. Others
+    return __bit_popcount_val;
+  }
+
+  template<typename _Integralish>
+  constexpr int __bit_countl_zero(_Integralish __val) noexcept
+  {
+    if constexpr (::std::is_enum_v<_Integralish> ||
+                  __is_code_unit_v<_Integralish>)
+      {
+        return __bit_countl_zero(__to_underlying_if_enum_or_char_t(__val));
+      }
+    else
+      {
+        using _UIntegralish = ::std::make_unsigned_t<_Integralish>;
+        if constexpr (std::is_signed_v<_Integralish>)
+          {
+            // destroy sign bit
+            __val = static_cast<_Integralish>(
+              static_cast<_UIntegralish>(__val) &
+              static_cast<_UIntegralish>(
+                ::std::numeric_limits<_Integralish>::max()));
+          }
+        int __bit_countl_zero_val =
+          __bit_unsigned_countl_zero(static_cast<_UIntegralish>(__val));
+        if constexpr (std::is_signed_v<_Integralish>)
+          {
+            // remove +1 that comes from sign bit
+            --__bit_countl_zero_val;
+          }
+        return __bit_countl_zero_val;
+      }
+  }
+
+  template<typename _Integralish>
+  constexpr int __bit_countl_one(_Integralish __val) noexcept
+  {
+    if constexpr (::std::is_enum_v<_Integralish> ||
+                  __is_code_unit_v<_Integralish>)
+      {
+        return __bit_countl_one(__to_underlying_if_enum_or_char_t(__val));
+      }
+    else
+      {
+        using _UIntegralish = ::std::make_unsigned_t<_Integralish>;
+        if constexpr (std::is_signed_v<_Integralish>)
+          {
+            // force set sign bit
+            __val = static_cast<_Integralish>(
+              static_cast<_UIntegralish>(__val) |
+              (static_cast<_UIntegralish>(1)
+                << __max_binary_index_v<_UIntegralish>));
+          }
+        int __bit_countl_one_val =
+          __bit_unsigned_countl_one(static_cast<_UIntegralish>(__val));
+        if constexpr (std::is_signed_v<_Integralish>)
+          {
+            // remove +1 that comes from sign bit
+            --__bit_countl_one_val;
+          }
+        return __bit_countl_one_val;
+      }
+  }
+
+  template<typename _Integralish>
+  constexpr int __bit_countr_zero(_Integralish __val) noexcept
+  {
+    if constexpr (::std::is_enum_v<_Integralish> ||
+                  __is_code_unit_v<_Integralish>)
+      {
+        return __bit_countr_zero(__to_underlying_if_enum_or_char_t(__val));
+      }
+    else
+      {
+        using _UIntegralish = ::std::make_unsigned_t<_Integralish>;
+        int __bit_countr_zero_val =
+          __bit_unsigned_countr_zero(static_cast<_UIntegralish>(__val));
+        if constexpr (std::is_signed_v<_Integralish>)
+          {
+            if (__bit_countr_zero_val == __binary_digits_v<_UIntegralish>)
+              {
+                return __binary_digits_v<_Integralish>;
+              }
+          }
+        return __bit_countr_zero_val;
+      }
+  }
+
+  template<typename _Integralish>
+  constexpr int __bit_countr_one(_Integralish __val) noexcept
+  {
+    if constexpr (::std::is_enum_v<_Integralish> ||
+                  __is_code_unit_v<_Integralish>)
+      {
+        return __bit_countr_one(__to_underlying_if_enum_or_char_t(__val));
+      }
+    else
+      {
+        using _UIntegralish = ::std::make_unsigned_t<_Integralish>;
+        int __bit_countr_zero_val =
+          __bit_unsigned_countr_one(static_cast<_UIntegralish>(__val));
+        if constexpr (std::is_signed_v<_Integralish>)
+          {
+            if (__bit_countr_zero_val == __binary_digits_v<_UIntegralish>)
+              {
+                return __binary_digits_v<_Integralish>;
+              }
+          }
+        return __bit_countr_zero_val;
+      }
+  }
+
+  template<typename _Integralish>
+  constexpr int __bit_firstr_one(_Integralish __val)
+  {
+    if constexpr (::std::is_enum_v<_Integralish> ||
+                  __is_code_unit_v<_Integralish>)
+      {
+        return __bit_firstr_one(__to_underlying_if_enum_or_char_t(__val));
+      }
+    else
+      {
+        using _UIntegralish = ::std::make_unsigned_t<_Integralish>;
+        int __bit_firstr_one_val =
+          __bit_unsigned_firstr_one(static_cast<_UIntegralish>(__val));
+        if constexpr (std::is_signed_v<_Integralish>)
+          {
+            if (__bit_firstr_one_val == __binary_digits_v<_UIntegralish>)
+              {
+                return 0;
+              }
+          }
+        return __bit_firstr_one_val;
+      }
+  }
+
+  template<typename _Integralish>
+  constexpr int __bit_firstr_zero(_Integralish __val)
+  {
+    if constexpr (::std::is_enum_v<_Integralish> ||
+                  __is_code_unit_v<_Integralish>)
+      {
+        return __bit_firstr_zero(__to_underlying_if_enum_or_char_t(__val));
+      }
+    else
+      {
+        using _UIntegralish = ::std::make_unsigned_t<_Integralish>;
+        int __bit_firstr_zero_val =
+          __bit_unsigned_firstr_zero(static_cast<_UIntegralish>(__val));
+        if constexpr (std::is_signed_v<_Integralish>)
+          {
+            if (__bit_firstr_zero_val == __binary_digits_v<_UIntegralish>)
+              {
+                return 0;
+              }
+          }
+        return __bit_firstr_zero_val;
+      }
+  }
+
+  template<typename _Integralish>
+  constexpr int __bit_firstl_one(_Integralish __val)
+  {
+
+    if constexpr (::std::is_enum_v<_Integralish> ||
+                  __is_code_unit_v<_Integralish>)
+      {
+        return __bit_firstl_one(__to_underlying_if_enum_or_char_t(__val));
+      }
+    else
+      {
+        using _UIntegralish = ::std::make_unsigned_t<_Integralish>;
+        if constexpr (std::is_signed_v<_Integralish>)
+          {
+            // force clear sign bit
+            __val = static_cast<_Integralish>(
+              static_cast<_UIntegralish>(__val) &
+              static_cast<_UIntegralish>(
+                ::std::numeric_limits<_Integralish>::max()));
+          }
+        int __bit_firstl_one_val =
+          __bit_unsigned_firstl_one(static_cast<_UIntegralish>(__val));
+        if constexpr (std::is_signed_v<_Integralish>)
+          {
+            if (__bit_firstl_one_val == 0)
+              {
+                return 0;
+              }
+            --__bit_firstl_one_val;
+          }
+        return __bit_firstl_one_val;
+      }
+  }
+
+  template<typename _Integralish>
+  constexpr int __bit_firstl_zero(_Integralish __val)
+  {
+
+    if constexpr (::std::is_enum_v<_Integralish> ||
+                  __is_code_unit_v<_Integralish>)
+      {
+        return __bit_firstl_zero(__to_underlying_if_enum_or_char_t(__val));
+      }
+    else
+      {
+        using _UIntegralish = ::std::make_unsigned_t<_Integralish>;
+        if constexpr (std::is_signed_v<_Integralish>)
+          {
+            // force set sign bit
+            __val = static_cast<_Integralish>(
+              static_cast<_UIntegralish>(__val) |
+              (static_cast<_UIntegralish>(1)
+                << __max_binary_index_v<_UIntegralish>));
+          }
+        int __bit_firstl_zero_val =
+          __bit_unsigned_firstl_zero(static_cast<_UIntegralish>(__val));
+        if constexpr (std::is_signed_v<_Integralish>)
+          {
+            if (__bit_firstl_zero_val == 0)
+              {
+                return 0;
+              }
+            return __bit_firstl_zero_val - 1;
+          }
+        else
+          {
+            return __bit_firstl_zero_val;
+          }
+      }
+  }
+
+  template<typename _Integralish>
+  constexpr int __bit_popcount(_Integralish __val)
+  {
+    if constexpr (::std::is_enum_v<_Integralish> ||
+                  __is_code_unit_v<_Integralish>)
+      {
+        return __bit_popcount(__to_underlying_if_enum_or_char_t(__val));
+      }
+    else
+      {
+        using _UIntegralish = ::std::make_unsigned_t<_Integralish>;
+        if constexpr (std::is_signed_v<_Integralish>)
+          {
+            // force clear sign bit
+            __val = static_cast<_Integralish>(
+              static_cast<_UIntegralish>(__val) &
+              static_cast<_UIntegralish>(
+                ::std::numeric_limits<_Integralish>::max()));
+          }
+        int __bit_popcount_val =
+          __bit_unsigned_popcount(static_cast<_UIntegralish>(__val));
+        return __bit_popcount_val;
+      }
+  }
+
+  template<typename _Pos, typename _Mask>
+  inline constexpr _Pos __mask_to_pos(_Mask __mask) noexcept
+  {
+    _Pos __pos = static_cast<_Pos>(0);
+    while (__mask != static_cast<_Mask>(0))
+      {
+        ++__pos;
+        __mask >>= 1;
+      }
+    return static_cast<_Pos>(__pos);
+  }
+
+  template<typename _Mask, typename _Pos>
+  inline constexpr _Mask __pos_to_mask(_Pos __pos) noexcept
+  {
+    return static_cast<_Mask>(static_cast<_Mask>(1) << __pos);
+  }
+
+  template<typename _Mask, typename _Pos>
+  inline constexpr _Mask __pos_to_all_1_mask(_Pos __pos) noexcept
+  {
+    _Mask __mask(static_cast<_Mask>(2) << __pos);
+    __mask = static_cast<_Mask>(__to_underlying_if_enum_or_char_t(__mask) - 1);
+    return __mask;
+  }
+
+  template<typename _Word, bool _ShiftLeft, bool _PreserveLeft, typename _Ref,
+    typename _Pos, typename _Shift>
+  inline constexpr void __shift_and_preserve(
+    _Ref & __storage_ref, _Pos __pos_position, _Shift __shift_by)
+  {
+    _Word __preservation      = __storage_ref;
+    _Word __preservation_mask = __pos_to_all_1_mask<_Word>(__pos_position);
+    if constexpr (_PreserveLeft)
+      {
+        __preservation_mask = ~__preservation_mask;
+      }
+    _Word __preservation_complement_mask = ~__preservation_mask;
+
+    __preservation = __preservation & __preservation_mask;
+    if constexpr (_ShiftLeft)
+      {
+        __storage_ref <<= __shift_by;
+      }
+    else
+      {
+        __storage_ref >>= __shift_by;
+      }
+    // restore bits from desired "untouched" section
+    __storage_ref =
+      (__storage_ref & __preservation_complement_mask) | (__preservation);
+  }
+
+  template<typename _Word, typename _Ref, typename _Pos, typename _Shift>
+  inline constexpr void __shift_left_preserve_right(
+    _Ref & __storage_ref, _Pos __pos_position, _Shift __shift_by)
+  {
+    return __shift_and_preserve<_Word, true, false>(
+      __storage_ref, __pos_position, __shift_by);
+  }
+
+  template<typename _Word, typename _Ref, typename _Pos, typename _Shift>
+  inline constexpr void __shift_right_preserve_right(
+    _Ref & __storage_ref, _Pos __pos_position, _Shift __shift_by)
+  {
+    return __shift_and_preserve<_Word, false, false>(
+      __storage_ref, __pos_position, __shift_by);
+  }
+
+  template<typename _Word, typename _Ref, typename _Pos, typename _Shift>
+  inline constexpr void __shift_left_preserve_left(
+    _Ref & __storage_ref, _Pos __pos_position, _Shift __shift_by)
+  {
+    return __shift_and_preserve<_Word, true, true>(
+      __storage_ref, __pos_position, __shift_by);
+  }
+
+  template<typename _Word, typename _Ref, typename _Pos, typename _Shift>
+  inline constexpr void __shift_right_preserve_left(
+    _Ref & __storage_ref, _Pos __pos_position, _Shift __shift_by)
+  {
+    return __shift_and_preserve<_Word, false, true>(
+      __storage_ref, __pos_position, __shift_by);
+  }
+
+  template<typename _Word, typename _Pos>
+  inline constexpr _Word __merge_bits_at(
+    _Word & __lsb, _Word & __msb, _Pos __bit_position)
+  {
+    _Word __lsb_mask = __pos_to_all_1_mask<_Word>(__bit_position);
+    _Word __msb_mask = ~__lsb_mask;
+    return (__lsb & __lsb_mask) | (__msb & __msb_mask);
+  }
+
+  template<typename _Word, typename _Ref, typename _Pos>
+  inline constexpr _Word __replace_most_significant_bits_from(
+    _Ref & __target, _Ref & __donor, _Pos __num_bits)
+  {
+    _Word __donor_give_mask  = __pos_to_all_1_mask<_Word>(__num_bits - 1);
+    _Word __target_keep_mask = (~__donor_give_mask) >> __num_bits;
+    _Pos __at                = __binary_digits_v<_Word> - __num_bits;
+    return (__target & __target_keep_mask) |
+           ((__donor & __donor_give_mask) << __at);
+  }
+
+  _GLIBCXX_END_NAMESPACE_VERSION
+} // namespace __gnu_cxx_GLIBCXX_VISIBILITY(default)
+
+#endif // __cplusplus is on 20/2a or better
+
+#endif
diff --git a/libstdc++-v3/include/ext/bit_ds/bit_sequence.h b/libstdc++-v3/include/ext/bit_ds/bit_sequence.h
new file mode 100644
index 00000000000..08eb495ac46
--- /dev/null
+++ b/libstdc++-v3/include/ext/bit_ds/bit_sequence.h
@@ -0,0 +1,1346 @@
+
+
+// range-alike bit adaptor -*- C++ -*-
+
+// Copyright (C) 2019-2019 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// Under Section 7 of GPL version 3, you are granted additional
+// permissions described in the GCC Runtime Library Exception, version
+// 3.1, as published by the Free Software Foundation.
+
+// You should have received a copy of the GNU General Public License and
+// a copy of the GCC Runtime Library Exception along with this program;
+// see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+// <http://www.gnu.org/licenses/>.
+
+/** @file ext/bit_ds/bit_sequence.h
+ *  This file is a GNU extension to the Standard C++ Library.
+ *  It provides a container adaptor (similar to std::queue)
+ *  that takes a container and adapts it to insert, work
+ *  with, and display bits.
+ */
+
+#pragma once
+
+#ifndef _EXT_BIT_DS_BIT_SEQUENCE_H
+#define _EXT_BIT_DS_BIT_SEQUENCE_H 1
+
+#if (defined(__cplusplus) && __cplusplus >= 201703L)
+
+#include <ext/bit_ds/bit_iterator.h>
+#include <ext/bit_ds/bit_operations.h>
+#include <ext/bit_ds/bit_algorithm.h>
+
+#include <cstddef>
+#include <type_traits>
+#include <iterator>
+#include <utility>
+#include <algorithm>
+
+namespace __gnu_cxx _GLIBCXX_VISIBILITY(default)
+{
+  _GLIBCXX_BEGIN_NAMESPACE_VERSION
+
+  template<typename _Container>
+  class __bit_sequence
+  : private __bit_view<_Container, __word_bit_bounds<_Container>>
+  {
+  private:
+    template<typename, typename>
+    friend class __bit_view;
+
+    using __base_t    = __bit_view<_Container, __word_bit_bounds<_Container>>;
+    using __word_type = typename __base_t::__word_type;
+    using __integral_word_type = typename __base_t::__integral_word_type;
+    using __base_reference     = typename __base_t::__base_reference;
+    using __base_c_reference   = typename __base_t::__base_c_reference;
+    using __base_iterator      = typename __base_t::__base_iterator;
+    using __base_c_iterator    = typename __base_t::__base_c_iterator;
+    using __base_iterator_category =
+      typename __base_t::__base_iterator_category;
+    using __base_c_iterator_category =
+      typename __base_t::__base_c_iterator_category;
+    using __range_ref = typename __base_t::__range_ref;
+
+  public:
+    using difference_type = typename __base_t::difference_type;
+    using size_type       = typename __base_t::size_type;
+    using value_type      = typename __base_t::value_type;
+    using reference       = typename __base_t::reference;
+    using const_reference = typename __base_t::const_reference;
+    // FIXME: also apply iterator concept when applicable
+    using iterator_category = typename __base_t::iterator_category;
+    using pointer           = typename __base_t::pointer;
+    using iterator          = typename __base_t::iterator;
+    using sentinel          = typename __base_t::sentinel;
+    using const_iterator    = typename __base_t::const_iterator;
+    using const_sentinel    = typename __base_t::const_sentinel;
+    using container_type    = typename __base_t::container_type;
+
+    // constructors
+    __bit_sequence() noexcept(noexcept(__base_t()))
+    : __base_t(), _M_bit_pos(__binary_digits_v<__word_type>)
+    {
+    }
+
+    template<typename... _Args>
+    __bit_sequence(::std::in_place_t, _Args&&... __args) noexcept(
+      noexcept(__base_t(::std::forward<_Args>(__args)...)))
+    : __base_t(::std::forward<_Args>(__args)...)
+    , _M_bit_pos(__binary_digits_v<__word_type>)
+    {
+    }
+
+    template<typename _Iterator>
+    __bit_sequence(_Iterator __first, _Iterator __last) noexcept(
+      noexcept(__bit_sequence(
+        __dummy_tag{}, __bit_sequence::_M_efficient_empty_create(
+                         ::std::move(__first), ::std::move(__last)))))
+    : __bit_sequence(
+        __dummy_tag{}, __bit_sequence::_M_efficient_empty_create(
+                         ::std::move(__first), ::std::move(__last)))
+    {
+    }
+
+    __bit_sequence(size_type __num) noexcept(noexcept(__bit_sequence(
+      __dummy_tag{}, __bit_sequence::_M_efficient_empty_create(__num))))
+    : __bit_sequence(
+        __dummy_tag{}, __bit_sequence::_M_efficient_empty_create(__num))
+    {
+    }
+
+    __bit_sequence(size_type __num, value_type __val) noexcept(
+      noexcept(__bit_sequence(__dummy_tag{},
+        __bit_sequence::_M_efficient_empty_create(__num, __val))))
+    : __bit_sequence(
+        __dummy_tag{}, __bit_sequence::_M_efficient_empty_create(__num, __val))
+    {
+    }
+
+    __bit_sequence(::std::initializer_list<value_type> __il) noexcept(
+      noexcept(__bit_sequence(__il.begin(), __il.end())))
+    : __bit_sequence(__il.begin(), __il.end())
+    {
+    }
+
+    __bit_sequence(const __bit_sequence& __right) = default;
+
+    __bit_sequence(__bit_sequence&& __right) = default;
+
+    // assignment
+    __bit_sequence&
+    operator=(const __bit_sequence& __right) = default;
+
+    __bit_sequence&
+    operator=(__bit_sequence&& __right) = default;
+
+    // modifiers
+    __bit_sequence&
+    assign(const __bit_sequence& __right)
+    {
+      return this->operator=(__right);
+    }
+
+    __bit_sequence&
+    assign(__bit_sequence&& __right)
+    {
+      return this->operator=(::std::move(__right));
+    }
+
+    __bit_sequence&
+    assign(::std::initializer_list<value_type> __il)
+    {
+      clear();
+      if (__il.size() == 0)
+        {
+          return *this;
+        }
+      this->_M_empty_assign(__il.begin(), __il.end());
+      return *this;
+    }
+
+    template<typename _Iterator>
+    __bit_sequence&
+    assign(_Iterator __first, _Iterator __last)
+    {
+      clear();
+      if (__first == __last)
+        {
+          return *this;
+        }
+      this->_M_empty_assign(::std::move(__first), ::std::move(__last));
+      return *this;
+    }
+
+    __bit_sequence&
+    assign(size_type __num, value_type __val)
+    {
+      clear();
+      if (__num == static_cast<size_type>(0))
+        {
+          return *this;
+        }
+
+      this->_M_empty_assign(__num, __val);
+      return *this;
+    }
+
+    using __base_t::flip;
+    using __base_t::reset;
+    using __base_t::set;
+
+    void
+    push_back(value_type __val)
+    {
+      using __bit_ref = reference;
+      __base_iterator __storage_it;
+      if (_M_bit_pos == __binary_digits_v<__word_type>)
+        {
+          // FIXME: use optimized push_front of container,
+          // if possible!
+          __storage_it = this->_M_storage_unwrapped().insert(
+            this->_M_storage_cend(), static_cast<__word_type>(0));
+          _M_bit_pos = 0;
+        }
+      else
+        {
+          __storage_it = this->_M_storage_end();
+          --__storage_it;
+        }
+
+      __bit_ref __ref(*__storage_it, _M_bit_pos);
+      __ref = __val;
+
+      ++_M_bit_pos;
+    }
+
+    void
+    push_front(value_type __val)
+    {
+      using __bit_ref = reference;
+      if (_M_bit_pos == __binary_digits_v<__word_type>)
+        {
+          // FIXME: use optimized push_front of container,
+          // if possible!
+          this->_M_storage_unwrapped().insert(
+            this->_M_storage_cend(), static_cast<__word_type>(0));
+          _M_bit_pos = 0;
+        }
+      ++_M_bit_pos;
+
+      auto __storage_first = this->_M_storage_begin();
+      auto __storage_last  = this->_M_storage_end();
+      value_type __old_val = __val;
+      for (; __storage_first != __storage_last; ++__storage_first)
+        {
+          __base_reference __ref = *__storage_first;
+          __bit_ref __front(__ref, 0);
+          __bit_ref __back(__ref, __max_binary_index_v<__word_type>);
+          __old_val = __back;
+          __ref <<= 1;
+          __front = __val;
+          __val   = __old_val;
+        }
+    }
+
+    iterator
+    insert(const_iterator __pos, ::std::initializer_list<value_type> __il)
+    {
+      return this->insert(::std::move(__pos), __il.begin(), __il.end());
+    }
+
+    iterator
+    insert(const_iterator __pos, size_type __num, value_type __val)
+    {
+      if (__num < static_cast<size_type>(1))
+        {
+          __base_iterator __nowhere =
+            this->_M_storage_unwrapped().insert(__pos.base(), __pos.base());
+          return iterator(::std::move(__nowhere), __pos.position());
+        }
+      iterator __current_pos = this->insert(::std::move(__pos), __val);
+      --__num;
+      for (size_type __ni = __num; __ni-- > 0;)
+        {
+          __current_pos = this->insert(::std::move(__current_pos), __val);
+        }
+      return __current_pos;
+    }
+
+    template<typename _Iterator>
+    iterator
+    insert(const_iterator __pos, _Iterator __first, _Iterator __last)
+    {
+      if (__first == __last)
+        {
+          __base_c_iterator __pos_base = ::std::move(__pos).base();
+          __base_iterator __nowhere    = __iter_as_mutable_from_begin(
+            __pos_base, this->_M_storage_unwrapped());
+          return iterator(::std::move(__nowhere), __pos.position());
+        }
+
+      if constexpr (__is_iterator_category_or_better_v<
+                      std::random_access_iterator_tag,
+                      typename ::std::iterator_traits<
+                        _Iterator>::iterator_category>)
+        {
+          return this->_M_source_random_access_insert(
+            ::std::move(__pos), ::std::move(__first), ::std::move(__last));
+        }
+      else
+        {
+          return this->_M_basic_insert(
+            ::std::move(__pos), ::std::move(__first), ::std::move(__last));
+        }
+    }
+
+    iterator
+    insert(const_iterator __pos, value_type __val)
+    {
+      if (this->empty())
+        {
+          push_back(__val);
+          return --this->end();
+        }
+      auto __pos_base_it  = ::std::move(__pos).base();
+      auto __pos_position = ::std::move(__pos).position();
+      auto __storage_last = this->_M_storage_cend();
+      if (__pos.base() == __storage_last)
+        {
+          push_back(__val);
+          return --this->end();
+        }
+      auto __storage_before_last = __storage_last;
+      --__storage_before_last;
+      if (__storage_before_last == __pos_base_it &&
+          __pos_position >= this->_M_bit_pos)
+        {
+          push_back(__val);
+          return --this->end();
+        }
+      if (__pos_base_it == this->_M_storage_cbegin() && __pos_position == 0)
+        {
+          push_front(__val);
+          return this->begin();
+        }
+
+      // okay, we are inserting somewhere in the
+      // middle of the words ...
+      // do we have enough space?
+      if (this->_M_bit_pos == __binary_digits_v<__word_type>)
+        {
+          // we need more space for this
+          // this may also invalidates old iterators,
+          // so we need to re-establish
+          // the position iterator we had...
+          difference_type __saved_dist =
+            ::std::distance(this->_M_storage_cbegin(), __pos_base_it);
+          this->_M_storage_unwrapped().insert(
+            this->_M_storage_cend(), static_cast<__word_type>(0));
+          this->_M_bit_pos = 0;
+          __pos_base_it    = this->_M_storage_cbegin();
+          ::std::advance(__pos_base_it, __saved_dist);
+          __storage_last = this->_M_storage_cend();
+        }
+      __base_iterator __storage_first = this->_M_storage_begin();
+      difference_type __storage_dist =
+        ::std::distance(__base_c_iterator(__storage_first), __pos_base_it);
+      __base_iterator __storage_it =
+        ::std::next(__storage_first, __storage_dist);
+      iterator __insertion_return(__storage_it, __pos_position);
+
+      __base_reference __first_ref = *__storage_it;
+      ++__storage_it;
+      reference __first_insert_target(__first_ref, __pos_position);
+      // save potential off-the-edge value
+      value_type __old_val =
+        reference(__first_ref, __max_binary_index_v<__word_type>);
+
+      // are we not at the MSB edge of a word?
+      if (__pos_position != __max_binary_index_v<__word_type>)
+        {
+          // we are not at the edge of a word
+          // need to shift pertinent values
+          if (__pos_position != 0)
+            {
+              // we are not at the LSB, shift bits
+              __shift_left_preserve_right<__word_type>(
+                __first_ref, __pos_position, 1);
+            }
+          else
+            {
+              __first_ref <<= 1;
+            }
+        }
+      // write new value
+      __first_insert_target = __val;
+
+      for (; __storage_it != __storage_last; ++__storage_it)
+        {
+          __base_reference __storage_current_ref = *__storage_it;
+          value_type __saved =
+            reference(__storage_current_ref, __max_binary_index_v<__word_type>);
+          __storage_current_ref <<= 1;
+          reference(__storage_current_ref, 0) = __old_val;
+          __old_val                           = __saved;
+        }
+
+      ++_M_bit_pos;
+
+      return __insertion_return;
+    }
+
+    void
+    pop_back()
+    {
+      if (this->empty())
+        {
+          return;
+        }
+      --this->_M_bit_pos;
+      if (this->_M_bit_pos == 0)
+        {
+          this->_M_bit_pos = __binary_digits_v<__word_type>;
+          // FIXME: use optimized pop_back of container,
+          // if possible!
+          this->_M_storage_unwrapped().erase(--this->_M_storage_cend());
+        }
+    }
+
+    void
+    pop_front()
+    {
+      if (this->empty())
+        {
+          return;
+        }
+      __base_iterator __storage_first  = this->_M_storage_begin();
+      __base_iterator __storage_last   = this->_M_storage_end();
+      __base_iterator __old_storage_it = __storage_first;
+      (*__old_storage_it) >>= 1;
+      ++__storage_first;
+      for (; __storage_first != __storage_last;
+           ++__storage_first, (void)++__old_storage_it)
+        {
+          __base_reference __storage_ref = *__storage_first;
+          value_type __old_val           = reference(__storage_ref, 0);
+          __storage_ref >>= 1;
+          reference __old_bit_ref(
+            *__old_storage_it, __max_binary_index_v<__word_type>);
+          __old_bit_ref = __old_val;
+        }
+      if (this->_M_bit_pos == 0)
+        {
+          this->_M_bit_pos = __binary_digits_v<__word_type>;
+          // FIXME: use optimized pop_front of container,
+          // if possible!
+          this->_M_storage_unwrapped().erase(--this->_M_storage_cend());
+        }
+      --this->_M_bit_pos;
+    }
+
+    constexpr iterator
+    erase(const_iterator __first, const_iterator __last) noexcept
+    {
+      if (__first == __last)
+        {
+          __base_iterator __nowhere =
+            this->_M_storage_unwrapped().erase(__first.base(), __first.base());
+          return iterator(::std::move(__nowhere), __first.position());
+        }
+      if (this->empty())
+        {
+          return this->end();
+        }
+      if (__first == this->cbegin() && __last == this->cend())
+        {
+          clear();
+          return this->end();
+        }
+      // if this is a random access iterator,
+      // then size computation is cheap
+      // and so is bulk, sized removal
+      if constexpr (__is_iterator_category_or_better_v<
+                      std::random_access_iterator_tag, iterator_category>)
+        {
+          return this->_M_this_random_access_erase(
+            ::std::move(__first), ::std::move(__last));
+        }
+      else
+        {
+          return this->_M_basic_erase(
+            ::std::move(__first), ::std::move(__last));
+        }
+    }
+
+    constexpr iterator
+    erase(const_iterator __pos) noexcept
+    {
+      if (this->empty())
+        {
+          return this->end();
+        }
+      auto __pos_base_it  = ::std::move(__pos).base();
+      auto __pos_position = ::std::move(__pos).position();
+      auto __storage_last = this->_M_storage_cend();
+      if (__pos_base_it == __storage_last)
+        {
+          return this->end();
+        }
+      --__storage_last;
+      if (__storage_last == __pos_base_it)
+        {
+          if (__pos_position >= this->_M_bit_pos)
+            {
+              pop_back();
+              return this->end();
+            }
+          else if (this->_M_bit_pos - 1 == __pos_position)
+            {
+              this->pop_back();
+              return this->end();
+            }
+        }
+      if (__pos_base_it == this->_M_storage_cbegin() && __pos_position == 0)
+        {
+          this->pop_front();
+          return this->begin();
+        }
+      // okay, we actually have to remove old bits now...
+      __base_iterator __storage_first = this->_M_storage_begin();
+      difference_type __storage_dist =
+        ::std::distance(__base_c_iterator(__storage_first), __pos_base_it);
+      __base_iterator __storage_it =
+        ::std::next(__storage_first, __storage_dist);
+
+      // put __storage_last back to
+      // the end iterator
+      ++__storage_last;
+
+      // save old bits that will be affected by left shift
+      __base_reference __storage_ref = *__storage_it;
+      if (__pos_position == 0)
+        {
+          // no old bits matter: just truncate at the desired position
+          __storage_ref >>= 1;
+        }
+      else
+        {
+          // sigh... old bits do matter, save, truncate, then restore old bits
+          __shift_right_preserve_right<__word_type>(
+            __storage_ref, __pos_position - 1, 1);
+        }
+
+      // great, now shift literally everything else indiscriminately
+      auto __old_storage_it  = __storage_it;
+      auto __curr_storage_it = __storage_it;
+      ++__curr_storage_it;
+      for (; __curr_storage_it != __storage_last;
+           ++__curr_storage_it, (void)++__old_storage_it)
+        {
+          // get current iterator's position
+          __base_reference __curr_pos_ref = *__curr_storage_it;
+          // get least significant bit that is going to
+          // be shift-truncated
+          value_type __old_val = reference(__curr_pos_ref, 0);
+          // assign it to the MSB of the old word
+          reference(*__old_storage_it, __max_binary_index_v<__word_type>) =
+            __old_val;
+          // shift over
+          __curr_pos_ref >>= 1;
+        }
+
+      // did we chop off an old word?
+      if (_M_bit_pos == 0)
+        {
+          this->_M_bit_pos = __binary_digits_v<__word_type> - 1;
+          // destroy it
+          --__storage_last;
+          bool __storage_last_is_current = __storage_it == __storage_last;
+          auto __removed_storage_it =
+            this->_M_storage_unwrapped().erase(__storage_last);
+          if (__storage_last_is_current)
+            {
+              // the storage we had was removed, we need to return
+              // that iterator itself
+              // otherwise we have invalidation issues!
+              return iterator(
+                ::std::move(--__removed_storage_it), __pos_position);
+            }
+        }
+      else
+        {
+          // no, so just decrement and
+          // pretend higher bits don't exist
+          --_M_bit_pos;
+        }
+      return iterator(::std::move(__storage_it), __pos_position);
+    }
+
+    constexpr void
+    clear() noexcept
+    {
+      this->_M_bit_pos = __binary_digits_v<__word_type>;
+      this->_M_storage_unwrapped().clear();
+    }
+
+    constexpr void
+    swap(__bit_sequence& __right) noexcept(
+      ::std::is_nothrow_swappable_v<container_type>)
+    {
+      __adl_swap(this->_M_storage_unwrapped(), __right._M_storage);
+      __adl_swap(this->_M_bit_pos, __right._M_bit_pos);
+    }
+
+    // observers
+    using __base_t::all;
+    using __base_t::any;
+    using __base_t::count;
+    using __base_t::none;
+    using __base_t::one_count;
+    using __base_t::popcount;
+    using __base_t::test;
+    using __base_t::zero_count;
+
+    using __base_t::operator[];
+
+    bool
+    empty() const
+    {
+      return __adl_empty(this->_M_storage_unwrapped());
+    }
+
+    reference
+    back() noexcept
+    {
+      auto __back_it = this->end();
+      --__back_it;
+      return *(__back_it);
+    }
+
+    const_reference
+    back() const noexcept
+    {
+      auto __back_it = this->cend();
+      --__back_it;
+      return *(__back_it);
+    }
+
+    reference
+    front() noexcept
+    {
+      __base_reference __storage_ref = *this->_M_storage_begin();
+      return reference(__storage_ref, 0);
+    }
+
+    const_reference
+    front() const noexcept
+    {
+      __base_c_reference __storage_ref = *this->_M_storage_cbegin();
+      return const_reference(__storage_ref, 0);
+    }
+
+    std::add_lvalue_reference_t<_Container>
+    base() noexcept
+    {
+      return this->_M_storage_unwrapped();
+    }
+
+    std::add_const_t<std::add_lvalue_reference_t<_Container>>
+    base() const noexcept
+    {
+      return this->_M_storage_unwrapped();
+    }
+
+    constexpr size_type
+    size() const noexcept
+    {
+      size_type __word_size = __adl_size(this->_M_storage_unwrapped());
+      if (__word_size == 0)
+        {
+          return 0;
+        }
+      return (__word_size - 1) * __binary_digits_v<__word_type> +
+             this->_M_bit_pos;
+    }
+
+    constexpr iterator
+    begin() noexcept
+    {
+      return iterator(this->_M_storage_begin(), 0);
+    }
+
+    constexpr sentinel
+    end() noexcept
+    {
+      auto __storage_last = this->_M_storage_end();
+      if (this->_M_bit_pos < __binary_digits_v<__word_type>)
+        {
+          --__storage_last;
+          return sentinel(::std::move(__storage_last), this->_M_bit_pos);
+        }
+      return sentinel(::std::move(__storage_last), 0);
+    }
+
+    constexpr const_iterator
+    begin() const noexcept
+    {
+      return this->cbegin();
+    }
+
+    constexpr const_sentinel
+    end() const noexcept
+    {
+      return this->cend();
+    }
+
+    constexpr const_iterator
+    cbegin() const noexcept
+    {
+      return const_iterator(this->_M_storage_begin(), 0);
+    }
+
+    constexpr const_sentinel
+    cend() const noexcept
+    {
+      auto __storage_last = this->_M_storage_cend();
+      if (this->_M_bit_pos < __binary_digits_v<__word_type>)
+        {
+          --__storage_last;
+          return const_sentinel(::std::move(__storage_last), this->_M_bit_pos);
+        }
+      return const_sentinel(::std::move(__storage_last), 0);
+    }
+
+    template<typename _RightContainer>
+    friend constexpr bool
+    operator==(const __bit_sequence& __left,
+      const __bit_sequence<_RightContainer>& __right)
+    {
+      using _Left  = __bit_sequence;
+      using _Right = __bit_sequence<_RightContainer>;
+
+      if (__left._M_bit_pos == __binary_digits_v<typename _Left::__word_type> &&
+          __right._M_bit_pos == __binary_digits_v<typename _Right::__word_type>)
+        {
+          return static_cast<const typename _Left::__base_t&>(__left) ==
+                 static_cast<const typename _Right::__base_t&>(__right);
+        }
+      auto __left_size  = __left.size();
+      auto __right_size = __right.size();
+      if (__left_size != __right_size)
+        {
+          return false;
+        }
+      else
+        {
+          return ::std::equal(__left.cbegin(), __left.cend(), __right.cbegin(),
+            __right.cend(), ::std::equal_to<value_type>());
+        }
+    }
+
+    template<typename _RightContainer>
+    friend constexpr bool
+    operator!=(const __bit_sequence& __left,
+      const __bit_sequence<_RightContainer>& __right)
+    {
+      using _Left  = __bit_sequence;
+      using _Right = __bit_sequence<_RightContainer>;
+
+      if (__left._M_bit_pos == __binary_digits_v<typename _Left::__word_type> &&
+          __right._M_bit_pos == __binary_digits_v<typename _Right::__word_type>)
+        {
+          return static_cast<const typename _Left::__base_t&>(__left) !=
+                 static_cast<const typename _Right::__base_t&>(__right);
+        }
+      auto __left_size  = __left.size();
+      auto __right_size = __right.size();
+      if (__left_size != __right_size)
+        {
+          return true;
+        }
+      else
+        {
+          return !::std::equal(__left.cbegin(), __left.cend(), __right.cbegin(),
+            __right.cend(), ::std::equal_to<bool>());
+        }
+    }
+
+    template<typename _RightContainer>
+    friend constexpr bool
+    operator<(const __bit_sequence& __left,
+      const __bit_sequence<_RightContainer>& __right)
+    {
+      using _Left  = __bit_sequence;
+      using _Right = __bit_sequence<_RightContainer>;
+
+      if (__left._M_bit_pos == __binary_digits_v<typename _Left::__word_type> &&
+          __right._M_bit_pos == __binary_digits_v<typename _Right::__word_type>)
+        {
+          return static_cast<const typename _Left::__base_t&>(__left) <
+                 static_cast<const typename _Right::__base_t&>(__right);
+        }
+      return ::std::lexicographical_compare(__left.cbegin(), __left.cend(),
+        __right.cbegin(), __right.cend(), ::std::less<bool>());
+    }
+
+    template<typename _RightContainer>
+    friend constexpr bool
+    operator<=(const __bit_sequence& __left,
+      const __bit_sequence<_RightContainer>& __right)
+    {
+      using _Left  = __bit_sequence;
+      using _Right = __bit_sequence<_RightContainer>;
+
+      if (__left._M_bit_pos == __binary_digits_v<typename _Left::__word_type> &&
+          __right._M_bit_pos == __binary_digits_v<typename _Right::__word_type>)
+        {
+          return static_cast<const typename _Left::__base_t&>(__left) <=
+                 static_cast<const typename _Right::__base_t&>(__right);
+        }
+
+      return !::std::lexicographical_compare(__left.cbegin(), __left.cend(),
+        __right.cbegin(), __right.cend(), ::std::greater<bool>());
+    }
+
+    template<typename _RightContainer>
+    friend constexpr bool
+    operator>(const __bit_sequence& __left,
+      const __bit_sequence<_RightContainer>& __right)
+    {
+      using _Left  = __bit_sequence;
+      using _Right = __bit_sequence<_RightContainer>;
+
+      if (__left._M_bit_pos == __binary_digits_v<typename _Left::__word_type> &&
+          __right._M_bit_pos == __binary_digits_v<typename _Right::__word_type>)
+        {
+          return static_cast<const typename _Left::__base_t&>(__left) >
+                 static_cast<const typename _Right::__base_t&>(__right);
+        }
+      return ::std::lexicographical_compare(__left.cbegin(), __left.cend(),
+        __right.cbegin(), __right.cend(), ::std::greater<bool>());
+    }
+
+    template<typename _RightContainer>
+    friend constexpr bool
+    operator>=(const __bit_sequence& __left,
+      const __bit_sequence<_RightContainer>& __right)
+    {
+      using _Left  = __bit_sequence;
+      using _Right = __bit_sequence<_RightContainer>;
+
+      if (__left._M_bit_pos == __binary_digits_v<typename _Left::__word_type> &&
+          __right._M_bit_pos == __binary_digits_v<typename _Right::__word_type>)
+        {
+          return static_cast<const typename _Left::__base_t&>(__left) >=
+                 static_cast<const typename _Right::__base_t&>(__right);
+        }
+
+      return !::std::lexicographical_compare(__left.cbegin(), __left.cend(),
+        __right.cbegin(), __right.cend(), ::std::less<bool>());
+    }
+
+  private:
+    size_type _M_bit_pos = 0;
+
+    __bit_sequence(__dummy_tag,
+      ::std::pair<container_type, size_type>
+        __container_position) noexcept(noexcept(__base_t(::std::
+        move(__container_position.first))))
+    : __base_t(::std::move(__container_position.first))
+    , _M_bit_pos(__container_position.second)
+    {
+      // avoids inefficiencies by using a static method to create needed data
+      // and delegating to some internal constructor which can properly init the
+      // data C++ needs a better constructor story, or we'll keep having spammy
+      // constructor delegation like this for all eternity... but what do I
+      // know? I'm just a GSoCer. c:
+    }
+
+    template<typename _Iterator>
+    static constexpr void
+    _M_efficient_empty_assign_into(_Iterator __first, _Iterator __last,
+      __range_ref& __storage, size_type& __bit_pos)
+    {
+      // welp...
+      // it's bulk, so only medium slow
+      // instead of slow-slow?
+      size_type __bit_counter        = 0;
+      size_type __modulo_bit_counter = 0;
+      __base_iterator __storage_it =
+        __storage.insert(__adl_cend(__storage), static_cast<__word_type>(0));
+      iterator __it(::std::move(__storage_it), 0);
+      for (; __first != __last; ++__first, (void)++__bit_counter,
+           (void)++__modulo_bit_counter, (void)++__it)
+        {
+          if (__modulo_bit_counter == __binary_digits_v<__word_type>)
+            {
+              __base_iterator __storage_it = __storage.insert(
+                __adl_cend(__storage), static_cast<__word_type>(0));
+              __it                 = iterator(::std::move(__storage_it), 0);
+              __modulo_bit_counter = 0;
+            }
+          *__it = *__first;
+        }
+      __bit_pos = __modulo_bit_counter;
+    }
+
+    static constexpr void
+    _M_empty_assign_into(size_type __num, value_type __val,
+      __range_ref& __storage, size_type& __bit_pos)
+    {
+      size_type __word_insertion = (__num / __binary_digits_v<__word_type>);
+      __bit_pos                  = (__num % __binary_digits_v<__word_type>);
+      if (__bit_pos == 0)
+        {
+          __bit_pos = __binary_digits_v<__word_type>;
+        }
+      else
+        {
+          ++__word_insertion;
+        }
+
+      __storage.assign(__word_insertion,
+        __val ? static_cast<__word_type>(
+                  ::std::numeric_limits<__integral_word_type>::max())
+              : static_cast<__word_type>(0));
+    }
+
+    template<typename _Iterator>
+    constexpr void
+    _M_empty_assign(_Iterator __first, _Iterator __last)
+    {
+      decltype(auto) __storage = this->_M_storage_unwrapped();
+      _M_efficient_empty_assign_into(
+        ::std::move(__first), ::std::move(__last), __storage);
+    }
+
+    constexpr void
+    _M_empty_assign(size_type __num, value_type __val)
+    {
+      decltype(auto) __storage = this->_M_storage_unwrapped();
+      _M_empty_assign_into(__num, __val, __storage);
+    }
+
+    template<typename _Iterator>
+    static constexpr ::std::pair<container_type, size_type>
+    _M_efficient_empty_create(_Iterator __first, _Iterator __last)
+    {
+      if (__first == __last)
+        {
+          return { container_type(),
+            static_cast<size_type>(__binary_digits_v<__word_type>) };
+        }
+
+      if constexpr (__is_iterator_category_or_better_v<
+                      std::random_access_iterator_tag,
+                      typename ::std::iterator_traits<
+                        _Iterator>::iterator_category>)
+        {
+          size_type __num            = ::std::distance(__first, __last);
+          size_type __word_insertion = (__num / __binary_digits_v<__word_type>);
+          size_type __bit_pos        = (__num % __binary_digits_v<__word_type>);
+          if (__bit_pos == 0)
+            {
+              __bit_pos = __binary_digits_v<__word_type>;
+            }
+          else
+            {
+              ++__word_insertion;
+            }
+
+
+          container_type __storage(
+            __word_insertion, static_cast<__word_type>(0));
+          __base_iterator __storage_it = __storage.begin();
+          iterator __copy_it(::std::move(__storage_it), 0);
+          ::std::copy_n(__first, __num, __copy_it);
+          return { ::std::move(__storage), __bit_pos };
+        }
+      else
+        {
+          container_type __storage;
+          size_type __bit_pos;
+          _M_efficient_empty_assign_into(
+            ::std::move(__first), ::std::move(__last), __storage, __bit_pos);
+          return { ::std::move(__storage), __bit_pos };
+        }
+    }
+
+    static constexpr ::std::pair<container_type, size_type>
+    _M_efficient_empty_create(size_type __num, value_type __val)
+    {
+      if (__num < 1)
+        {
+          return { container_type(),
+            static_cast<size_type>(__binary_digits_v<__word_type>) };
+        }
+      size_type __word_insertion = (__num / __binary_digits_v<__word_type>);
+      size_type __bit_pos        = (__num % __binary_digits_v<__word_type>);
+      if (__bit_pos == 0)
+        {
+          __bit_pos = __binary_digits_v<__word_type>;
+        }
+      else
+        {
+          ++__word_insertion;
+        }
+
+
+      container_type __storage(__word_insertion,
+        __val ? static_cast<__word_type>(
+                  ::std::numeric_limits<__integral_word_type>::max())
+              : static_cast<__word_type>(0));
+      return { ::std::move(__storage), __bit_pos };
+    }
+
+    static constexpr ::std::pair<container_type, size_type>
+    _M_efficient_empty_create(size_type __num)
+    {
+      return _M_efficient_empty_create(__num, static_cast<value_type>(false));
+    }
+
+    template<typename _Iterator>
+    constexpr iterator
+    _M_source_random_access_insert(
+      const_iterator __pos, _Iterator __first, _Iterator __last)
+    {
+      if constexpr (__is_iterator_category_or_better_v<
+                      std::random_access_iterator_tag, iterator_category>)
+        {
+          difference_type __insert_bit_count = ::std::distance(__first, __last);
+          return this->_M_this_and_source_random_access_insert(
+            __insert_bit_count, ::std::move(__pos), ::std::move(__first),
+            ::std::move(__last));
+        }
+      else
+        {
+          return this->_M_basic_insert(
+            ::std::move(__pos), ::std::move(__first), ::std::move(__last));
+        }
+    }
+
+    template<typename _Iterator>
+    constexpr iterator
+    _M_this_and_source_random_access_insert(difference_type __insert_bit_count,
+      const_iterator __pos, _Iterator __first, _Iterator __last)
+    {
+      size_type __pos_position   = __pos.position();
+      difference_type __pos_dist = __pos - this->cbegin();
+      if (__pos_position == 0)
+        {
+          // we can copy literally everything
+          // without individual bit management
+          __base_c_iterator __pos_base_it = ::std::move(__pos).base();
+          difference_type __insert_word_count =
+            __insert_bit_count / __binary_digits_v<__word_type>;
+          difference_type __insert_bit_shift =
+            __insert_bit_count % __binary_digits_v<__word_type>;
+          iterator __shift_insertion_target = this->_M_copy_words_if_necessary(
+            __insert_word_count, __pos_dist, __pos_base_it, __first);
+          if (__insert_bit_shift > 0)
+            {
+              this->_M_basic_insert(__shift_insertion_target, __first, __last);
+            }
+          iterator __ret = this->begin();
+          __ret += __pos_dist;
+          return __ret;
+        }
+      // okay now we're back to the boring implementation...
+      // first, shove in as many bits until we get to
+      // a word boundary using basic insert
+
+      // FIXME: optimize basic less-than-word bulk insertions
+      difference_type __bits_to_boundary =
+        __binary_digits_v<__word_type> - __pos_position;
+      if (__bits_to_boundary >= __insert_bit_count)
+        {
+          _Iterator __boundary_last = __first;
+          __boundary_last += __insert_bit_count;
+          return this->_M_basic_insert(::std::move(__pos), ::std::move(__first),
+            ::std::move(__boundary_last));
+        }
+      iterator __boundary_it = this->_M_basic_insert(
+        ::std::move(__pos), __first, __first + __bits_to_boundary);
+      __base_iterator __boundary_base_it = ::std::move(__boundary_it).base();
+      ++__boundary_base_it;
+
+      // now insert and copy words, which require no shifts at all
+      difference_type __leftover_bits = __insert_bit_count - __bits_to_boundary;
+      difference_type __leftover_words =
+        __leftover_bits / __binary_digits_v<__word_type>;
+      difference_type __leftover_words_bits =
+        __leftover_words * __binary_digits_v<__word_type>;
+      __base_iterator __insertion_point = this->_M_storage_unwrapped().insert(
+        ::std::move(__boundary_base_it),
+        static_cast<size_type>(__leftover_words), static_cast<__word_type>(0));
+      __first += __bits_to_boundary;
+      iterator __post_word_it = ::std::copy_n(
+        __first, __leftover_words_bits, iterator(__insertion_point, 0));
+
+      // finally, handle the last bits...
+      // FIXME: handle bulk less-than-word insertions
+      __leftover_bits -= __leftover_words_bits;
+      if (__leftover_bits > 0)
+        {
+          __first += __leftover_words_bits;
+          this->_M_basic_insert(__post_word_it, __first, __last);
+        }
+      iterator __ret = this->begin();
+      __ret += __pos_dist;
+      return __ret;
+    }
+
+    template<typename _Iterator>
+    constexpr iterator
+    _M_copy_words_if_necessary(difference_type __insert_word_count,
+      difference_type __pos_dist, __base_c_iterator __pos_base_it,
+      _Iterator& __first)
+    {
+      if (__insert_word_count > 0)
+        {
+          difference_type __pos_base_dist =
+            __pos_dist / __binary_digits_v<__word_type>;
+          difference_type __insert_word_bit_count =
+            __insert_word_count * __binary_digits_v<__word_type>;
+          __base_iterator __storage_it =
+            this->_M_storage_unwrapped().insert(::std::move(__pos_base_it),
+              static_cast<size_type>(__insert_word_count),
+              static_cast<__word_type>(0));
+          ::std::advance(__storage_it, __pos_base_dist);
+          iterator __insertion_point = iterator(__storage_it, 0);
+          iterator __post_copy_it =
+            ::std::copy_n(__first, __insert_word_bit_count, __insertion_point);
+          __first += __insert_word_bit_count;
+          return __post_copy_it;
+        }
+      return iterator(__iter_as_mutable_from_begin(
+                        __pos_base_it, this->_M_storage_unwrapped()),
+        0);
+    }
+
+    template<typename _Iterator>
+    constexpr iterator
+    _M_basic_insert(const_iterator __pos, _Iterator __first, _Iterator __last)
+    {
+      bool __is_storage_empty = this->empty();
+      if (__is_storage_empty)
+        {
+          for (; __first != __last; ++__first)
+            {
+              this->push_back(*__first);
+            }
+          return this->begin();
+        }
+      // we can only check cbegin, because
+      // we can't save an iterator for
+      // wherever "end" is before we start
+      // shoveling things in (yay, iterator invalidation...)
+      if constexpr (__is_iterator_category_or_better_v<
+                      std::random_access_iterator_tag, iterator_category>)
+        {
+          // if we're inserting at the end,
+          // and we are random access,
+          // we can get a distance
+          // and then use it later on to return the
+          // insertion point properly from this method
+          if (__pos == this->cend())
+            {
+              difference_type __insertion_point_at =
+                static_cast<difference_type>(this->size());
+              for (; __first != __last; ++__first)
+                {
+                  this->push_back(*__first);
+                }
+              return ::std::next(this->begin(), __insertion_point_at);
+            }
+        }
+      if (__pos == this->cbegin())
+        {
+          for (; __first != __last; ++__first)
+            {
+              this->push_front(*__first);
+            }
+          return this->begin();
+        }
+      --__last;
+      bool __the_last_time   = __last == __first;
+      iterator __current_pos = this->insert(::std::move(__pos), *__last);
+      for (; !__the_last_time;)
+        {
+          --__last;
+          __the_last_time = __last == __first;
+          __current_pos   = this->insert(::std::move(__current_pos), *__last);
+        }
+      return __current_pos;
+    }
+
+    constexpr __base_iterator
+    _M_maybe_storage_bulk_erase(__base_c_iterator& __first_base_it,
+      size_type __first_position, difference_type __erase_word_count)
+    {
+      if (__erase_word_count > static_cast<difference_type>(0))
+        {
+          return this->_M_storage_bulk_erase(
+            __first_base_it, __first_position, __erase_word_count);
+        }
+      else
+        {
+          return __iter_as_mutable_from_begin(
+            __first_base_it, this->_M_storage_unwrapped());
+        }
+    }
+
+    constexpr __base_iterator
+    _M_storage_bulk_erase(__base_c_iterator& __first_base_it,
+      size_type __first_position, difference_type __erase_word_count) noexcept
+    {
+      // are we on a boundary?
+      if (__first_position == 0)
+        {
+          // perfectly aligned on word boundary,
+          // no half-word to shift:
+          // remove indiscriminately
+          auto __storage_it = this->_M_storage_unwrapped().erase(
+            __first_base_it, __first_base_it + __erase_word_count);
+          return __storage_it;
+        }
+
+      // Not perfectly aligned...
+      // attempt to preserve bits on boundaries of removal
+      __base_c_iterator __last_base_it = __first_base_it + (__erase_word_count);
+      // if the last is equal to end, we're just removing everything aren't we?
+      if (__last_base_it == this->_M_storage_cend())
+        {
+          return this->_M_storage_unwrapped().erase(
+            __first_base_it, __last_base_it);
+        }
+
+      // bulk-remove the parts we do not care about
+      // and merge tips into a single word that
+      // we can perform shifts on later
+      // save msb word for later merging into non-removed part, for when the
+      // shift happens
+      __word_type __lsb_word_chunk = *__first_base_it;
+      __base_iterator __storage_it =
+        this->_M_storage_unwrapped().erase(__first_base_it, __last_base_it);
+      __base_reference __msb_word_chunk_ref = *__storage_it;
+      __word_type __msb_word_chunk          = __msb_word_chunk_ref;
+      __msb_word_chunk_ref =
+        __merge_bits_at(__lsb_word_chunk, __msb_word_chunk, __first_position);
+      return __storage_it;
+    }
+
+    constexpr iterator
+    _M_this_random_access_erase(
+      const_iterator __first, const_iterator __last) noexcept
+    {
+      // early check: are we deleting
+      // everything?
+      if (__first == this->begin() && __last == this->cend())
+        {
+          clear();
+          return this->end();
+        }
+      difference_type __erase_bit_count = ::std::distance(__first, __last);
+      difference_type __erase_word_count =
+        __erase_bit_count / __binary_digits_v<__word_type>;
+      difference_type __erase_bit_shift =
+        __erase_bit_count % __binary_digits_v<__word_type>;
+      __base_c_iterator __first_base_it  = __first.base();
+      size_type __first_position         = __first.position();
+      __base_iterator __first_storage_it = _M_maybe_storage_bulk_erase(
+        __first_base_it, __first_position, __erase_word_count);
+      // are we out of bits?
+      if (__erase_bit_shift == 0)
+        {
+          // then we're already done
+          return iterator(::std::move(__first_storage_it), __first_position);
+        }
+      // we are not out of bits:
+      // shift down the first, then do the rest
+      __base_reference __first_storage_ref = *__first_storage_it;
+      if (__first_position == 0)
+        {
+          __first_storage_ref >>= __erase_bit_shift;
+        }
+      else
+        {
+          // bit preserver is inclusive: subtract 1
+          size_type __bit_pivot = __first_position - 1;
+          __shift_right_preserve_right<__word_type>(
+            __first_storage_ref, __bit_pivot, __erase_bit_shift);
+        }
+      // shift down all other bits now
+      __base_iterator __storage_last   = this->_M_storage_end();
+      __base_iterator __storage_it     = __first_storage_it;
+      __base_iterator __old_storage_it = __first_storage_it;
+
+      ++__storage_it;
+      for (; __storage_it != __storage_last;
+           ++__storage_it, (void)++__old_storage_it)
+        {
+          __base_reference __storage_ref     = *__storage_it;     // msb
+          __base_reference __old_storage_ref = *__old_storage_it; // lsb
+          __old_storage_ref = __replace_most_significant_bits_from<__word_type>(
+            __old_storage_ref, __storage_ref, __erase_bit_shift);
+          __storage_ref >>= __erase_bit_shift;
+        }
+      // update bit count
+      if (this->_M_bit_pos > static_cast<size_type>(__erase_bit_shift))
+        {
+          // simple rollback
+          this->_M_bit_pos -= static_cast<size_type>(__erase_bit_shift);
+        }
+      else
+        {
+          // we're going back over a word,
+          // so we need to remove the old word
+          this->_M_storage_unwrapped().erase(
+            --this->_M_storage_unwrapped().cend());
+          // then adjust the bit position
+          this->_M_bit_pos = __binary_digits_v<__word_type> -
+                             (__erase_bit_shift - this->_M_bit_pos);
+        }
+      return iterator(::std::move(__first_storage_it), __first_position);
+    }
+
+    constexpr iterator
+    _M_basic_erase(const_iterator __first, const_iterator __last) noexcept
+    {
+      // we already checked if we were empty
+      --__last;
+      // is this the first iterator?
+      // if so, this is our last iteration
+      bool __the_last_time   = __last == __first;
+      iterator __current_pos = this->erase(__last);
+      for (; !__the_last_time;)
+        {
+          // __last is currently invalid
+          // because we just killed it...
+          __last = __current_pos;
+          --__last;
+          __the_last_time = __last == __first;
+          __current_pos   = this->erase(__last);
+        }
+      return __current_pos;
+    }
+  };
+
+  _GLIBCXX_END_NAMESPACE_VERSION
+} // namespace __gnu_cxx_GLIBCXX_VISIBILITY(default)
+
+#endif // __cplusplus is on 20/2a or better
+
+#endif
diff --git a/libstdc++-v3/include/ext/bit_ds/bit_view.h b/libstdc++-v3/include/ext/bit_ds/bit_view.h
new file mode 100644
index 00000000000..e20a36f5abd
--- /dev/null
+++ b/libstdc++-v3/include/ext/bit_ds/bit_view.h
@@ -0,0 +1,1112 @@
+
+// friendly bit range adaptor -*- C++ -*-
+
+// Copyright (C) 2019-2019 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// Under Section 7 of GPL version 3, you are granted additional
+// permissions described in the GCC Runtime Library Exception, version
+// 3.1, as published by the Free Software Foundation.
+
+// You should have received a copy of the GNU General Public License and
+// a copy of the GCC Runtime Library Exception along with this program;
+// see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+// <http://www.gnu.org/licenses/>.
+
+/** @file ext/bit_ds/bit_operations.h
+ *  This file is a GNU extension to the Standard C++ Library.
+ *  It provides a C++20-alike, std::ranges-similar adaptation
+ *  of bits. It takes the original range, and an bounds
+ *  parameter which informs the range which section of
+ *  bits it would like to view. The bounds can be
+ *  computed at constant evaluation time as well
+ *  using __bit_bounds.
+ */
+
+#pragma once
+
+#ifndef _EXT_BIT_DS_BIT_VIEW_H
+#define _EXT_BIT_DS_BIT_VIEW_H 1
+
+#if (defined(__cplusplus) && __cplusplus >= 201703L)
+
+#include <ext/bit_ds/bit_iterator.h>
+#include <ext/bit_ds/bit_operations.h>
+#include <ext/bit_ds/bit_algorithm.h>
+
+#include <cstddef>
+#include <type_traits>
+#include <iterator>
+#include <utility>
+#include <algorithm>
+
+namespace __gnu_cxx _GLIBCXX_VISIBILITY(default)
+{
+  _GLIBCXX_BEGIN_NAMESPACE_VERSION
+
+  template<typename _Container>
+  class __word_bit_bounds
+  {
+  private:
+    using __container_type = __unwrap_t<_Container>;
+    using __container_ref  = std::add_lvalue_reference_t<__container_type>;
+    using __base_iterator =
+      decltype(__adl_begin(::std::declval<__container_ref>()));
+    using __word_type =
+      typename ::std::iterator_traits<__base_iterator>::value_type;
+    using __difference_type =
+      typename ::std::iterator_traits<__base_iterator>::difference_type;
+    using __size_type = ::std::make_unsigned_t<__difference_type>;
+
+  public:
+    static constexpr __size_type
+    begin_position(const __container_type&) noexcept
+    {
+      return 0;
+    }
+
+    static constexpr __size_type
+    end_position(const __container_type& __container) noexcept
+    {
+      if constexpr (::std::is_array_v<__container_type>)
+        {
+          return static_cast<__size_type>(
+            __adl_size(__container) * __binary_digits_v<__word_type>);
+        }
+      else if constexpr (__is_detected_v<__has_size_function_test,
+                           const __container_type&>)
+        {
+          return static_cast<__size_type>(
+            __container.size() * __binary_digits_v<__word_type>);
+        }
+      else
+        {
+          return static_cast<__size_type>(
+            ::std::distance(
+              ::std::cbegin(__container), ::std::cend(__container)) *
+            __binary_digits_v<__word_type>);
+        }
+    }
+  };
+
+  template<::std::size_t _BeginBit, ::std::size_t _EndBit>
+  class __bit_bounds
+  {
+  public:
+    template<typename _Container>
+    static constexpr ::std::size_t
+    begin_position(const _Container&) noexcept
+    {
+      return _BeginBit;
+    }
+
+    template<typename _Container>
+    static constexpr ::std::size_t
+    end_position(const _Container&) noexcept
+    {
+      return _EndBit;
+    }
+  };
+
+  template<typename _Container>
+  class __dynamic_bit_bounds_for
+  {
+  private:
+    using __container_type = __unwrap_t<_Container>;
+    using __range_ref      = std::add_lvalue_reference_t<__container_type>;
+    using __base_iterator =
+      decltype(::std::begin(::std::declval<__range_ref>()));
+    using __difference_type =
+      typename ::std::iterator_traits<__base_iterator>::difference_type;
+    using __size_type = ::std::make_unsigned_t<__difference_type>;
+    using __value_type =
+      typename ::std::iterator_traits<__base_iterator>::value_type;
+
+  public:
+    __size_type first;
+    __size_type last;
+
+    __dynamic_bit_bounds_for(const __range_ref __range) noexcept
+    : first(0), last(__adl_size(__range) * __binary_digits_v<__value_type>)
+    {
+    }
+
+    __dynamic_bit_bounds_for(__size_type __first, __size_type __last) noexcept
+    : first(__first), last(__last)
+    {
+    }
+
+    constexpr __size_type
+    begin_position(const __container_type&) const noexcept
+    {
+      return first;
+    }
+
+    constexpr __size_type
+    end_position(const __container_type&) const noexcept
+    {
+      return last;
+    }
+  };
+
+  class __dynamic_bit_bounds
+  {
+  public:
+    ::std::size_t first;
+    ::std::size_t last;
+
+    template<typename _Container>
+    __dynamic_bit_bounds(const _Container& __container) noexcept
+    : __dynamic_bit_bounds(0, __container)
+    {
+    }
+
+    template<typename _Container,
+      ::std::enable_if_t<!::std::is_arithmetic_v<_Container>>* = nullptr>
+    __dynamic_bit_bounds(
+      ::std::size_t __first, const _Container& __container) noexcept
+    : first(__first)
+    , last(
+        __first + (__adl_size(__unwrap_ref(__container)) *
+                    __binary_digits_v<typename ::std::iterator_traits<decltype(
+                      __adl_begin(__unwrap_ref(__container)))>::value_type>))
+    {
+    }
+
+    __dynamic_bit_bounds(::std::size_t __first, ::std::size_t __last) noexcept
+    : first(__first), last(__last)
+    {
+    }
+
+    template<typename _Container>
+    constexpr ::std::size_t
+    begin_position(const _Container&) const noexcept
+    {
+      return first;
+    }
+
+    template<typename container_type>
+    constexpr ::std::size_t
+    end_position(const container_type&) const noexcept
+    {
+      return last;
+    }
+  };
+
+  namespace __detail
+  {
+
+    template<typename>
+    struct __is_word_bit_bounds : ::std::false_type
+    {
+    };
+
+    template<typename container_type>
+    struct __is_word_bit_bounds<__word_bit_bounds<container_type>>
+    : ::std::true_type
+    {
+    };
+
+    template<typename _Type>
+    inline constexpr bool __is_word_bit_bounds_v =
+      __is_word_bit_bounds<_Type>::value;
+
+    template<typename _Type>
+    struct __is_word_or_bit_bounds : __is_word_bit_bounds<_Type>
+    {
+    };
+
+    template<::std::size_t __First, ::std::size_t __Last>
+    struct __is_word_or_bit_bounds<__bit_bounds<__First, __Last>>
+    : ::std::true_type
+    {
+    };
+
+    template<typename _Type>
+    inline constexpr bool __is_word_or_bit_bounds_v =
+      __is_word_or_bit_bounds<_Type>::value;
+
+    template<typename _Bounds, typename = void>
+    class __bounds_storage : private _Bounds
+    {
+    public:
+      constexpr __bounds_storage()                        = default;
+      constexpr __bounds_storage(const __bounds_storage&) = default;
+      constexpr __bounds_storage(__bounds_storage&&)      = default;
+      template<typename _Arg, typename... _Args,
+        ::std::enable_if_t<
+          !::std::is_same_v<::std::remove_cv_t<::std::remove_reference_t<_Arg>>,
+            __bounds_storage>>* = nullptr>
+      constexpr __bounds_storage(_Arg&& __arg, _Args&&... __args) noexcept(
+        ::std::is_nothrow_constructible_v<_Bounds, _Arg, _Args...>)
+      : _Bounds(::std::forward<_Arg>(__arg), ::std::forward<_Args>(__args)...)
+      {
+      }
+
+      constexpr __bounds_storage&
+      operator=(const __bounds_storage&) = default;
+      constexpr __bounds_storage&
+      operator=(__bounds_storage&&) = default;
+      template<typename _Arg,
+        ::std::enable_if_t<
+          !::std::is_same_v<::std::remove_cv_t<::std::remove_reference_t<_Arg>>,
+            __bounds_storage>>* = nullptr>
+      constexpr __bounds_storage&
+      operator=(_Arg&& __arg)
+      {
+        this->_Bounds::operator=(::std::forward<_Arg>(__arg));
+        return *this;
+      }
+
+      constexpr _Bounds&
+      value() &
+      {
+        return static_cast<_Bounds&>(*this);
+      }
+
+      constexpr const _Bounds&
+      value() const&
+      {
+        return static_cast<const _Bounds&>(*this);
+      }
+
+      constexpr _Bounds&&
+      value() &&
+      {
+        return static_cast<_Bounds&&>(*this);
+      }
+    };
+
+    template<typename _Bounds>
+    class __bounds_storage<_Bounds,
+      ::std::enable_if_t<::std::is_final_v<_Bounds> ||
+                         !::std::is_object_v<_Bounds>>> : private _Bounds
+    {
+    private:
+      _Bounds _M_bounds;
+
+    public:
+      constexpr __bounds_storage()                        = default;
+      constexpr __bounds_storage(const __bounds_storage&) = default;
+      constexpr __bounds_storage(__bounds_storage&&)      = default;
+      template<typename _Arg, typename... _Args,
+        ::std::enable_if_t<
+          !::std::is_same_v<::std::remove_cv_t<::std::remove_reference_t<_Arg>>,
+            __bounds_storage>>* = nullptr>
+      constexpr __bounds_storage(_Arg&& __arg, _Args&&... __args) noexcept(
+        ::std::is_nothrow_constructible_v<_Bounds, _Arg, _Args...>)
+      : _M_bounds(::std::forward<_Arg>(__arg), ::std::forward<_Args>(__args)...)
+      {
+      }
+
+      constexpr __bounds_storage&
+      operator=(const __bounds_storage&) = default;
+      constexpr __bounds_storage&
+      operator=(__bounds_storage&&) = default;
+      template<typename _Arg,
+        ::std::enable_if_t<
+          !::std::is_same_v<::std::remove_cv_t<::std::remove_reference_t<_Arg>>,
+            __bounds_storage>>* = nullptr>
+      constexpr __bounds_storage&
+      operator=(_Arg&& __arg)
+      {
+        this->_M_nounds = ::std::forward<_Arg>(__arg);
+        return *this;
+      }
+
+      constexpr _Bounds&
+      value() &
+      {
+        return this->_M_bounds;
+      }
+
+      constexpr const _Bounds&
+      value() const&
+      {
+        return this->_M_bounds;
+      }
+
+      constexpr _Bounds&&
+      value() &&
+      {
+        return ::std::move(this->_M_bounds);
+      }
+    };
+  } // namespace __detail
+
+  template<typename _Range,
+    typename _Bounds = __word_bit_bounds<__unwrap_t<_Range>>>
+  class __bit_view : __detail::__bounds_storage<_Bounds>
+  {
+  private:
+    template<typename, typename>
+    friend class __bit_view;
+    template<typename>
+    friend class __bit_sequence;
+
+    using __base_t    = __detail::__bounds_storage<_Bounds>;
+    using __range     = __unwrap_t<_Range>;
+    using __range_ref = std::add_lvalue_reference_t<__range>;
+    using __base_iterator =
+      decltype(__adl_begin(::std::declval<__range_ref>()));
+    using __base_sentinel = decltype(__adl_end(::std::declval<__range_ref>()));
+    using __base_c_iterator =
+      decltype(__adl_cbegin(::std::declval<__range_ref>()));
+    using __base_c_sentinel =
+      decltype(__adl_cend(::std::declval<__range_ref>()));
+    using __base_pointer =
+      typename ::std::iterator_traits<__base_iterator>::pointer;
+    using __base_reference =
+      typename ::std::iterator_traits<__base_iterator>::reference;
+    using __base_c_pointer =
+      typename ::std::iterator_traits<__base_c_iterator>::pointer;
+    using __base_c_reference =
+      typename ::std::iterator_traits<__base_c_iterator>::reference;
+    using __iterator   = __bit_iterator<__base_iterator>;
+    using __sentinel   = __bit_iterator<__base_sentinel>;
+    using __c_iterator = __bit_iterator<__base_c_iterator>;
+    using __c_sentinel = __bit_iterator<__base_c_sentinel>;
+    using __word_type =
+      typename ::std::iterator_traits<__base_iterator>::value_type;
+    using __integral_word_type = __any_to_underlying_t<__word_type>;
+    using __reference =
+      __bit_reference<__base_reference, __bit_mask_type_t<__word_type>>;
+    using __const_reference =
+      __bit_reference<__base_c_reference, __bit_mask_type_t<__word_type>>;
+    using __base_iterator_category =
+      typename ::std::iterator_traits<__base_iterator>::iterator_category;
+    using __base_c_iterator_category =
+      typename ::std::iterator_traits<__base_c_iterator>::iterator_category;
+
+  public:
+    using difference_type =
+      typename ::std::iterator_traits<__base_iterator>::difference_type;
+    using size_type       = ::std::make_unsigned_t<difference_type>;
+    using value_type      = __bit_value;
+    using reference       = __reference;
+    using const_reference = __const_reference;
+    using pointer         = __bit_pointer<__base_pointer>;
+    using const_pointer   = __bit_pointer<__base_c_pointer>;
+    using iterator_category =
+      typename ::std::iterator_traits<__base_iterator>::iterator_category;
+    // FIXME: strengthen guarantees by checking for `iterator_concept`
+    // on iterator_traits when ranges gets merged
+    using iterator_concept = iterator_category;
+    using iterator         = __iterator;
+    using sentinel         = __sentinel;
+    using const_iterator   = __c_iterator;
+    using const_sentinel   = __c_sentinel;
+    using container_type   = _Range;
+    using bounds_type      = _Bounds;
+
+    constexpr __bit_view() noexcept(::std::is_nothrow_default_constructible_v<
+      container_type>&& ::std::is_nothrow_default_constructible_v<bounds_type>)
+    : __base_t(), _M_storage()
+    {
+    }
+
+    template<typename _Arg, typename... _Args,
+      ::std::enable_if_t<!__is_same_no_cvref_v<__bit_view, _Arg> &&
+                           !__is_same_no_cvref_v<bounds_type, _Arg>,
+        void*> = nullptr>
+    constexpr __bit_view(_Arg&& __arg, _Args&&... __args) noexcept(
+      ::std::is_nothrow_constructible_v<container_type, _Arg,
+        _Args...>&& ::std::is_nothrow_default_constructible_v<bounds_type>)
+    : __base_t()
+    , _M_storage(::std::forward<_Arg>(__arg), ::std::forward<_Args>(__args)...)
+    {
+    }
+
+    template<typename... _Args>
+    constexpr __bit_view(bounds_type __extents, _Args&&... __args) noexcept(
+      ::std::is_nothrow_constructible_v<container_type,
+        _Args...>&& ::std::is_nothrow_move_constructible_v<bounds_type>)
+    : __base_t(std::move(__extents))
+    , _M_storage(::std::forward<_Args>(__args)...)
+    {
+    }
+
+    constexpr __bit_view(const __bit_view& __right) = default;
+    constexpr __bit_view(__bit_view&& __right)      = default;
+
+    constexpr __bit_view&
+    operator=(const __bit_view& __right) = default;
+    constexpr __bit_view&
+    operator=(__bit_view&& __right) = default;
+
+    // modifiers
+    constexpr reference operator[](difference_type __n) noexcept
+    {
+      auto __it = this->begin();
+      __it += __n;
+      return *__it;
+    }
+
+    constexpr const_reference operator[](difference_type __n) const noexcept
+    {
+      auto __it = this->cbegin();
+      __it += __n;
+      return *__it;
+    }
+
+    constexpr void
+    set() noexcept
+    {
+      set(0, this->size());
+    }
+
+    // prevent integer promotion
+    // from giving users the wrong idea
+    constexpr void
+    set(bool __value)
+    {
+      set(value_type(__value));
+    }
+
+    constexpr void
+    set(value_type __value) noexcept
+    {
+      set(0, this->size(), __value);
+    }
+
+    constexpr void
+    set(size_type __pos) noexcept
+    {
+      auto __it = this->begin();
+      ::std::advance(__it, __pos);
+      auto ref = *__it;
+      ref.set();
+    }
+
+    constexpr void
+    set(size_type __pos, bool __val) noexcept
+    {
+      set(__pos, value_type(__val));
+    }
+
+    constexpr void
+    set(size_type __pos, value_type __val) noexcept
+    {
+      auto __it = this->begin();
+      ::std::advance(__it, __pos);
+      auto ref = *__it;
+      ref.set(__val);
+    }
+
+    constexpr void
+    set(size_type __pos, size_type __len) noexcept
+    {
+      auto __it = this->begin();
+      ::std::advance(__it, __pos);
+      __bit_fill_n(__it, __len, true);
+    }
+
+    constexpr void
+    set(size_type __pos, size_type __len, bool __val) noexcept
+    {
+      this->set(__pos, __len, value_type(__val));
+    }
+
+    constexpr void
+    set(size_type __pos, size_type __len, value_type __val) noexcept
+    {
+      if (__val)
+        {
+          this->set(__pos, __len);
+        }
+      else
+        {
+          this->reset(__pos, __len);
+        }
+    }
+
+    constexpr void
+    reset() noexcept
+    {
+      reset(0, this->size());
+    }
+
+    constexpr void
+    reset(size_type __pos) noexcept
+    {
+      auto __it = this->begin();
+      ::std::advance(__it, __pos);
+      auto ref = *__it;
+      ref.reset();
+    }
+
+    constexpr void
+    reset(size_type __pos, size_type __len) noexcept
+    {
+      auto __it = this->begin();
+      ::std::advance(__it, __pos);
+      __bit_fill_n(__it, __len, false);
+    }
+
+    constexpr void
+    flip() noexcept
+    {
+      flip(0, this->size());
+    }
+
+    constexpr void
+    flip(size_type __pos) noexcept
+    {
+      auto __it = this->begin();
+      ::std::advance(__it, __pos);
+      auto ref = *__it;
+      ref.flip();
+    }
+
+    constexpr void
+    flip(size_type __pos, size_type __len) noexcept
+    {
+      iterator __it = this->begin();
+      ::std::advance(__it, __pos);
+      if constexpr (::std::is_unsigned_v<__word_type>)
+        {
+          // get to word boundary
+          for (size_type __boundary =
+                 __len - (__len % (__binary_digits_v<__word_type>));
+               __boundary < __len; ++__it, (void)--__len)
+            {
+              auto ref = *__it;
+              ref.flip();
+            }
+          // process words
+          __base_iterator __it_base = ::std::move(__it).base();
+          for (; __len > __binary_digits_v<__word_type>;
+               __len -= __binary_digits_v<__word_type>)
+            {
+              __base_reference __ref_base = *__it_base;
+              __ref_base                  = ~__ref_base;
+              ++__it_base;
+            }
+          __it = iterator(::std::move(__it_base), 0);
+        }
+      // process individual bits
+      for (; __len-- > 0; ++__it)
+        {
+          reference __ref = *__it;
+          __ref.flip();
+        }
+    }
+
+    constexpr iterator
+    begin() noexcept
+    {
+      if constexpr (__detail::__is_word_bit_bounds_v<bounds_type>)
+        {
+          return iterator(this->_M_storage_begin(), 0);
+        }
+      else
+        {
+          auto __bit_distance = this->_M_bounds_unwrapped().begin_position(
+            this->_M_storage_unwrapped());
+          auto __first = iterator(this->_M_storage_begin());
+          __first += __bit_distance;
+          return __first;
+        }
+    }
+
+    constexpr sentinel
+    end() noexcept
+    {
+      if constexpr (__detail::__is_word_bit_bounds_v<bounds_type>)
+        {
+          return const_sentinel(this->_M_storage_end(), 0);
+        }
+      else
+        {
+          auto __bit_distance = this->_M_bounds_unwrapped().end_position(
+            this->_M_storage_unwrapped());
+          auto __last = const_iterator(this->_M_storage_begin());
+          ::std::advance(__last, __bit_distance);
+          return __last;
+        }
+    }
+
+    constexpr const_iterator
+    begin() const noexcept
+    {
+      return this->cbegin();
+    }
+
+    constexpr const_sentinel
+    end() const noexcept
+    {
+      return this->cend();
+    }
+
+    constexpr const_iterator
+    cbegin() const noexcept
+    {
+      if constexpr (__detail::__is_word_bit_bounds_v<bounds_type>)
+        {
+          return const_iterator(this->_M_storage_cbegin(), 0);
+        }
+      else
+        {
+          auto __bit_distance = this->_M_bounds_unwrapped().begin_position(
+            this->_M_storage_unwrapped());
+          auto __first = const_iterator(this->_M_storage_cbegin());
+          __first += __bit_distance;
+          return __first;
+        }
+    }
+
+    constexpr const_sentinel
+    cend() const noexcept
+    {
+      if constexpr (__detail::__is_word_bit_bounds_v<bounds_type>)
+        {
+          return const_sentinel(this->_M_storage_cend(), 0);
+        }
+      else
+        {
+          auto __bit_distance = this->_M_bounds_unwrapped().end_position(
+            this->_M_storage_unwrapped());
+          auto __last = const_iterator(this->_M_storage_cbegin());
+          __last += __bit_distance;
+          return __last;
+        }
+    }
+
+    // observers
+    bool
+    empty() const
+    {
+      if constexpr (__detail::__is_word_bit_bounds_v<bounds_type>)
+        {
+          return __adl_empty(this->_M_storage_unwrapped());
+        }
+      else
+        {
+          return this->_M_bounds_unwrapped().begin_position(
+                   this->_M_storage_unwrapped()) ==
+                 this->_M_bounds_unwrapped().end_position(
+                   this->_M_storage_unwrapped());
+        }
+    }
+
+    constexpr const container_type&
+    base() const& noexcept
+    {
+      return this->_M_storage_unwrapped();
+    }
+
+    constexpr container_type&
+      base() &
+      noexcept
+    {
+      return this->_M_storage_unwrapped();
+    }
+
+    constexpr container_type&&
+      base() &&
+      noexcept
+    {
+      return ::std::move(this->_M_storage_unwrapped());
+    }
+
+    constexpr bool
+    test(difference_type __pos) const noexcept
+    {
+      return *::std::next(this->cbegin(), __pos);
+    }
+
+    constexpr size_type
+    count(value_type __value) const noexcept
+    {
+      size_type __count = __bit_count(this->cbegin(), this->cend(), true);
+      if (!__value)
+        {
+          return size() - __count;
+        }
+      return __count;
+    }
+
+    constexpr size_type
+    popcount() const noexcept
+    {
+      return this->count(true);
+    }
+
+    constexpr size_type
+    one_count() const noexcept
+    {
+      return this->count(true);
+    }
+
+    constexpr size_type
+    zero_count() const noexcept
+    {
+      return this->count(false);
+    }
+
+    constexpr bool
+    all() const noexcept
+    {
+      const_iterator __last = this->cend();
+      return __bit_find(this->cbegin(), __last, false) == __last;
+    }
+
+    constexpr bool
+    any() const noexcept
+    {
+      const_iterator __last = this->cend();
+      return __bit_find(this->cbegin(), __last, true) != __last;
+    }
+
+    constexpr bool
+    none() const noexcept
+    {
+      const_iterator __last = this->cend();
+      return __bit_find(this->cbegin(), __last, true) == __last;
+    }
+
+    constexpr size_type
+    size() const noexcept
+    {
+      return this->_M_bit_distance();
+    }
+
+    constexpr const bounds_type&
+    bounds() const noexcept
+    {
+      return this->_M_bounds.value();
+    }
+
+    constexpr bounds_type&
+    bounds() noexcept
+    {
+      return this->_M_bounds.value();
+    }
+
+    template<typename _LeftR, typename _LeftEx, typename _RightR,
+      typename _RightEx>
+    friend constexpr bool
+    operator==(const __bit_view<_LeftR, _LeftEx>& __left,
+      const __bit_view<_RightR, _RightEx>& __right);
+
+    template<typename _LeftR, typename _LeftEx, typename _RightR,
+      typename _RightEx>
+    friend constexpr bool
+    operator!=(const __bit_view<_LeftR, _LeftEx>& __left,
+      const __bit_view<_RightR, _RightEx>& __right);
+
+    template<typename _LeftR, typename _LeftEx, typename _RightR,
+      typename _RightEx>
+    friend constexpr bool
+    operator<(const __bit_view<_LeftR, _LeftEx>& __left,
+      const __bit_view<_RightR, _RightEx>& __right);
+
+    template<typename _LeftR, typename _LeftEx, typename _RightR,
+      typename _RightEx>
+    friend constexpr bool
+    operator<=(const __bit_view<_LeftR, _LeftEx>& __left,
+      const __bit_view<_RightR, _RightEx>& __right);
+
+    template<typename _LeftR, typename _LeftEx, typename _RightR,
+      typename _RightEx>
+    friend constexpr bool
+    operator>(const __bit_view<_LeftR, _LeftEx>& __left,
+      const __bit_view<_RightR, _RightEx>& __right);
+
+    template<typename _LeftR, typename _LeftEx, typename _RightR,
+      typename _RightEx>
+    friend constexpr bool
+    operator>=(const __bit_view<_LeftR, _LeftEx>& __left,
+      const __bit_view<_RightR, _RightEx>& __right);
+
+  private:
+    container_type _M_storage;
+
+    template<typename _Right>
+    inline static constexpr bool __is_directly_comparable =
+      ::std::is_unsigned_v<__integral_word_type>&& ::std::
+        is_unsigned_v<typename _Right::__integral_word_type>&& ::std::is_same_v<
+          container_type, typename _Right::container_type>&& ::std::
+          is_same_v<bounds_type, typename _Right::bounds_type>&&
+            __detail::__is_word_bit_bounds_v<bounds_type>&&
+              __detail::__is_word_bit_bounds_v<typename _Right::bounds_type>;
+
+    constexpr size_type
+    _M_bit_distance() const noexcept
+    {
+      return static_cast<size_type>(
+        this->_M_bounds_unwrapped().end_position(this->_M_storage_unwrapped()) -
+        this->_M_bounds_unwrapped().begin_position(
+          this->_M_storage_unwrapped()));
+    }
+
+    constexpr __base_iterator
+    _M_storage_begin() noexcept(
+      noexcept(__adl_begin(this->_M_storage_unwrapped())))
+    {
+      return __adl_begin(this->_M_storage_unwrapped());
+    }
+
+    constexpr __base_sentinel
+    _M_storage_end() noexcept(noexcept(__adl_end(this->_M_storage_unwrapped())))
+    {
+      return __adl_end(this->_M_storage_unwrapped());
+    }
+
+    constexpr __base_c_iterator
+    _M_storage_begin() const
+      noexcept(noexcept(__adl_begin(this->_M_storage_unwrapped())))
+    {
+      return __adl_begin(this->_M_storage_unwrapped());
+    }
+
+    constexpr __base_c_sentinel
+    _M_storage_end() const
+      noexcept(noexcept(__adl_end(this->_M_storage_unwrapped())))
+    {
+      return __adl_end(this->_M_storage_unwrapped());
+    }
+
+    constexpr __base_c_iterator
+    _M_storage_cbegin() const
+      noexcept(noexcept(__adl_cbegin(this->_M_storage_unwrapped())))
+    {
+      return __adl_cbegin(this->_M_storage_unwrapped());
+    }
+
+    constexpr __base_c_sentinel
+    _M_storage_cend() const
+      noexcept(noexcept(__adl_cend(this->_M_storage_unwrapped())))
+    {
+      return __adl_cend(this->_M_storage_unwrapped());
+    }
+
+    constexpr decltype(auto)
+    _M_storage_unwrapped() const noexcept
+    {
+      return __unwrap_ref(this->_M_storage);
+    }
+
+    constexpr decltype(auto)
+    _M_storage_unwrapped() noexcept
+    {
+      return __unwrap_ref(this->_M_storage);
+    }
+
+    constexpr decltype(auto)
+    _M_bounds_unwrapped() const noexcept
+    {
+      return __unwrap_ref(static_cast<const __base_t&>(*this).value());
+    }
+
+    constexpr decltype(auto)
+    _M_bounds_unwrapped() noexcept
+    {
+      return __unwrap_ref(static_cast<__base_t&>(*this).value());
+    }
+  };
+
+  template<typename _LeftR, typename _LeftEx, typename _RightR,
+    typename _RightEx>
+  constexpr bool operator==(const __bit_view<_LeftR, _LeftEx>& __left,
+    const __bit_view<_RightR, _RightEx>& __right)
+  {
+    using _Left         = __bit_view<_LeftR, _LeftEx>;
+    using _Right        = __bit_view<_RightR, _RightEx>;
+    using _LeftStorage  = typename _Left::container_type;
+    using _RightStorage = typename _Right::container_type;
+    if constexpr (_Left::template __is_directly_comparable<_Right> &&
+                  __is_detected_v<__equal_to_test, _LeftStorage, _RightStorage>)
+      {
+        return __left._M_storage == __right._M_storage;
+      }
+    else
+      {
+        auto __left_size  = __left.size();
+        auto __right_size = __right.size();
+        if (__left_size != __right_size)
+          {
+            return false;
+          }
+        if constexpr (std::is_same_v<typename _Left::__word_type,
+                        typename _Right::__word_type> &&
+                      __detail::__is_word_bit_bounds_v<
+                        typename _Left::bounds_type> &&
+                      __detail::__is_word_bit_bounds_v<
+                        typename _Right::bounds_type>)
+          {
+            auto __left_it0  = __left._M_storage_cbegin();
+            auto __left_it1  = __left._M_storage_cend();
+            auto __right_it0 = __right._M_storage_cbegin();
+            auto __right_it1 = __right._M_storage_cend();
+            return ::std::equal(
+              __left_it0, __left_it1, __right_it0, __right_it1);
+          }
+        else
+          {
+            auto __left_it0  = __left.cbegin();
+            auto __left_it1  = __left.cend();
+            auto __right_it0 = __right.cbegin();
+            auto __right_it1 = __right.cbegin();
+            return ::std::equal(
+              __left_it0, __left_it1, __right_it0, __right_it1);
+          }
+      }
+  }
+
+  template<typename _LeftR, typename _LeftEx, typename _RightR,
+    typename _RightEx>
+  constexpr bool operator!=(const __bit_view<_LeftR, _LeftEx>& __left,
+    const __bit_view<_RightR, _RightEx>& __right)
+  {
+    using _Left         = __bit_view<_LeftR, _LeftEx>;
+    using _Right        = __bit_view<_RightR, _RightEx>;
+    using _LeftStorage  = typename _Left::container_type;
+    using _RightStorage = typename _Right::container_type;
+    if constexpr (_Left::template __is_directly_comparable<_Right> &&
+                  __is_detected_v<__not_equal_to_test, _LeftStorage,
+                    _RightStorage>)
+      {
+        return __left._M_storage != __right._M_storage;
+      }
+    else
+      {
+        auto __left_size  = __left.size();
+        auto __right_size = __right.size();
+        if (__left_size == __right_size)
+          {
+            if constexpr (std::is_same_v<typename _Left::__word_type,
+                            typename _Right::__word_type> &&
+                          __detail::__is_word_bit_bounds_v<
+                            typename _Left::bounds_type> &&
+                          __detail::__is_word_bit_bounds_v<
+                            typename _Right::bounds_type>)
+              {
+                auto __left_it0  = __left._M_storage_cbegin();
+                auto __left_it1  = __left._M_storage_cend();
+                auto __right_it0 = __right._M_storage_cbegin();
+                auto __right_it1 = __right._M_storage_cend();
+                return !::std::equal(
+                  __left_it0, __left_it1, __right_it0, __right_it1);
+              }
+            else
+              {
+                auto __left_it0  = __left.cbegin();
+                auto __left_it1  = __left.cend();
+                auto __right_it0 = __right.cbegin();
+                auto __right_it1 = __right.cbegin();
+                return !::std::equal(
+                  __left_it0, __left_it1, __right_it0, __right_it1);
+              }
+          }
+        return false;
+      }
+  }
+
+  template<typename _LeftR, typename _LeftEx, typename _RightR,
+    typename _RightEx>
+  constexpr bool operator<(const __bit_view<_LeftR, _LeftEx>& __left,
+    const __bit_view<_RightR, _RightEx>& __right)
+  {
+    using _Left         = __bit_view<_LeftR, _LeftEx>;
+    using _Right        = __bit_view<_RightR, _RightEx>;
+    using _LeftStorage  = typename _Left::container_type;
+    using _RightStorage = typename _Right::container_type;
+    if constexpr (_Left::template __is_directly_comparable<_Right> &&
+                  __is_detected_v<__less_than_test, _LeftStorage,
+                    _RightStorage>)
+      {
+        return __left._M_storage < __right._M_storage;
+      }
+    else
+      {
+        auto __leftfirst  = __left.cbegin();
+        auto __leftlast   = __left.cend();
+        auto __rightfirst = __right.cbegin();
+        auto __rightlast  = __right.cend();
+        return ::std::lexicographical_compare(std::move(__leftfirst),
+          std::move(__leftlast), std::move(__rightfirst),
+          std::move(__rightlast));
+      }
+  }
+
+  template<typename _LeftR, typename _LeftEx, typename _RightR,
+    typename _RightEx>
+  constexpr bool operator<=(const __bit_view<_LeftR, _LeftEx>& __left,
+    const __bit_view<_RightR, _RightEx>& __right)
+  {
+    using _Left         = __bit_view<_LeftR, _LeftEx>;
+    using _Right        = __bit_view<_RightR, _RightEx>;
+    using _LeftStorage  = typename _Left::container_type;
+    using _RightStorage = typename _Right::container_type;
+    if constexpr (_Left::template __is_directly_comparable<_Right> &&
+                  __is_detected_v<__less_equal_to_test, _LeftStorage,
+                    _RightStorage>)
+      {
+        return __left._M_storage <= __right._M_storage;
+      }
+    else
+      {
+        return !(__left > __right);
+      }
+  }
+
+  template<typename _LeftR, typename _LeftEx, typename _RightR,
+    typename _RightEx>
+  constexpr bool operator>(const __bit_view<_LeftR, _LeftEx>& __left,
+    const __bit_view<_RightR, _RightEx>& __right)
+  {
+    using _Left         = __bit_view<_LeftR, _LeftEx>;
+    using _Right        = __bit_view<_RightR, _RightEx>;
+    using _LeftStorage  = typename _Left::container_type;
+    using _RightStorage = typename _Right::container_type;
+    if constexpr (_Left::template __is_directly_comparable<_Right> &&
+                  __is_detected_v<__greater_than_test, _LeftStorage,
+                    _RightStorage>)
+      {
+        return __left._M_storage > __right._M_storage;
+      }
+    else
+      {
+        return ::std::lexicographical_compare(__left.cbegin(), __left.cend(),
+          __right.cbegin(), __right.cend(), std::greater<bool>());
+      }
+  }
+
+  template<typename _LeftR, typename _LeftEx, typename _RightR,
+    typename _RightEx>
+  constexpr bool operator>=(const __bit_view<_LeftR, _LeftEx>& __left,
+    const __bit_view<_RightR, _RightEx>& __right)
+  {
+    using _Left         = __bit_view<_LeftR, _LeftEx>;
+    using _Right        = __bit_view<_RightR, _RightEx>;
+    using _LeftStorage  = typename _Left::container_type;
+    using _RightStorage = typename _Right::container_type;
+    if constexpr (_Left::template __is_directly_comparable<_Right> &&
+                  __is_detected_v<__greater_equal_to_test, _LeftStorage,
+                    _RightStorage>)
+      {
+        return __left._M_storage >= __right._M_storage;
+      }
+    else
+      {
+        return !(__left < __right);
+      }
+  }
+
+  _GLIBCXX_END_NAMESPACE_VERSION
+} // namespace __gnu_cxx_GLIBCXX_VISIBILITY(default)
+
+#endif // __cplusplus is on 20/2a or better
+
+#endif
diff --git a/libstdc++-v3/testsuite/ext/bit_ds/bit_ds_tests_constants.h b/libstdc++-v3/testsuite/ext/bit_ds/bit_ds_tests_constants.h
new file mode 100644
index 00000000000..a1ba40b1ff4
--- /dev/null
+++ b/libstdc++-v3/testsuite/ext/bit_ds/bit_ds_tests_constants.h
@@ -0,0 +1,34 @@
+// bit data structures extension tests -*- C++ -*-
+
+// Copyright (C) 2019-2019 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// Under Section 7 of GPL version 3, you are granted additional
+// permissions described in the GCC Runtime Library Exception, version
+// 3.1, as published by the Free Software Foundation.
+
+// You should have received a copy of the GNU General Public License and
+// a copy of the GCC Runtime Library Exception along with this program;
+// see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+// <http://www.gnu.org/licenses/>.
+
+#pragma once
+
+#ifndef _EXT_BIT_DS_TESTS_CONSTANTS_H
+#define _EXT_BIT_DS_TESTS_CONSTANTS_H 1
+
+#include <cstddef>
+
+inline constexpr std::size_t expected_words = 30;
+
+#endif
diff --git a/libstdc++-v3/testsuite/ext/bit_ds/bit_ds_tests_require.h b/libstdc++-v3/testsuite/ext/bit_ds/bit_ds_tests_require.h
new file mode 100644
index 00000000000..0ad6f206377
--- /dev/null
+++ b/libstdc++-v3/testsuite/ext/bit_ds/bit_ds_tests_require.h
@@ -0,0 +1,47 @@
+// bit data structures extension tests -*- C++ -*-
+
+// Copyright (C) 2019-2019 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// Under Section 7 of GPL version 3, you are granted additional
+// permissions described in the GCC Runtime Library Exception, version
+// 3.1, as published by the Free Software Foundation.
+
+// You should have received a copy of the GNU General Public License and
+// a copy of the GCC Runtime Library Exception along with this program;
+// see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+// <http://www.gnu.org/licenses/>.
+
+/** @file testsuite/ext/bit_ds/bit_ds_test_require.h
+ *  This file tests a GNU extension to the Standard C++ Library.
+ *  It creates a few macros and includes headers which
+ *  make writing tests a bit easier.
+ */
+
+#pragma once
+
+#ifndef _EXT_BIT_DS_TESTS_REQUIRE_H
+#define _EXT_BIT_DS_TESTS_REQUIRE_H 1
+
+#include <testsuite_hooks.h>
+#include <initializer_list>
+#include "ranges_fill.h"
+#include "span_fill.h"
+
+#define REQUIRE(...) VERIFY(__VA_ARGS__)
+#define REQUIRE_FALSE(...) VERIFY(!(__VA_ARGS__))
+// TODO: hook section to help failures provide
+// more information on specific locations of failure
+#define SECTION(...)
+
+#endif
diff --git a/libstdc++-v3/testsuite/ext/bit_ds/bit_ds_tests_shared_insert_erase_tests.h b/libstdc++-v3/testsuite/ext/bit_ds/bit_ds_tests_shared_insert_erase_tests.h
new file mode 100644
index 00000000000..4cd70821017
--- /dev/null
+++ b/libstdc++-v3/testsuite/ext/bit_ds/bit_ds_tests_shared_insert_erase_tests.h
@@ -0,0 +1,430 @@
+// bit data structures extension tests -*- C++ -*-
+
+// Copyright (C) 2019-2019 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// Under Section 7 of GPL version 3, you are granted additional
+// permissions described in the GCC Runtime Library Exception, version
+// 3.1, as published by the Free Software Foundation.
+
+// You should have received a copy of the GNU General Public License and
+// a copy of the GCC Runtime Library Exception along with this program;
+// see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+// <http://www.gnu.org/licenses/>.
+
+#pragma once
+
+#ifndef _EXT_BIT_DS_TESTS_SHARED_TESTS_H
+#define _EXT_BIT_DS_TESTS_SHARED_TESTS_H 1
+
+#include "bit_ds_tests_require.h"
+
+#include <ext/bit>
+
+#include <vector>
+
+template<typename TestType>
+constexpr bool
+is_even_respecting_boundaries(std::size_t i) noexcept
+{
+  std::size_t modulo = i % __gnu_cxx::binary_digits_v<TestType>;
+  return (modulo % 2) == 0;
+}
+
+template<typename TestType, typename BitSequence>
+void
+bit_sequence_insert_erase_test(BitSequence& bs)
+{
+  const std::size_t original_size   = bs.size();
+  const std::size_t pre_insert_size = original_size + 2;
+  const std::size_t post_insert_size =
+    pre_insert_size + __gnu_cxx::binary_digits_v<TestType>;
+
+  REQUIRE(original_size == 0);
+  REQUIRE(bs.empty());
+  REQUIRE(bs.size() == 0);
+  REQUIRE(bs.cbegin() == bs.cend());
+  REQUIRE(bs.begin() == bs.end());
+  REQUIRE_FALSE(bs.cbegin() != bs.cend());
+  REQUIRE_FALSE(bs.begin() != bs.end());
+  bs.push_back(false);
+  bs.push_back(false);
+
+  REQUIRE(bs.size() == pre_insert_size);
+
+  for (std::size_t i = 0; i < __gnu_cxx::binary_digits_v<TestType>; ++i)
+    {
+      auto it  = bs.insert(++bs.cbegin(), true);
+      bool val = *it;
+      REQUIRE(val);
+    }
+
+  REQUIRE_FALSE(bs.empty());
+  REQUIRE(bs.size() == post_insert_size);
+  REQUIRE_FALSE(bs.cbegin() == bs.cend());
+  REQUIRE_FALSE(bs.begin() == bs.end());
+  REQUIRE(bs.cbegin() != bs.cend());
+  REQUIRE(bs.begin() != bs.end());
+
+  for (std::size_t i = 0; i < bs.size(); ++i)
+    {
+      bool value = bs[i];
+      if (i == 0 || i == (1 + __gnu_cxx::binary_digits_v<TestType>))
+        {
+          REQUIRE_FALSE(value);
+        }
+      else
+        {
+          REQUIRE(value);
+        }
+    }
+
+  for (std::size_t i = 0; i < __gnu_cxx::binary_digits_v<TestType>; ++i)
+    {
+      auto target = bs.cbegin();
+      std::advance(target, 1);
+      auto it        = bs.erase(target);
+      const bool val = *it;
+      const bool expected_val =
+        (i < (__gnu_cxx::binary_digits_v<TestType> - 1));
+      std::size_t size = bs.size();
+      std::size_t expected_size =
+        static_cast<std::size_t>(post_insert_size - i - 1);
+      REQUIRE(val == expected_val);
+      REQUIRE(size == expected_size);
+    }
+
+  REQUIRE(bs.size() == pre_insert_size);
+  REQUIRE_FALSE(bs.empty());
+  REQUIRE_FALSE(bs.cbegin() == bs.cend());
+  REQUIRE_FALSE(bs.begin() == bs.end());
+  REQUIRE(bs.cbegin() != bs.cend());
+  REQUIRE(bs.begin() != bs.end());
+
+  for (std::size_t i = 0; i < bs.size(); ++i)
+    {
+      bool value = bs[i];
+      REQUIRE_FALSE(value);
+    }
+
+  bs.clear();
+
+  REQUIRE(bs.size() == 0);
+  REQUIRE(bs.empty());
+  REQUIRE(bs.cbegin() == bs.cend());
+  REQUIRE(bs.begin() == bs.end());
+  REQUIRE_FALSE(bs.cbegin() != bs.cend());
+  REQUIRE_FALSE(bs.begin() != bs.end());
+}
+
+template<typename TestType, typename BitSequence>
+void
+bit_sequence_insert_test_bulk_small(BitSequence& bs)
+{
+  using value_type = typename BitSequence::value_type;
+  REQUIRE(bs.empty());
+  REQUIRE(bs.size() == 0);
+
+  std::initializer_list<value_type> il0 = { false, true, false, true, false };
+  auto insert_it0                       = bs.insert(bs.cbegin(), il0);
+  auto expected_insert_it0              = bs.begin();
+  const std::size_t post_insert0_size   = bs.size();
+  const std::size_t expected_post_insert0_size = il0.size();
+  REQUIRE(insert_it0 == expected_insert_it0);
+  REQUIRE(post_insert0_size == expected_post_insert0_size);
+  for (std::size_t i = 0; i < bs.size(); ++i)
+    {
+      bool val = bs[i];
+      REQUIRE(val == ((i % 2) == 1));
+    }
+
+  std::initializer_list<value_type> il1 = { true, false };
+  auto insert_it1          = bs.insert(std::next(bs.cbegin(), 5), il1);
+  auto expected_insert_it1 = std::next(bs.begin(), 5);
+  const std::size_t post_insert1_size = bs.size();
+  const std::size_t expected_post_insert1_size =
+    il1.size() + expected_post_insert0_size;
+  REQUIRE(insert_it1 == expected_insert_it1);
+  REQUIRE(post_insert1_size == expected_post_insert1_size);
+  for (std::size_t i = 0; i < bs.size(); ++i)
+    {
+      bool val = bs[i];
+      REQUIRE(val == ((i % 2) == 1));
+    }
+
+  std::initializer_list<value_type> il2 = { true, false, true, false, true,
+    false, true, false, true, false, true, false };
+  auto insert_it2          = bs.insert(std::next(bs.cbegin(), 3), il2);
+  auto expected_insert_it2 = std::next(bs.cbegin(), 3);
+  const std::size_t post_insert2_size = bs.size();
+  const std::size_t expected_post_insert2_size =
+    il2.size() + expected_post_insert1_size;
+  REQUIRE(insert_it2 == expected_insert_it2);
+  REQUIRE(post_insert2_size == expected_post_insert2_size);
+  for (std::size_t i = 0; i < bs.size(); ++i)
+    {
+      bool val = bs[i];
+      REQUIRE(val == ((i % 2) == 1));
+    }
+
+  std::initializer_list<value_type> empty_il = {};
+  const std::size_t pre_insert3_size         = bs.size();
+  auto insert_it3          = bs.insert(std::next(bs.cbegin(), 3), empty_il);
+  auto expected_insert_it3 = std::next(bs.cbegin(), 3);
+  const std::size_t post_insert3_size = bs.size();
+  const std::size_t expected_insert3_size =
+    empty_il.size() + expected_post_insert2_size;
+  REQUIRE(insert_it3 == expected_insert_it3);
+  REQUIRE(bs.size() == pre_insert3_size);
+  REQUIRE(bs.size() == post_insert3_size);
+  REQUIRE(pre_insert3_size == expected_insert3_size);
+  REQUIRE(post_insert3_size == expected_insert3_size);
+  for (std::size_t i = 0; i < bs.size(); ++i)
+    {
+      bool val = bs[i];
+      REQUIRE(val == ((i % 2) == 1));
+    }
+}
+
+template<typename TestType, typename BitSequence>
+void
+bit_sequence_insert_erase_test_bulk_small(BitSequence& bs)
+{
+  REQUIRE(bs.empty());
+  REQUIRE(bs.size() == 0);
+
+  auto insert_it0 = bs.insert(bs.cbegin(), { false, true, false, true, false });
+  auto expected_insert_it0 = bs.begin();
+  REQUIRE(insert_it0 == expected_insert_it0);
+  REQUIRE(bs.size() == 5);
+  for (std::size_t i = 0; i < bs.size(); ++i)
+    {
+      bool val = bs[i];
+      REQUIRE(val == ((i % 2) == 1));
+    }
+
+  auto insert_it1 = bs.insert(std::next(bs.cbegin(), 5), { true, false });
+  auto expected_insert_it1 = std::next(bs.begin(), 5);
+  REQUIRE(insert_it1 == expected_insert_it1);
+  REQUIRE(bs.size() == 7);
+  for (std::size_t i = 0; i < bs.size(); ++i)
+    {
+      bool val = bs[i];
+      REQUIRE(val == ((i % 2) == 1));
+    }
+
+  auto erase_it0          = bs.erase(bs.cend() - 3, bs.cend());
+  auto expected_erase_it0 = bs.cend();
+  REQUIRE(erase_it0 == expected_erase_it0);
+  REQUIRE(bs.size() == 4);
+  REQUIRE_FALSE(bs.empty());
+
+  bool val0 = bs[0];
+  bool val1 = bs[1];
+  bool val2 = bs[2];
+  bool val3 = bs[3];
+  REQUIRE_FALSE(val0);
+  REQUIRE(val1);
+  REQUIRE_FALSE(val2);
+  REQUIRE(val3);
+
+  auto erase_it1          = bs.erase(bs.cbegin(), bs.cbegin() + 4);
+  auto expected_erase_it1 = bs.end();
+  REQUIRE(erase_it1 == expected_erase_it1);
+  REQUIRE(erase_it1 == bs.cbegin());
+  REQUIRE(erase_it1 == bs.cend());
+  REQUIRE(bs.size() == 0);
+  REQUIRE(bs.empty());
+}
+
+template<typename TestType, typename BitSequence>
+void
+bit_sequence_insert_erase_test_bulk_large(BitSequence& bs)
+{
+	REQUIRE(bs.empty());
+	REQUIRE(bs.size() == 0);
+
+	const std::size_t full_binary_bits = __gnu_cxx::binary_digits_v<TestType>;
+	const std::size_t high_half_binary_bits =
+	  (__gnu_cxx::binary_digits_v<TestType> / 2) + static_cast<std::size_t>(std::is_signed_v<TestType>);
+	const std::size_t low_half_binary_bits = (__gnu_cxx::binary_digits_v<TestType> / 2);
+
+	std::vector<TestType> insertion_storage(15, static_cast<TestType>(0));
+	__gnu_cxx::bit_view<std::span<TestType>> insertion_view(insertion_storage);
+	{
+		auto start  = insertion_view.begin();
+		auto finish = insertion_view.end();
+		for (std::size_t i = 0; start != finish; ++start, ++i)
+			{
+				*start = is_even_respecting_boundaries<TestType>(i);
+			}
+	}
+
+	auto it_post_insertion = bs.insert(bs.cbegin(), insertion_view.begin(), insertion_view.end());
+	auto it_post_insertion_dist = std::distance(bs.begin(), it_post_insertion);
+	REQUIRE(it_post_insertion_dist == 0);
+	const std::size_t post_insertion_size          = bs.size();
+	const std::size_t expected_post_insertion_size = insertion_view.size();
+	REQUIRE(post_insertion_size == expected_post_insertion_size);
+	{
+		auto start    = insertion_view.begin();
+		auto finish   = insertion_view.end();
+		auto bsstart  = bs.begin();
+		auto bsfinish = bs.end();
+		for (std::size_t i = 0; start != finish; ++i, ++bsstart, ++start)
+			{
+				bool expected = is_even_respecting_boundaries<TestType>(i);
+				bool iv_val   = *start;
+				bool bs_val   = *bsstart;
+				REQUIRE(expected == iv_val);
+				REQUIRE(expected == bs_val);
+				REQUIRE(bs_val == iv_val);
+			}
+		REQUIRE(bsstart == bsfinish);
+	}
+
+	auto it_post_erase0      = bs.erase(bs.begin(), bs.begin() + full_binary_bits);
+	auto it_post_erase0_dist = std::distance(bs.begin(), it_post_erase0);
+	REQUIRE(it_post_erase0_dist == 0);
+	const std::size_t post_erase_size0          = bs.size();
+	const std::size_t expected_post_erase_size0 = (post_insertion_size - full_binary_bits);
+	REQUIRE(post_erase_size0 == expected_post_erase_size0);
+	{
+		auto bsstart  = bs.cbegin();
+		auto bsfinish = bs.cend();
+		for (std::size_t i = 0; bsstart != bsfinish; ++i, ++bsstart)
+			{
+				bool expected = is_even_respecting_boundaries<TestType>(i);
+				bool bs_val   = *bsstart;
+				REQUIRE(expected == bs_val);
+			}
+	}
+
+	auto it_post_erase1      = bs.erase(bs.begin(), bs.begin() + (full_binary_bits * 3));
+	auto it_post_erase1_dist = std::distance(bs.begin(), it_post_erase1);
+	REQUIRE(it_post_erase1_dist == 0);
+	const std::size_t post_erase_size1          = bs.size();
+	const std::size_t expected_post_erase_size1 = (post_erase_size0 - full_binary_bits * 3);
+	REQUIRE(post_erase_size1 == expected_post_erase_size1);
+	{
+		auto bsstart  = bs.cbegin();
+		auto bsfinish = bs.cend();
+		for (std::size_t i = 0; bsstart != bsfinish; ++i, ++bsstart)
+			{
+				bool expected = is_even_respecting_boundaries<TestType>(i);
+				bool bs_val   = *bsstart;
+				REQUIRE(expected == bs_val);
+			}
+	}
+
+	auto it_post_erase2      = bs.erase(bs.begin() + 1, bs.begin() + high_half_binary_bits + 1);
+	auto it_post_erase2_dist = std::distance(bs.begin(), it_post_erase2);
+	REQUIRE(it_post_erase2_dist == 1);
+	const std::size_t post_erase_size2          = bs.size();
+	const std::size_t expected_post_erase_size2 = (post_erase_size1 - high_half_binary_bits);
+	REQUIRE(post_erase_size2 == expected_post_erase_size2);
+	if constexpr (!std::is_signed_v<TestType>)
+		{
+			auto bsstart  = bs.cbegin();
+			auto bsfinish = bs.cend();
+			for (std::size_t i = 0; bsstart != bsfinish; ++i, ++bsstart)
+				{
+					bool expected = is_even_respecting_boundaries<TestType>(i);
+					bool bs_val   = *bsstart;
+					REQUIRE(expected == bs_val);
+				}
+		}
+
+	auto it_post_erase3 =
+	  bs.erase(bs.begin() + 1, bs.begin() + (full_binary_bits + low_half_binary_bits) + 1);
+	auto it_post_erase3_dist = std::distance(bs.begin(), it_post_erase3);
+	REQUIRE(it_post_erase3_dist == 1);
+	const std::size_t post_erase_size3 = bs.size();
+	const std::size_t expected_post_erase_size3 =
+	  (post_erase_size2 - (full_binary_bits + low_half_binary_bits));
+	REQUIRE(post_erase_size3 == expected_post_erase_size3);
+	{
+		auto bsstart  = bs.cbegin();
+		auto bsfinish = bs.cend();
+		for (std::size_t i = 0; bsstart != bsfinish; ++i, ++bsstart)
+			{
+				bool expected = is_even_respecting_boundaries<TestType>(i);
+				bool bs_val   = *bsstart;
+				REQUIRE(expected == bs_val);
+			}
+	}
+
+	auto it_post_erase4      = bs.erase(bs.begin(), bs.begin() + 3);
+	auto it_post_erase4_dist = std::distance(bs.begin(), it_post_erase4);
+	REQUIRE(it_post_erase4_dist == 0);
+	const std::size_t post_erase_size4          = bs.size();
+	const std::size_t expected_post_erase_size4 = (post_erase_size3 - 3);
+	REQUIRE(post_erase_size4 == expected_post_erase_size4);
+	if constexpr (!std::is_signed_v<TestType>)
+		{
+			auto bsstart  = bs.cbegin();
+			auto bsfinish = bs.cend();
+			for (std::size_t i = 0; bsstart != bsfinish; ++i, ++bsstart)
+				{
+					bool expected = !is_even_respecting_boundaries<TestType>(i);
+					bool bs_val   = *bsstart;
+					REQUIRE(expected == bs_val);
+				}
+		}
+
+	auto it_post_erase5      = bs.erase(bs.begin(), bs.begin() + 1);
+	auto it_post_erase5_dist = std::distance(bs.begin(), it_post_erase5);
+	REQUIRE(it_post_erase5_dist == 0);
+	const std::size_t post_erase_size5          = bs.size();
+	const std::size_t expected_post_erase_size5 = (post_erase_size4 - 1);
+	REQUIRE(post_erase_size5 == expected_post_erase_size5);
+	if constexpr (!std::is_signed_v<TestType>)
+		{
+			auto bsstart  = bs.cbegin();
+			auto bsfinish = bs.cend();
+			for (std::size_t i = 0; bsstart != bsfinish; ++i, ++bsstart)
+				{
+					bool expected = is_even_respecting_boundaries<TestType>(i);
+					bool bs_val   = *bsstart;
+					REQUIRE(expected == bs_val);
+				}
+		}
+
+	auto it_post_erase6      = bs.erase(bs.begin(), bs.begin() + 4);
+	auto it_post_erase6_dist = std::distance(bs.begin(), it_post_erase6);
+	REQUIRE(it_post_erase6_dist == 0);
+	const std::size_t post_erase_size6          = bs.size();
+	const std::size_t expected_post_erase_size6 = (post_erase_size5 - 4);
+	REQUIRE(post_erase_size6 == expected_post_erase_size6);
+	if constexpr (!std::is_signed_v<TestType>)
+		{
+			auto bsstart  = bs.cbegin();
+			auto bsfinish = bs.cend();
+			for (std::size_t i = 0; bsstart != bsfinish; ++i, ++bsstart)
+				{
+					bool expected = is_even_respecting_boundaries<TestType>(i);
+					bool bs_val   = *bsstart;
+					REQUIRE(expected == bs_val);
+				}
+		}
+
+	auto it_post_erase7      = bs.erase(bs.cbegin(), bs.cend());
+	auto it_post_erase7_dist = std::distance(bs.begin(), it_post_erase7);
+	REQUIRE(it_post_erase7_dist == 0);
+	const std::size_t post_erase_size7          = bs.size();
+	const std::size_t expected_post_erase_size7 = 0;
+	REQUIRE(post_erase_size7 == expected_post_erase_size7);
+	REQUIRE(it_post_erase7 == bs.cend());
+}
+
+#endif
diff --git a/libstdc++-v3/testsuite/ext/bit_ds/bit_ds_tests_shared_tests.h b/libstdc++-v3/testsuite/ext/bit_ds/bit_ds_tests_shared_tests.h
new file mode 100644
index 00000000000..d70d3abf5b3
--- /dev/null
+++ b/libstdc++-v3/testsuite/ext/bit_ds/bit_ds_tests_shared_tests.h
@@ -0,0 +1,329 @@
+// bit data structures extension tests -*- C++ -*-
+
+// Copyright (C) 2019-2019 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// Under Section 7 of GPL version 3, you are granted additional
+// permissions described in the GCC Runtime Library Exception, version
+// 3.1, as published by the Free Software Foundation.
+
+// You should have received a copy of the GNU General Public License and
+// a copy of the GCC Runtime Library Exception along with this program;
+// see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+// <http://www.gnu.org/licenses/>.
+
+#pragma once
+
+#ifndef _EXT_BIT_DS_TESTS_SHARED_TESTS_H
+#define _EXT_BIT_DS_TESTS_SHARED_TESTS_H 1
+
+#include "bit_ds_tests_require.h"
+
+#include "bit_ds_tests_constants.h"
+
+#include <ext/bit>
+
+template<typename BitView>
+void
+bit_view_test_mixed_any_all_none(BitView& view_bits)
+{
+  REQUIRE_FALSE(view_bits.none());
+  REQUIRE_FALSE(view_bits.all());
+  REQUIRE(view_bits.any());
+}
+
+template<typename TestType, typename BitView, typename On, typename Off>
+void
+bit_view_test_iteration(BitView& view_bits, On& on_indices, Off& off_indices,
+  std::size_t expected_bits = expected_words *
+                              __gnu_cxx::binary_digits_v<TestType>)
+{
+  const std::size_t expected_on_bits  = std::size(on_indices);
+  const std::size_t expected_off_bits = expected_bits - expected_on_bits;
+
+  for (const auto& off_index : off_indices)
+    {
+      bool off_index_bit = view_bits[off_index];
+      REQUIRE_FALSE(off_index_bit);
+      REQUIRE(off_index_bit == view_bits.test(off_index));
+    }
+
+  for (const auto& on_index : on_indices)
+    {
+      bool on_index_bit = view_bits[on_index];
+      REQUIRE(on_index_bit);
+      REQUIRE(on_index_bit == view_bits.test(on_index));
+    }
+
+  {
+    std::size_t iter_count     = 0;
+    std::size_t iter_on_count  = 0;
+    std::size_t iter_off_count = 0;
+    for (const auto& ref : view_bits)
+      {
+        ++iter_count;
+        if (ref)
+          {
+            ++iter_on_count;
+          }
+        else
+          {
+            ++iter_off_count;
+          }
+      }
+    REQUIRE(iter_count == expected_bits);
+    REQUIRE(iter_on_count == expected_on_bits);
+    REQUIRE(iter_off_count == expected_off_bits);
+  }
+
+  REQUIRE(view_bits.one_count() == expected_on_bits);
+  REQUIRE(view_bits.count(true) == expected_on_bits);
+  REQUIRE(view_bits.count(false) == expected_off_bits);
+}
+
+template<typename BitView>
+void
+bit_view_test_iterator_comparisons(BitView& view_bits)
+{
+  auto first = view_bits.begin();
+  auto lower = first;
+  ++lower;
+  auto upper = lower;
+  ++upper;
+  auto last = view_bits.end();
+
+  REQUIRE(first == first);
+  REQUIRE(lower == lower);
+  REQUIRE(upper == upper);
+  REQUIRE(last == last);
+
+  REQUIRE(first != lower);
+  REQUIRE(first != upper);
+  REQUIRE(first != last);
+
+  REQUIRE(lower != first);
+  REQUIRE(lower != upper);
+  REQUIRE(lower != last);
+
+  REQUIRE(upper != first);
+  REQUIRE(upper != lower);
+  REQUIRE(upper != last);
+
+  REQUIRE(last != first);
+  REQUIRE(last != lower);
+  REQUIRE(last != upper);
+
+  REQUIRE(first < lower);
+  REQUIRE(first < upper);
+  REQUIRE(first < last);
+
+  REQUIRE(last > first);
+  REQUIRE(last > lower);
+  REQUIRE(last > upper);
+
+  REQUIRE(first <= first);
+  REQUIRE(first <= lower);
+  REQUIRE(first <= upper);
+  REQUIRE(first <= last);
+
+  REQUIRE(last >= first);
+  REQUIRE(last >= lower);
+  REQUIRE(last >= upper);
+  REQUIRE(last >= last);
+}
+
+template<typename TestType, typename BitSpan, typename On>
+void
+bit_view_test_writability(BitSpan& span_bits, On& on_indices,
+  std::size_t expected_bits = expected_words *
+                              __gnu_cxx::binary_digits_v<TestType>)
+{
+  const std::size_t initial_expected_on_bits = std::size(on_indices);
+  const std::size_t initial_expected_off_bits =
+    expected_bits - initial_expected_on_bits;
+
+  std::size_t post_expected_on_bits  = 0;
+  std::size_t post_expected_off_bits = expected_bits - post_expected_on_bits;
+
+  REQUIRE(span_bits.one_count() == initial_expected_on_bits);
+  REQUIRE(span_bits.count(true) == initial_expected_on_bits);
+  REQUIRE(span_bits.count(false) == initial_expected_off_bits);
+
+  for (const auto& flip_index : on_indices)
+    {
+      auto flip_index_bit = span_bits[flip_index];
+      REQUIRE(flip_index_bit);
+      REQUIRE(flip_index_bit == span_bits.test(flip_index));
+      span_bits.flip(flip_index);
+      REQUIRE_FALSE(flip_index_bit);
+      REQUIRE(flip_index_bit == span_bits.test(flip_index));
+    }
+
+  REQUIRE(span_bits.one_count() == post_expected_on_bits);
+  REQUIRE(span_bits.count(true) == post_expected_on_bits);
+  REQUIRE(span_bits.count(false) == post_expected_off_bits);
+
+  for (const auto& flip_index : on_indices)
+    {
+      auto flip_index_bit = span_bits[flip_index];
+      REQUIRE_FALSE(flip_index_bit);
+      REQUIRE(flip_index_bit == span_bits.test(flip_index));
+      flip_index_bit = !static_cast<bool>(flip_index_bit);
+      REQUIRE(flip_index_bit);
+      REQUIRE(flip_index_bit == span_bits.test(flip_index));
+    }
+
+  REQUIRE(span_bits.one_count() == initial_expected_on_bits);
+  REQUIRE(span_bits.count(true) == initial_expected_on_bits);
+  REQUIRE(span_bits.count(false) == initial_expected_off_bits);
+
+  for (const auto& set_index : on_indices)
+    {
+      auto set_index_bit = span_bits[set_index];
+      REQUIRE(set_index_bit);
+      REQUIRE(set_index_bit == span_bits.test(set_index));
+      span_bits.set(set_index, false);
+      REQUIRE_FALSE(set_index_bit);
+      REQUIRE(set_index_bit == span_bits.test(set_index));
+    }
+
+  REQUIRE(span_bits.one_count() == post_expected_on_bits);
+  REQUIRE(span_bits.count(true) == post_expected_on_bits);
+  REQUIRE(span_bits.count(false) == post_expected_off_bits);
+
+  for (const auto& set_index : on_indices)
+    {
+      auto set_index_bit = span_bits[set_index];
+      REQUIRE_FALSE(set_index_bit);
+      REQUIRE(set_index_bit == span_bits.test(set_index));
+      span_bits.set(set_index, true);
+      REQUIRE(set_index_bit);
+      REQUIRE(set_index_bit == span_bits.test(set_index));
+    }
+
+  REQUIRE(span_bits.one_count() == initial_expected_on_bits);
+  REQUIRE(span_bits.count(true) == initial_expected_on_bits);
+  REQUIRE(span_bits.count(false) == initial_expected_off_bits);
+
+  for (const auto& set_index : on_indices)
+    {
+      auto set_index_bit = span_bits[set_index];
+      REQUIRE(set_index_bit);
+      REQUIRE(set_index_bit == span_bits.test(set_index));
+      span_bits[set_index] = false;
+      REQUIRE_FALSE(set_index_bit);
+      REQUIRE(set_index_bit == span_bits.test(set_index));
+    }
+
+  REQUIRE(span_bits.one_count() == post_expected_on_bits);
+  REQUIRE(span_bits.count(true) == post_expected_on_bits);
+  REQUIRE(span_bits.count(false) == post_expected_off_bits);
+
+  for (const auto& set_index : on_indices)
+    {
+      auto set_index_bit = span_bits[set_index];
+      REQUIRE_FALSE(set_index_bit);
+      REQUIRE(set_index_bit == span_bits.test(set_index));
+      span_bits[set_index] = true;
+      REQUIRE(set_index_bit);
+      REQUIRE(set_index_bit == span_bits.test(set_index));
+    }
+
+  REQUIRE(span_bits.popcount() == initial_expected_on_bits);
+  REQUIRE(span_bits.count(true) == initial_expected_on_bits);
+  REQUIRE(span_bits.count(false) == initial_expected_off_bits);
+}
+
+template<typename TestType, bool check_iterator_comparisons = true,
+  bool check_writability = true, typename Storage, typename OnIndices,
+  typename OffIndices>
+void
+generic_bit_tests(Storage& storage, OnIndices& on_indices,
+  OffIndices& off_indices,
+  std::size_t expected_bits = expected_words *
+                              __gnu_cxx::binary_digits_v<TestType>)
+{
+  using span_range  = std::span<TestType>;
+  using sub_range   = std::ranges::subrange<decltype(std::begin(storage)),
+    decltype(std::end(storage))>;
+  using c_sub_range = std::ranges::subrange<decltype(std::cbegin(storage)),
+    decltype(std::cend(storage))>;
+  using R = std::conditional_t<std::is_constructible_v<span_range, Storage&>,
+    span_range,
+    std::conditional_t<std::is_const_v<TestType>, c_sub_range, sub_range>>;
+
+  if constexpr (check_iterator_comparisons)
+    {
+      REQUIRE(std::size(storage) == expected_words);
+      __gnu_cxx::bit_view<R> truncated_view_bits(
+        &storage[0], std::size(storage) / 2);
+      REQUIRE(truncated_view_bits.size() == expected_bits / 2);
+    }
+
+  __gnu_cxx::bit_view<R> view_bits(storage);
+  REQUIRE(view_bits.size() == expected_bits);
+
+  bit_view_test_mixed_any_all_none(view_bits);
+  bit_view_test_iteration<TestType>(
+    view_bits, on_indices, off_indices, expected_bits);
+  if constexpr (check_iterator_comparisons)
+    {
+      bit_view_test_iterator_comparisons(view_bits);
+    }
+  if constexpr (check_writability)
+    {
+      bit_view_test_writability<TestType>(view_bits, on_indices, expected_bits);
+    }
+}
+
+template<typename TestType, bool check_iterator_comparisons = true,
+  bool check_writability = true, typename Storage, typename OnIndices,
+  typename OffIndices>
+void
+generic_bit_bounds_tests(Storage& storage, OnIndices& on_indices,
+  OffIndices& off_indices, std::size_t expected_bits = 22)
+{
+  using span_range  = std::span<TestType>;
+  using sub_range   = std::ranges::subrange<decltype(std::begin(storage)),
+    decltype(std::end(storage))>;
+  using c_sub_range = std::ranges::subrange<decltype(std::cbegin(storage)),
+    decltype(std::cend(storage))>;
+  using R = std::conditional_t<std::is_constructible_v<span_range, Storage&>,
+    span_range,
+    std::conditional_t<std::is_const_v<TestType>, c_sub_range, sub_range>>;
+
+  if constexpr (std::is_same_v<span_range, R>)
+    {
+      __gnu_cxx::bit_view<R, __gnu_cxx::dynamic_bit_bounds_for<R>> truncated_view_bits(
+          { 0, expected_bits / 2 }, &storage[0], std::size(storage) / 2);
+      REQUIRE(truncated_view_bits.size() == expected_bits / 2);
+    }
+
+  __gnu_cxx::bit_view<R, __gnu_cxx::dynamic_bit_bounds_for<R>> view_bits(
+    { 0, expected_bits }, storage);
+  REQUIRE(view_bits.size() == expected_bits);
+
+  bit_view_test_mixed_any_all_none(view_bits);
+  bit_view_test_iteration<TestType>(
+    view_bits, on_indices, off_indices, expected_bits);
+  if constexpr (check_iterator_comparisons)
+    {
+      bit_view_test_iterator_comparisons(view_bits);
+    }
+  if constexpr (check_writability)
+    {
+      bit_view_test_writability<TestType>(view_bits, on_indices, expected_bits);
+    }
+}
+
+#endif
diff --git a/libstdc++-v3/testsuite/ext/bit_ds/bit_sequence.constructors.cc b/libstdc++-v3/testsuite/ext/bit_ds/bit_sequence.constructors.cc
new file mode 100644
index 00000000000..a866a23df62
--- /dev/null
+++ b/libstdc++-v3/testsuite/ext/bit_ds/bit_sequence.constructors.cc
@@ -0,0 +1,283 @@
+// bit data structures extension tests -*- C++ -*-
+
+// Copyright (C) 2019-2019 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// Under Section 7 of GPL version 3, you are granted additional
+// permissions described in the GCC Runtime Library Exception, version
+// 3.1, as published by the Free Software Foundation.
+
+// You should have received a copy of the GNU General Public License and
+// a copy of the GCC Runtime Library Exception along with this program;
+// see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+// <http://www.gnu.org/licenses/>.
+
+// { dg-do run { target c++2a } }
+
+#include "bit_ds_tests_require.h"
+
+#include <ext/bit>
+
+#include <vector>
+#include <deque>
+#include <list>
+#include <string>
+
+template<typename BitSequence, typename Il>
+void
+test_bitset_constructors_initializer_list(BitSequence& storage, Il& il)
+{
+  REQUIRE(storage.size() == il.size());
+  std::size_t i     = 0;
+  auto storage_last = storage.cend();
+  for (auto storage_it = storage.cbegin(); storage_it != storage_last;
+       ++i, ++storage_it)
+    {
+      const bool val          = *storage_it;
+      const bool expected_val = (i % 2) == 1;
+      REQUIRE(val == expected_val);
+    }
+  REQUIRE(i == storage.size());
+}
+
+template<typename BitSequence, typename SizeType, typename ValueType>
+void
+test_bitset_constructors_num_val(
+  BitSequence& storage, SizeType num, ValueType constructor_val)
+{
+  REQUIRE(storage.size() == num);
+  std::size_t i     = 0;
+  auto storage_last = storage.cend();
+  for (auto storage_it = storage.cbegin(); storage_it != storage_last;
+       ++i, ++storage_it)
+    {
+      const bool val          = *storage_it;
+      const bool expected_val = static_cast<bool>(constructor_val);
+      REQUIRE(val == expected_val);
+    }
+  REQUIRE(i == storage.size());
+}
+
+template<typename BitSequence, typename SizeType>
+void
+test_bitset_constructors_num(BitSequence& storage, SizeType num)
+{
+  test_bitset_constructors_num_val(storage, num, false);
+}
+
+template<typename BitSequence, typename Source, typename First, typename Last>
+void
+test_bitset_constructors_first_last(
+  BitSequence& storage, Source& source, First first, Last last)
+{
+  const std::size_t expected_size = std::size(source);
+  REQUIRE(storage.size() == expected_size);
+  std::size_t i     = 0;
+  auto storage_last = std::cend(storage);
+  for (auto storage_it = std::cbegin(storage); storage_it != storage_last;
+       ++i, ++storage_it, ++first)
+    {
+      const bool val          = *storage_it;
+      const bool expected_val = *first;
+      REQUIRE(val == expected_val);
+    }
+  REQUIRE(i == storage.size());
+  REQUIRE(first == last);
+}
+
+template<typename TestType>
+void
+bit_ds_test_case_bit_sequence_constructors()
+{
+  SECTION("initializer_list")
+  {
+    std::initializer_list<__gnu_cxx::bit_value> il{ false, true, false, true,
+      false, true, false, true, false, true, false, true, false, true, false,
+      true, false, true, false, true, false, true, false, true, false, true,
+      false, true, false, true, false, true, false, true, false, true, false,
+      true, false, true, false, true, false, true, false, true, false, true,
+      false, true, false, true, false, true, false, true, false, true, false,
+      true, false, true, false, true, false, true, false, true, false, true,
+      false, true, false, true, false, true, false, true, false, true, false,
+      true, false, true, false, true, false, true, false, true, false, true,
+      false, true };
+    SECTION("vector")
+    {
+      __gnu_cxx::bit_sequence<std::vector<TestType>> storage(il);
+      test_bitset_constructors_initializer_list(storage, il);
+    }
+    SECTION("std::basic_string")
+    {
+      __gnu_cxx::bit_sequence<std::basic_string<TestType>> storage(il);
+      test_bitset_constructors_initializer_list(storage, il);
+    }
+    SECTION("deque")
+    {
+      __gnu_cxx::bit_sequence<std::deque<TestType>> storage(il);
+      test_bitset_constructors_initializer_list(storage, il);
+    }
+    SECTION("list")
+    {
+      __gnu_cxx::bit_sequence<std::list<TestType>> storage(il);
+      test_bitset_constructors_initializer_list(storage, il);
+    }
+  }
+  SECTION("num")
+  {
+    std::size_t num = 516;
+    SECTION("vector")
+    {
+      __gnu_cxx::bit_sequence<std::vector<TestType>> storage(num);
+      test_bitset_constructors_num(storage, num);
+    }
+    SECTION("std::basic_string")
+    {
+      __gnu_cxx::bit_sequence<std::basic_string<TestType>> storage(num);
+      test_bitset_constructors_num(storage, num);
+    }
+    SECTION("deque")
+    {
+      __gnu_cxx::bit_sequence<std::deque<TestType>> storage(num);
+      test_bitset_constructors_num(storage, num);
+    }
+    SECTION("list")
+    {
+      __gnu_cxx::bit_sequence<std::list<TestType>> storage(num);
+      test_bitset_constructors_num(storage, num);
+    }
+  }
+  SECTION("num, val")
+  {
+    std::size_t num          = 427;
+    __gnu_cxx::bit_value val = true;
+    SECTION("vector")
+    {
+      __gnu_cxx::bit_sequence<std::vector<TestType>> storage(num, val);
+      test_bitset_constructors_num_val(storage, num, val);
+    }
+    SECTION("std::basic_string")
+    {
+      __gnu_cxx::bit_sequence<std::basic_string<TestType>> storage(num, val);
+      test_bitset_constructors_num_val(storage, num, val);
+    }
+    SECTION("deque")
+    {
+      __gnu_cxx::bit_sequence<std::deque<TestType>> storage(num, val);
+      test_bitset_constructors_num_val(storage, num, val);
+    }
+    SECTION("list")
+    {
+      __gnu_cxx::bit_sequence<std::list<TestType>> storage(num, val);
+      test_bitset_constructors_num_val(storage, num, val);
+    }
+  }
+  SECTION("first, last (random access)")
+  {
+    const bool data[] = { false, true, false, false, false, false, false, false,
+      true, false, true, false, false, true, false, false, false, false, false,
+      false, true, false, true, false, false, true, false, false, false, false,
+      false, false, true, false, true, false, false, true, false, false, false,
+      false, false, false, true, false, true, false, false, true, false, false,
+      false, false, false, false, true, false, true, false, false, true, false,
+      false, false, false, false, false, true, false, true, false, false, true,
+      false, false, false, false, false, false, true, false, true, false, false,
+      true, false, false, false, false, false, false, true, false, true, false,
+      false, true, false, false, false, false, false, false, true, false, true,
+      false, false, true, false, false, false, false, false, false, true, false,
+      true, false, false, true, false, false, false, false, false, false, true,
+      false, true, false, true, true, false, false, true, true, true, true,
+      true, true, true, true, false, false, true, true, true, true, true, true,
+      true, true, false, false, true, true, true, true, true, true, true, true,
+      false, false, true, true, true, true, true, true };
+    const bool* first = data + 0;
+    const bool* last  = data + std::size(data);
+    SECTION("vector")
+    {
+      __gnu_cxx::bit_sequence<std::vector<TestType>> storage(first, last);
+      test_bitset_constructors_first_last(storage, data, first, last);
+    }
+    SECTION("std::basic_string")
+    {
+      __gnu_cxx::bit_sequence<std::basic_string<TestType>> storage(first, last);
+      test_bitset_constructors_first_last(storage, data, first, last);
+    }
+    SECTION("deque")
+    {
+      __gnu_cxx::bit_sequence<std::deque<TestType>> storage(first, last);
+      test_bitset_constructors_first_last(storage, data, first, last);
+    }
+    SECTION("list")
+    {
+      __gnu_cxx::bit_sequence<std::list<TestType>> storage(first, last);
+      test_bitset_constructors_first_last(storage, data, first, last);
+    }
+  }
+  SECTION("first, last (non-random-access)")
+  {
+    const std::list<bool> data{ false, true, false, false, false, false, false,
+      false, true, false, true, false, false, true, false, false, false, false,
+      false, false, true, false, true, false, false, true, false, false, false,
+      false, false, false, true, false, true, false, false, true, false, false,
+      false, false, false, false, true, false, true, false, false, true, false,
+      false, false, false, false, false, true, false, true, false, false, true,
+      false, false, false, false, false, false, true, false, true, false, false,
+      true, false, false, false, false, false, false, true, false, true, false,
+      false, true, false, false, false, false, false, false, true, false, true,
+      false, false, true, false, false, false, false, false, false, true, false,
+      true, false, false, true, false, false, false, false, false, false, true,
+      false, true, false, false, true, false, false, false, false, false, false,
+      true, false, true, false, true, true, false, false, true, true, true,
+      true, true, true, true, true, false, false, true, true, true, true, true,
+      true, true, true, false, false, true, true, true, true, true, true, true,
+      true, false, false, true, true, true, true, true, true };
+    auto first = data.cbegin();
+    auto last  = data.cend();
+    SECTION("vector")
+    {
+      __gnu_cxx::bit_sequence<std::vector<TestType>> storage(first, last);
+      test_bitset_constructors_first_last(storage, data, first, last);
+    }
+    SECTION("std::basic_string")
+    {
+      __gnu_cxx::bit_sequence<std::basic_string<TestType>> storage(first, last);
+      test_bitset_constructors_first_last(storage, data, first, last);
+    }
+    SECTION("deque")
+    {
+      __gnu_cxx::bit_sequence<std::deque<TestType>> storage(first, last);
+      test_bitset_constructors_first_last(storage, data, first, last);
+    }
+    SECTION("list")
+    {
+      __gnu_cxx::bit_sequence<std::list<TestType>> storage(first, last);
+      test_bitset_constructors_first_last(storage, data, first, last);
+    }
+  }
+}
+
+template<typename... TestTypes>
+void
+bit_ds_test_cases()
+{
+  (void)std::initializer_list<int>{ 0,
+    (bit_ds_test_case_bit_sequence_constructors<TestTypes>(), 0)... };
+}
+
+int
+main()
+{
+  bit_ds_test_cases<std::uint64_t, std::uint32_t, std::uint16_t, std::uint8_t,
+    std::byte, std::int64_t, std::int32_t, std::int16_t, std::int8_t, char32_t,
+    char16_t, char, unsigned char, signed char, std::size_t, std::ptrdiff_t>();
+  return 0;
+}
diff --git a/libstdc++-v3/testsuite/ext/bit_ds/bit_sequence.insert.cc b/libstdc++-v3/testsuite/ext/bit_ds/bit_sequence.insert.cc
new file mode 100644
index 00000000000..2a614c8d355
--- /dev/null
+++ b/libstdc++-v3/testsuite/ext/bit_ds/bit_sequence.insert.cc
@@ -0,0 +1,78 @@
+// bit data structures extension tests -*- C++ -*-
+
+// Copyright (C) 2019-2019 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// Under Section 7 of GPL version 3, you are granted additional
+// permissions described in the GCC Runtime Library Exception, version
+// 3.1, as published by the Free Software Foundation.
+
+// You should have received a copy of the GNU General Public License and
+// a copy of the GCC Runtime Library Exception along with this program;
+// see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+// <http://www.gnu.org/licenses/>.
+
+// { dg-do run { target c++2a } }
+
+#include "bit_ds_tests_shared_insert_erase_tests.h"
+#include "bit_ds_tests_require.h"
+
+#include <ext/bit>
+
+#include <vector>
+#include <deque>
+#include <list>
+#include <string>
+
+template<typename TestType>
+void
+bit_ds_test_bit_sequence_insert_bulk_small()
+{
+  SECTION("vector")
+  {
+    __gnu_cxx::bit_sequence<std::vector<TestType>> storage;
+    bit_sequence_insert_test_bulk_small<TestType>(storage);
+  }
+  SECTION("std::basic_string")
+  {
+    __gnu_cxx::bit_sequence<std::basic_string<TestType>> storage;
+    bit_sequence_insert_test_bulk_small<TestType>(storage);
+  }
+  SECTION("deque")
+  {
+    __gnu_cxx::bit_sequence<std::deque<TestType>> storage;
+    bit_sequence_insert_test_bulk_small<TestType>(storage);
+  }
+  SECTION("list")
+  {
+    __gnu_cxx::bit_sequence<std::list<TestType>> storage;
+    bit_sequence_insert_test_bulk_small<TestType>(storage);
+  }
+}
+
+template<typename... TestTypes>
+void
+bit_ds_test_cases()
+{
+  (void)std::initializer_list<int>{ 0,
+    (bit_ds_test_bit_sequence_insert_bulk_small<TestTypes>(), 0)... };
+}
+
+int
+main()
+{
+  bit_ds_test_cases<std::uint64_t, std::uint32_t, std::uint16_t, std::uint8_t,
+    std::byte, std::int64_t, std::int32_t, std::int16_t, std::int8_t, char32_t,
+    char16_t, char, unsigned char, signed char, std::size_t, std::ptrdiff_t>();
+  return 0;
+}
diff --git a/libstdc++-v3/testsuite/ext/bit_ds/bit_sequence.insert.erase.clear.bulk.small.cc b/libstdc++-v3/testsuite/ext/bit_ds/bit_sequence.insert.erase.clear.bulk.small.cc
new file mode 100644
index 00000000000..a112af7b72e
--- /dev/null
+++ b/libstdc++-v3/testsuite/ext/bit_ds/bit_sequence.insert.erase.clear.bulk.small.cc
@@ -0,0 +1,79 @@
+// bit data structures extension tests -*- C++ -*-
+
+// Copyright (C) 2019-2019 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// Under Section 7 of GPL version 3, you are granted additional
+// permissions described in the GCC Runtime Library Exception, version
+// 3.1, as published by the Free Software Foundation.
+
+// You should have received a copy of the GNU General Public License and
+// a copy of the GCC Runtime Library Exception along with this program;
+// see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+// <http://www.gnu.org/licenses/>.
+
+// { dg-do run { target c++2a } }
+
+#include "bit_ds_tests_shared_insert_erase_tests.h"
+#include "bit_ds_tests_require.h"
+
+#include <ext/bit>
+
+#include <vector>
+#include <deque>
+#include <list>
+#include <string>
+
+template<typename TestType>
+void
+bit_ds_test_bit_sequence_insert_erase_clear_bulk_small()
+{
+  SECTION("vector")
+  {
+    __gnu_cxx::bit_sequence<std::vector<TestType>> storage;
+    bit_sequence_insert_erase_test_bulk_small<TestType>(storage);
+  }
+  SECTION("std::basic_string")
+  {
+    __gnu_cxx::bit_sequence<std::basic_string<TestType>> storage;
+    bit_sequence_insert_erase_test_bulk_small<TestType>(storage);
+  }
+  SECTION("deque")
+  {
+    __gnu_cxx::bit_sequence<std::deque<TestType>> storage;
+    bit_sequence_insert_erase_test_bulk_small<TestType>(storage);
+  }
+  SECTION("list")
+  {
+    __gnu_cxx::bit_sequence<std::list<TestType>> storage;
+    bit_sequence_insert_erase_test_bulk_small<TestType>(storage);
+  }
+}
+
+template<typename... TestTypes>
+void
+bit_ds_test_cases()
+{
+  (void)std::initializer_list<int>{ 0,
+    (bit_ds_test_bit_sequence_insert_erase_clear_bulk_small<TestTypes>(), 0)...};
+}
+
+int
+main()
+{
+  bit_ds_test_cases<std::uint64_t, std::uint32_t, std::uint16_t, std::uint8_t,
+    std::byte, char32_t, char16_t, unsigned char, std::size_t, std::int64_t,
+    std::int32_t, std::int16_t, std::int8_t, char, signed char,
+    std::ptrdiff_t>();
+  return 0;
+}
diff --git a/libstdc++-v3/testsuite/ext/bit_ds/bit_sequence.insert.erase.clear.cc b/libstdc++-v3/testsuite/ext/bit_ds/bit_sequence.insert.erase.clear.cc
new file mode 100644
index 00000000000..1095133a07e
--- /dev/null
+++ b/libstdc++-v3/testsuite/ext/bit_ds/bit_sequence.insert.erase.clear.cc
@@ -0,0 +1,79 @@
+// bit data structures extension tests -*- C++ -*-
+
+// Copyright (C) 2019-2019 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// Under Section 7 of GPL version 3, you are granted additional
+// permissions described in the GCC Runtime Library Exception, version
+// 3.1, as published by the Free Software Foundation.
+
+// You should have received a copy of the GNU General Public License and
+// a copy of the GCC Runtime Library Exception along with this program;
+// see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+// <http://www.gnu.org/licenses/>.
+
+// { dg-do run { target c++2a } }
+
+#include "bit_ds_tests_shared_insert_erase_tests.h"
+#include "bit_ds_tests_require.h"
+
+#include <ext/bit>
+
+#include <vector>
+#include <deque>
+#include <list>
+#include <string>
+
+template<typename TestType>
+void
+bit_ds_test_bit_sequence_insert_erase_clear()
+{
+  SECTION("vector")
+  {
+    __gnu_cxx::bit_sequence<std::vector<TestType>> storage;
+    bit_sequence_insert_erase_test<TestType>(storage);
+  }
+  SECTION("std::basic_string")
+  {
+    __gnu_cxx::bit_sequence<std::basic_string<TestType>> storage;
+    bit_sequence_insert_erase_test<TestType>(storage);
+  }
+  SECTION("deque")
+  {
+    __gnu_cxx::bit_sequence<std::deque<TestType>> storage;
+    bit_sequence_insert_erase_test<TestType>(storage);
+  }
+  SECTION("list")
+  {
+    __gnu_cxx::bit_sequence<std::list<TestType>> storage;
+    bit_sequence_insert_erase_test<TestType>(storage);
+  }
+}
+
+template<typename... TestTypes>
+void
+bit_ds_test_cases()
+{
+  (void)std::initializer_list<int>{ 0,
+    (bit_ds_test_bit_sequence_insert_erase_clear<TestTypes>(), 0)... };
+}
+
+int
+main()
+{
+  bit_ds_test_cases<std::uint64_t, std::uint32_t, std::uint16_t, std::uint8_t,
+    std::byte, char32_t, char16_t, unsigned char, std::size_t, std::int64_t,
+    std::int32_t, std::int16_t, std::int8_t, char, signed char,
+    std::ptrdiff_t>();
+  return 0;
+}
diff --git a/libstdc++-v3/testsuite/ext/bit_ds/bit_sequence.push_front.push_back.cc b/libstdc++-v3/testsuite/ext/bit_ds/bit_sequence.push_front.push_back.cc
new file mode 100644
index 00000000000..3a5eb18b865
--- /dev/null
+++ b/libstdc++-v3/testsuite/ext/bit_ds/bit_sequence.push_front.push_back.cc
@@ -0,0 +1,234 @@
+// bit data structures extension tests -*- C++ -*-
+
+// Copyright (C) 2019-2019 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// Under Section 7 of GPL version 3, you are granted additional
+// permissions described in the GCC Runtime Library Exception, version
+// 3.1, as published by the Free Software Foundation.
+
+// You should have received a copy of the GNU General Public License and
+// a copy of the GCC Runtime Library Exception along with this program;
+// see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+// <http://www.gnu.org/licenses/>.
+
+// { dg-do run { target c++2a } }
+
+#include "bit_ds_tests_constants.h"
+#include "bit_ds_tests_shared_tests.h"
+#include "bit_ds_tests_require.h"
+
+#include <ext/bit>
+
+#include <cstddef>
+#include <cstdint>
+#include <iterator>
+#include <limits>
+
+#include <vector>
+#include <array>
+#include <deque>
+#include <list>
+#include <forward_list>
+#include <string>
+
+enum class insert_action
+{
+  push_front,
+  push_back,
+  begin,
+  end,
+};
+
+template<insert_action action, typename Sequence, typename Source>
+std::size_t
+insert_into_sequence(Sequence& sequence, Source& source)
+{
+  std::size_t seq_size = sequence.size();
+  for (std::size_t i = 0; i < source.size(); ++i)
+    {
+      bool val = source[i];
+      if constexpr (action == insert_action::push_front)
+        {
+          sequence.push_front(val);
+          REQUIRE(sequence.front() == val);
+        }
+      else if constexpr (action == insert_action::push_back)
+        {
+          sequence.push_back(val);
+          REQUIRE(sequence.back() == val);
+        }
+      else if constexpr (action == insert_action::begin)
+        {
+          sequence.insert(sequence.cbegin(), val);
+          REQUIRE(sequence.front() == val);
+        }
+      else if constexpr (action == insert_action::end)
+        {
+          sequence.insert(sequence.cend(), val);
+          REQUIRE(sequence.back() == val);
+        }
+      std::size_t current_seq_size = sequence.size();
+      REQUIRE(current_seq_size == (seq_size + 1));
+      seq_size = current_seq_size;
+    }
+  return seq_size;
+}
+
+template<typename TestType>
+void
+bit_ds_test_bit_sequence_push_front_push_back()
+{
+  const TestType max = static_cast<TestType>(
+    std::numeric_limits<std::conditional_t<std::is_same_v<TestType, std::byte>,
+      unsigned char, TestType>>::max());
+  const TestType zero = static_cast<TestType>(0ULL);
+
+  std::array<TestType, 2> word_data{ max, zero };
+  std::span<TestType> word_view(word_data.data(), word_data.size());
+  __gnu_cxx::bit_view<std::span<TestType>> word_insertion_view(word_view);
+  __gnu_cxx::bit_view<std::span<TestType>, __gnu_cxx::bit_bounds<0, 13>>
+    static_insertion_view(word_view);
+
+  SECTION("homogenous")
+  {
+    SECTION("on word boundary")
+    {
+      __gnu_cxx::bit_sequence<std::vector<TestType>> sequence0(
+        std::in_place, std::vector<TestType>{ static_cast<TestType>(0),
+                         static_cast<TestType>(1), static_cast<TestType>(2) });
+      __gnu_cxx::bit_sequence<std::vector<TestType>> sequence1(
+        std::in_place, std::vector<TestType>{ static_cast<TestType>(0),
+                         static_cast<TestType>(1), static_cast<TestType>(2) });
+      __gnu_cxx::bit_sequence<std::vector<TestType>> sequence2(
+        std::in_place, std::vector<TestType>{ static_cast<TestType>(0),
+                         static_cast<TestType>(1), static_cast<TestType>(2) });
+      __gnu_cxx::bit_sequence<std::vector<TestType>> sequence3(
+        std::in_place, std::vector<TestType>{ static_cast<TestType>(0),
+                         static_cast<TestType>(1), static_cast<TestType>(2) });
+
+      std::size_t seq_size0 = insert_into_sequence<insert_action::push_front>(
+        sequence0, word_insertion_view);
+      std::size_t seq_size1 = insert_into_sequence<insert_action::push_back>(
+        sequence1, word_insertion_view);
+      std::size_t seq_size2 = insert_into_sequence<insert_action::begin>(
+        sequence2, word_insertion_view);
+      std::size_t seq_size3 = insert_into_sequence<insert_action::end>(
+        sequence3, word_insertion_view);
+
+      REQUIRE(seq_size0 == seq_size2);
+      REQUIRE(seq_size1 == seq_size3);
+
+      REQUIRE(sequence0 == sequence2);
+      REQUIRE_FALSE(sequence0 != sequence2);
+      REQUIRE_FALSE(sequence0 < sequence2);
+      REQUIRE_FALSE(sequence0 > sequence2);
+      REQUIRE(sequence0 <= sequence2);
+      REQUIRE(sequence0 >= sequence2);
+
+      REQUIRE(sequence1 == sequence3);
+      REQUIRE_FALSE(sequence1 != sequence3);
+      REQUIRE_FALSE(sequence1 < sequence3);
+      REQUIRE_FALSE(sequence1 > sequence3);
+      REQUIRE(sequence1 <= sequence3);
+      REQUIRE(sequence1 >= sequence3);
+
+      REQUIRE_FALSE(sequence0 == sequence1);
+      REQUIRE(sequence0 != sequence1);
+      REQUIRE_FALSE(sequence0 < sequence1);
+      REQUIRE(sequence0 > sequence1);
+      REQUIRE_FALSE(sequence0 <= sequence1);
+      REQUIRE(sequence0 >= sequence1);
+
+      REQUIRE_FALSE(sequence2 == sequence3);
+      REQUIRE(sequence2 != sequence3);
+      REQUIRE_FALSE(sequence2 < sequence3);
+      REQUIRE(sequence2 > sequence3);
+      REQUIRE_FALSE(sequence2 <= sequence3);
+      REQUIRE(sequence2 >= sequence3);
+    }
+    SECTION("off word boundary")
+    {
+      __gnu_cxx::bit_sequence<std::vector<TestType>> sequence0(
+        std::in_place, std::vector<TestType>{ static_cast<TestType>(0),
+                         static_cast<TestType>(1), static_cast<TestType>(2) });
+      __gnu_cxx::bit_sequence<std::vector<TestType>> sequence1(
+        std::in_place, std::vector<TestType>{ static_cast<TestType>(0),
+                         static_cast<TestType>(1), static_cast<TestType>(2) });
+      __gnu_cxx::bit_sequence<std::vector<TestType>> sequence2(
+        std::in_place, std::vector<TestType>{ static_cast<TestType>(0),
+                         static_cast<TestType>(1), static_cast<TestType>(2) });
+      __gnu_cxx::bit_sequence<std::vector<TestType>> sequence3(
+        std::in_place, std::vector<TestType>{ static_cast<TestType>(0),
+                         static_cast<TestType>(1), static_cast<TestType>(2) });
+
+      std::size_t seq_size0 = insert_into_sequence<insert_action::push_front>(
+        sequence0, static_insertion_view);
+      std::size_t seq_size1 = insert_into_sequence<insert_action::push_back>(
+        sequence1, static_insertion_view);
+      std::size_t seq_size2 = insert_into_sequence<insert_action::begin>(
+        sequence2, static_insertion_view);
+      std::size_t seq_size3 = insert_into_sequence<insert_action::end>(
+        sequence3, static_insertion_view);
+
+      REQUIRE(seq_size0 == seq_size2);
+      REQUIRE(seq_size1 == seq_size3);
+
+      REQUIRE(sequence0 == sequence2);
+      REQUIRE_FALSE(sequence0 != sequence2);
+      REQUIRE_FALSE(sequence0 < sequence2);
+      REQUIRE_FALSE(sequence0 > sequence2);
+      REQUIRE(sequence0 <= sequence2);
+      REQUIRE(sequence0 >= sequence2);
+
+      REQUIRE(sequence1 == sequence3);
+      REQUIRE_FALSE(sequence1 != sequence3);
+      REQUIRE_FALSE(sequence1 < sequence3);
+      REQUIRE_FALSE(sequence1 > sequence3);
+      REQUIRE(sequence1 <= sequence3);
+      REQUIRE(sequence1 >= sequence3);
+
+      REQUIRE_FALSE(sequence0 == sequence1);
+      REQUIRE(sequence0 != sequence1);
+      REQUIRE_FALSE(sequence0 < sequence1);
+      REQUIRE(sequence0 > sequence1);
+      REQUIRE_FALSE(sequence0 <= sequence1);
+      REQUIRE(sequence0 >= sequence1);
+
+      REQUIRE_FALSE(sequence2 == sequence3);
+      REQUIRE(sequence2 != sequence3);
+      REQUIRE_FALSE(sequence2 < sequence3);
+      REQUIRE(sequence2 > sequence3);
+      REQUIRE_FALSE(sequence2 <= sequence3);
+      REQUIRE(sequence2 >= sequence3);
+    }
+  }
+}
+
+template<typename... TestTypes>
+void
+bit_ds_test_cases()
+{
+  (void)std::initializer_list<int>{ 0,
+    (bit_ds_test_bit_sequence_push_front_push_back<TestTypes>(), 0)... };
+}
+
+int
+main()
+{
+  bit_ds_test_cases<std::uint64_t, std::uint32_t, std::uint16_t, std::uint8_t,
+    std::byte, char32_t, char16_t, unsigned char, std::size_t, std::int64_t,
+    std::int32_t, std::int16_t, std::int8_t, char, signed char,
+    std::ptrdiff_t>();
+  return 0;
+}
diff --git a/libstdc++-v3/testsuite/ext/bit_ds/bit_sequence.reference_wrapper.cc b/libstdc++-v3/testsuite/ext/bit_ds/bit_sequence.reference_wrapper.cc
new file mode 100644
index 00000000000..12c2ebae6fc
--- /dev/null
+++ b/libstdc++-v3/testsuite/ext/bit_ds/bit_sequence.reference_wrapper.cc
@@ -0,0 +1,100 @@
+// bit data structures extension tests -*- C++ -*-
+
+// Copyright (C) 2019-2019 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// Under Section 7 of GPL version 3, you are granted additional
+// permissions described in the GCC Runtime Library Exception, version
+// 3.1, as published by the Free Software Foundation.
+
+// You should have received a copy of the GNU General Public License and
+// a copy of the GCC Runtime Library Exception along with this program;
+// see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+// <http://www.gnu.org/licenses/>.
+
+// { dg-do run { target c++2a } }
+
+#include "bit_ds_tests_shared_insert_erase_tests.h"
+#include "bit_ds_tests_require.h"
+
+#include <ext/bit>
+
+#include <vector>
+#include <deque>
+#include <list>
+#include <string>
+
+template<typename TestType>
+void
+bit_ds_test_case_bit_sequence_reference_wrapper()
+{
+  SECTION("vector")
+  {
+    std::vector<TestType> backing_storage;
+    {
+      __gnu_cxx::bit_sequence<std::reference_wrapper<std::vector<TestType>>>
+        storage(std::in_place, backing_storage);
+      bit_sequence_insert_test_bulk_small<TestType>(storage);
+    }
+    REQUIRE(backing_storage.size() > 0);
+  }
+  SECTION("std::basic_string")
+  {
+    std::basic_string<TestType> backing_storage;
+    {
+      __gnu_cxx::bit_sequence<
+        std::reference_wrapper<std::basic_string<TestType>>>
+        storage(std::in_place, backing_storage);
+      bit_sequence_insert_test_bulk_small<TestType>(storage);
+    }
+    REQUIRE(backing_storage.size() > 0);
+  }
+  SECTION("deque")
+  {
+    std::deque<TestType> backing_storage;
+    {
+      __gnu_cxx::bit_sequence<std::reference_wrapper<std::deque<TestType>>>
+        storage(std::in_place, backing_storage);
+      bit_sequence_insert_test_bulk_small<TestType>(storage);
+    }
+    REQUIRE(backing_storage.size() > 0);
+  }
+  SECTION("list")
+  {
+    std::list<TestType> backing_storage;
+    {
+      __gnu_cxx::bit_sequence<std::reference_wrapper<std::list<TestType>>>
+        storage(std::in_place, backing_storage);
+      bit_sequence_insert_test_bulk_small<TestType>(storage);
+    }
+    REQUIRE(backing_storage.size() > 0);
+  }
+}
+
+template<typename... TestTypes>
+void
+bit_ds_test_cases()
+{
+  (void)std::initializer_list<int>{ 0,
+    (bit_ds_test_case_bit_sequence_reference_wrapper<TestTypes>(), 0)... };
+}
+
+int
+main()
+{
+  bit_ds_test_cases<std::uint64_t, std::uint32_t, std::uint16_t, std::uint8_t,
+    std::byte, char32_t, char16_t, unsigned char, std::size_t, std::int64_t,
+    std::int32_t, std::int16_t, std::int8_t, char, signed char,
+    std::ptrdiff_t>();
+  return 0;
+}
diff --git a/libstdc++-v3/testsuite/ext/bit_ds/bit_view.bounds.cc b/libstdc++-v3/testsuite/ext/bit_ds/bit_view.bounds.cc
new file mode 100644
index 00000000000..1f3d721f89f
--- /dev/null
+++ b/libstdc++-v3/testsuite/ext/bit_ds/bit_view.bounds.cc
@@ -0,0 +1,102 @@
+// bit data structures extension tests -*- C++ -*-
+
+// Copyright (C) 2019-2019 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// Under Section 7 of GPL version 3, you are granted additional
+// permissions described in the GCC Runtime Library Exception, version
+// 3.1, as published by the Free Software Foundation.
+
+// You should have received a copy of the GNU General Public License and
+// a copy of the GCC Runtime Library Exception along with this program;
+// see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+// <http://www.gnu.org/licenses/>.
+
+// { dg-do run { target c++2a } }
+
+#include "bit_ds_tests_constants.h"
+#include "bit_ds_tests_shared_tests.h"
+#include "bit_ds_tests_require.h"
+
+#include <ext/bit>
+
+#include <cstddef>
+#include <cstdint>
+
+#include <iterator>
+
+#include <vector>
+#include <array>
+#include <deque>
+#include <list>
+#include <forward_list>
+#include <string>
+
+template<typename TestType>
+void
+bit_ds_test_case_bit_view_bounds()
+{
+  // non-exhaustive
+  constexpr std::ptrdiff_t off_indices[] = { 1, 2, 3, 4, 5, 6 };
+  // exhaustive
+  constexpr std::ptrdiff_t on_indices[] = { 0 };
+
+  constexpr std::size_t expected_bits = 15;
+
+  constexpr TestType b00 = static_cast<TestType>(0x00);
+  constexpr TestType b01 = static_cast<TestType>(0x01);
+  constexpr TestType b10 = static_cast<TestType>(0x02);
+
+  SECTION("vector")
+  {
+    std::vector<TestType> storage{ b01, b00, b10, b00, b00, b00, b00, b01, b00,
+      b00, b00, b00, b01, b00, b00, b00, b00, b01, b00, b00, b00, b00, b01, b00,
+      b00, b00, b00, b01, b00, b10 };
+    generic_bit_bounds_tests<TestType, true, true>(
+      storage, on_indices, off_indices, expected_bits);
+  }
+  SECTION("deque")
+  {
+    std::deque<TestType> storage{ b01, b00, b10, b00, b00, b00, b00, b01, b00,
+      b00, b00, b00, b01, b00, b00, b00, b00, b01, b00, b00, b00, b00, b01, b00,
+      b00, b00, b00, b01, b00, b10 };
+    generic_bit_bounds_tests<TestType, true, true>(
+      storage, on_indices, off_indices, expected_bits);
+  }
+  SECTION("deque")
+  {
+    std::deque<TestType> storage{ b01, b00, b10, b00, b00, b00, b00, b01, b00,
+      b00, b00, b00, b01, b00, b00, b00, b00, b01, b00, b00, b00, b00, b01, b00,
+      b00, b00, b00, b01, b00, b10 };
+    generic_bit_bounds_tests<TestType, true, true>(
+      storage, on_indices, off_indices, expected_bits);
+  }
+}
+
+template<typename... TestTypes>
+void
+bit_ds_test_cases()
+{
+  (void)std::initializer_list<int>{ 0,
+    (bit_ds_test_case_bit_view_bounds<TestTypes>(), 0)... };
+}
+
+int
+main()
+{
+  bit_ds_test_cases<std::uint64_t, std::uint32_t, std::uint16_t, std::uint8_t,
+    std::byte, char32_t, char16_t, unsigned char, std::size_t, std::int64_t,
+    std::int32_t, std::int16_t, std::int8_t, char, signed char,
+    std::ptrdiff_t>();
+  return 0;
+}
diff --git a/libstdc++-v3/testsuite/ext/bit_ds/bit_view.flip.set.reset.cc b/libstdc++-v3/testsuite/ext/bit_ds/bit_view.flip.set.reset.cc
new file mode 100644
index 00000000000..e58fff1e2b7
--- /dev/null
+++ b/libstdc++-v3/testsuite/ext/bit_ds/bit_view.flip.set.reset.cc
@@ -0,0 +1,206 @@
+// bit data structures extension tests -*- C++ -*-
+
+// Copyright (C) 2019-2019 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// Under Section 7 of GPL version 3, you are granted additional
+// permissions described in the GCC Runtime Library Exception, version
+// 3.1, as published by the Free Software Foundation.
+
+// You should have received a copy of the GNU General Public License and
+// a copy of the GCC Runtime Library Exception along with this program;
+// see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+// <http://www.gnu.org/licenses/>.
+
+// { dg-do run { target c++2a } }
+
+#include "bit_ds_tests_constants.h"
+#include "bit_ds_tests_require.h"
+
+#include <ext/bit>
+
+#include <cstddef>
+#include <cstdint>
+#include <iterator>
+
+#include <vector>
+#include <array>
+#include <string>
+#include <list>
+
+template<typename Sequence, typename Truth>
+void
+bit_view_test_flip_set_reset(Sequence& sequence, Truth& truth)
+{
+  {
+    auto it       = sequence.cbegin();
+    auto truth_it = truth.cbegin();
+    auto last     = sequence.cend();
+    for (; it != last; ++it, ++truth_it)
+      {
+        bool val          = *it;
+        bool expected_val = *truth_it;
+        REQUIRE(val == expected_val);
+      }
+    REQUIRE(truth_it == truth.cend());
+  }
+  sequence.flip();
+  {
+    auto it       = sequence.cbegin();
+    auto truth_it = truth.cbegin();
+    auto last     = sequence.cend();
+    for (; it != last; ++it, ++truth_it)
+      {
+        bool val          = *it;
+        bool expected_val = !*truth_it;
+        REQUIRE(val == expected_val);
+      }
+    REQUIRE(truth_it == truth.cend());
+  }
+  sequence.flip();
+  {
+    auto it       = sequence.cbegin();
+    auto truth_it = truth.cbegin();
+    auto last     = sequence.cend();
+    for (; it != last; ++it, ++truth_it)
+      {
+        bool val          = *it;
+        bool expected_val = *truth_it;
+        REQUIRE(val == expected_val);
+      }
+    REQUIRE(truth_it == truth.cend());
+  }
+
+  sequence.reset();
+  {
+    auto it   = sequence.cbegin();
+    auto last = sequence.cend();
+    for (; it != last; ++it)
+      {
+        bool val          = *it;
+        bool expected_val = false;
+        REQUIRE(val == expected_val);
+      }
+  }
+  sequence.set();
+  {
+    auto it   = sequence.cbegin();
+    auto last = sequence.cend();
+    for (; it != last; ++it)
+      {
+        bool val          = *it;
+        bool expected_val = true;
+        REQUIRE(val == expected_val);
+      }
+  }
+  sequence.set(false);
+  {
+    auto it   = sequence.cbegin();
+    auto last = sequence.cend();
+    for (; it != last; ++it)
+      {
+        bool val          = *it;
+        bool expected_val = false;
+        REQUIRE(val == expected_val);
+      }
+  }
+  sequence.set(true);
+  {
+    auto it   = sequence.cbegin();
+    auto last = sequence.cend();
+    for (; it != last; ++it)
+      {
+        bool val          = *it;
+        bool expected_val = true;
+        REQUIRE(val == expected_val);
+      }
+  }
+}
+
+template<typename TestType>
+void
+bit_ds_test_case_bit_view_modifiers()
+{
+  constexpr TestType b00 = static_cast<TestType>(0x00);
+  constexpr TestType b01 = static_cast<TestType>(0x01);
+  constexpr TestType b10 = static_cast<TestType>(0x02);
+
+  std::vector<TestType> truth_storage{ b01, b00, b01, b00, b00, b00, b00, b01,
+    b00, b00, b00, b00, b01, b00, b00, b00, b00, b01, b00, b00, b00, b00, b01,
+    b00, b00, b00, b00, b01, b00, b10 };
+  __gnu_cxx::bit_view<std::span<TestType>> truth(truth_storage);
+  std::list<TestType> truth_list_storage{ b01, b00, b01, b00, b00, b00, b00,
+    b01, b00, b00, b00, b00, b01, b00, b00, b00, b00, b01, b00, b00, b00, b00,
+    b01, b00, b00, b00, b00, b01, b00, b10 };
+  auto truth_list_range = std::ranges::make_subrange(truth_list_storage);
+  __gnu_cxx::bit_view<decltype(truth_list_range)> truth_list(truth_list_range);
+
+  SECTION("vector")
+  {
+    std::vector<TestType> backing_storage{ b01, b00, b01, b00, b00, b00, b00,
+      b01, b00, b00, b00, b00, b01, b00, b00, b00, b00, b01, b00, b00, b00, b00,
+      b01, b00, b00, b00, b00, b01, b00, b10 };
+    __gnu_cxx::bit_view<std::span<TestType>> storage(backing_storage);
+    bit_view_test_flip_set_reset(storage, truth);
+  }
+  SECTION("std::array")
+  {
+    std::array<TestType, expected_words> backing_storage{ b01, b00, b01, b00,
+      b00, b00, b00, b01, b00, b00, b00, b00, b01, b00, b00, b00, b00, b01, b00,
+      b00, b00, b00, b01, b00, b00, b00, b00, b01, b00, b10 };
+    __gnu_cxx::bit_view<std::span<TestType>> storage(backing_storage);
+    bit_view_test_flip_set_reset(storage, truth);
+  }
+  SECTION("std::basic_string")
+  {
+    std::basic_string<TestType> backing_storage{ b01, b00, b01, b00, b00, b00,
+      b00, b01, b00, b00, b00, b00, b01, b00, b00, b00, b00, b01, b00, b00, b00,
+      b00, b01, b00, b00, b00, b00, b01, b00, b10 };
+    __gnu_cxx::bit_view<std::span<TestType>> storage(backing_storage);
+    bit_view_test_flip_set_reset(storage, truth);
+  }
+  SECTION("c array")
+  {
+    TestType backing_storage[expected_words]{ b01, b00, b01, b00, b00, b00, b00,
+      b01, b00, b00, b00, b00, b01, b00, b00, b00, b00, b01, b00, b00, b00, b00,
+      b01, b00, b00, b00, b00, b01, b00, b10 };
+    __gnu_cxx::bit_view<std::span<TestType>> storage(backing_storage);
+    bit_view_test_flip_set_reset(storage, truth);
+  }
+  SECTION("std::list")
+  {
+    std::list<TestType> backing_storage{ b01, b00, b01, b00, b00, b00, b00, b01,
+      b00, b00, b00, b00, b01, b00, b00, b00, b00, b01, b00, b00, b00, b00, b01,
+      b00, b00, b00, b00, b01, b00, b10 };
+    auto sr = std::ranges::make_subrange(backing_storage);
+    __gnu_cxx::bit_view<decltype(sr)> storage(sr);
+    bit_view_test_flip_set_reset(storage, truth_list);
+  }
+}
+
+template<typename... TestTypes>
+void
+bit_ds_test_cases()
+{
+  (void)std::initializer_list<int>{ 0,
+    (bit_ds_test_case_bit_view_modifiers<TestTypes>(), 0)... };
+}
+
+int
+main()
+{
+  bit_ds_test_cases<std::uint64_t, std::uint32_t, std::uint16_t, std::uint8_t,
+    std::byte, std::int64_t, std::int32_t, std::int16_t, std::int8_t, char32_t,
+    char16_t, char, unsigned char, signed char, std::size_t, std::ptrdiff_t>();
+  return 0;
+}
diff --git a/libstdc++-v3/testsuite/ext/bit_ds/ranges_fill.h b/libstdc++-v3/testsuite/ext/bit_ds/ranges_fill.h
new file mode 100644
index 00000000000..4321d7e9893
--- /dev/null
+++ b/libstdc++-v3/testsuite/ext/bit_ds/ranges_fill.h
@@ -0,0 +1,122 @@
+// ranges polyfill -*- C++ -*-
+
+// Copyright (C) 2019-2019 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// Under Section 7 of GPL version 3, you are granted additional
+// permissions described in the GCC Runtime Library Exception, version
+// 3.1, as published by the Free Software Foundation.
+
+// You should have received a copy of the GNU General Public License and
+// a copy of the GCC Runtime Library Exception along with this program;
+// see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+// <http://www.gnu.org/licenses/>.
+
+/** @file testsuite/ext/bit_ds/ranges
+ *  This file is a polyfill file for testing.
+ *  It provides the world's laziest incomplete
+ *  std::ranges::subrange implementation.
+ */
+
+#pragma once
+
+#ifndef _EXT_BIT_DS_TESTS_RANGES_POLYFILL_H
+#define _EXT_BIT_DS_TESTS_RANGES_POLYFILL_H 1
+
+#if (defined(__cplusplus) && __cplusplus >= 201703L)
+
+namespace std
+{
+  namespace ranges
+  {
+    enum class subrange_kind : bool
+    {
+      unsized,
+      sized
+    };
+
+    template<typename _Iterator, typename _Sentinel, subrange_kind _Kind = subrange_kind::unsized>
+    class subrange
+    {
+      _Iterator _M_it;
+      _Sentinel _M_sen;
+
+    public:
+      using value_type = typename ::std::iterator_traits<_Iterator>::value_type;
+      using reference  = typename ::std::iterator_traits<_Iterator>::reference;
+      using const_reference  = reference;
+      using iterator   = _Iterator;
+      using const_iterator  = _Iterator;
+      using pointer = typename ::std::iterator_traits<_Iterator>::pointer;
+      using const_pointer = pointer;
+      using difference_type = typename ::std::iterator_traits<_Iterator>::difference_type;
+      using size_type       = ::std::make_unsigned_t<difference_type>;
+
+      constexpr subrange() noexcept = default;
+
+      template <typename _Range, ::std::enable_if_t<!::std::is_same_v<::std::remove_cvref_t<_Range>, subrange>>* = nullptr>
+      constexpr subrange(_Range&& __range) noexcept
+      : subrange(::std::begin(__range), ::std::end(__range))
+      {
+      }
+
+      constexpr subrange(_Iterator __it, _Sentinel __sen) noexcept
+      : _M_it(::std::move(__it)), _M_sen(::std::move(__sen))
+      {
+      }
+
+      constexpr _Iterator
+      begin() const
+      {
+        return _M_it;
+      }
+
+      constexpr _Sentinel
+      end() const
+      {
+        return _M_sen;
+      }
+
+      constexpr _Iterator
+      cbegin() const
+      {
+        return _M_it;
+      }
+
+      constexpr _Sentinel
+      cend() const
+      {
+        return _M_sen;
+      }
+
+      constexpr auto size() const
+      {
+        return ::std::distance(this->_M_it, this->_M_sen);
+      }
+    };
+
+    template<typename _Range>
+    constexpr auto
+    make_subrange(_Range&& __range)
+    {
+      using _It       = decltype(::std::begin(__range));
+      using _Sentinel = decltype(::std::end(__range));
+      return subrange<_It, _Sentinel, subrange_kind::unsized>(
+        ::std::begin(__range), ::std::end(__range));
+    }
+  } // namespace ranges
+} // namespace std
+
+#endif
+
+#endif
diff --git a/libstdc++-v3/testsuite/ext/bit_ds/span_fill.h b/libstdc++-v3/testsuite/ext/bit_ds/span_fill.h
new file mode 100644
index 00000000000..c531f7ec625
--- /dev/null
+++ b/libstdc++-v3/testsuite/ext/bit_ds/span_fill.h
@@ -0,0 +1,144 @@
+// span polyfill -*- C++ -*-
+
+// Copyright (C) 2019-2019 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// Under Section 7 of GPL version 3, you are granted additional
+// permissions described in the GCC Runtime Library Exception, version
+// 3.1, as published by the Free Software Foundation.
+
+// You should have received a copy of the GNU General Public License and
+// a copy of the GCC Runtime Library Exception along with this program;
+// see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+// <http://www.gnu.org/licenses/>.
+
+/** @file testsuite/ext/bit_ds/span
+ *  This file is a polyfill file for a test.
+ *  It provides the world's laziest incomplete
+ *  std::span implementation.
+ */
+
+#pragma once
+
+#ifndef _EXT_BIT_DS_TESTS_SPAN_POLYFILL_H
+#define _EXT_BIT_DS_TESTS_SPAN_POLYFILL_H 1
+
+#if (defined(__cplusplus) && __cplusplus >= 201703L)
+
+#include <cstdint>
+#include <iterator>
+#include <utility>
+#include <bits/range_access.h>
+
+#include <ext/bit_ds/bit_operations.h>
+
+namespace std
+{
+  template<typename _Type,
+    ::std::size_t _Extent = static_cast<::std::size_t>(-1)>
+  class span
+  {
+    _Type* _M_it;
+    _Type* _M_sen;
+
+  public:
+    using element_type    = _Type;
+    using value_type      = ::std::remove_cv_t<_Type>;
+    using reference       = _Type&;
+    using const_reference = const _Type&;
+    using pointer         = _Type*;
+    using const_pointer   = const _Type*;
+    using iterator        = pointer;
+    using const_iterator  = const_pointer;
+    using difference_type = ::std::ptrdiff_t;
+    using size_type       = ::std::size_t;
+    using index_type      = ::std::size_t;
+
+    constexpr span() noexcept : span(nullptr, nullptr)
+    {
+    }
+
+    constexpr span(const span&) noexcept = default;
+    constexpr span&
+    operator=(const span&) noexcept = default;
+
+    template<typename _Range,
+      ::std::enable_if_t<
+        !::std::is_same_v<::std::remove_reference_t<::std::remove_cv_t<_Range>>,
+          span> &&
+        ::std::is_convertible_v<::std::remove_pointer_t<decltype(
+                                  ::std::data(::std::declval<_Range&>()))> (*)[],
+          element_type (*)[]>>* = nullptr>
+    constexpr span(_Range&& __range) noexcept
+    : _M_it(::std::data(__range))
+    , _M_sen(::std::data(__range) + ::std::size(__range))
+    {
+    }
+
+    constexpr span(_Type* __it, _Type* __sen) noexcept
+    : _M_it(std::move(__it)), _M_sen(::std::move(__sen))
+    {
+    }
+
+    constexpr span(_Type* __it, size_type __count) noexcept
+    : _M_it(__it), _M_sen(__it + __count)
+    {
+    }
+
+    constexpr iterator
+    begin() const noexcept
+    {
+      return this->_M_it;
+    }
+
+    constexpr iterator
+    end() const noexcept
+    {
+      return this->_M_sen;
+    }
+
+    constexpr const_iterator
+    cbegin() const noexcept
+    {
+      return this->_M_it;
+    }
+
+    constexpr const_iterator
+    cend() const noexcept
+    {
+      return this->_M_sen;
+    }
+
+    constexpr auto
+    data() noexcept
+    {
+      return this->_M_it;
+    }
+
+    constexpr auto
+    data() const noexcept
+    {
+      return this->_M_it;
+    }
+
+    constexpr auto
+    size() const noexcept
+    {
+      return this->_M_sen - this->_M_it;
+    }
+  };
+} // namespace std
+
+#endif
+
+#endif


More information about the Libstdc++ mailing list