summaryrefslogtreecommitdiff
path: root/third_party/libcxx/include/c++/v1/experimental
diff options
context:
space:
mode:
Diffstat (limited to 'third_party/libcxx/include/c++/v1/experimental')
-rw-r--r--third_party/libcxx/include/c++/v1/experimental/__simd/aligned_tag.h75
-rw-r--r--third_party/libcxx/include/c++/v1/experimental/__simd/declaration.h88
-rw-r--r--third_party/libcxx/include/c++/v1/experimental/__simd/reference.h192
-rw-r--r--third_party/libcxx/include/c++/v1/experimental/__simd/scalar.h102
-rw-r--r--third_party/libcxx/include/c++/v1/experimental/__simd/simd.h155
-rw-r--r--third_party/libcxx/include/c++/v1/experimental/__simd/simd_mask.h97
-rw-r--r--third_party/libcxx/include/c++/v1/experimental/__simd/traits.h75
-rw-r--r--third_party/libcxx/include/c++/v1/experimental/__simd/utility.h103
-rw-r--r--third_party/libcxx/include/c++/v1/experimental/__simd/vec_ext.h130
-rw-r--r--third_party/libcxx/include/c++/v1/experimental/iterator140
-rw-r--r--third_party/libcxx/include/c++/v1/experimental/memory205
-rw-r--r--third_party/libcxx/include/c++/v1/experimental/propagate_const497
-rw-r--r--third_party/libcxx/include/c++/v1/experimental/simd96
-rw-r--r--third_party/libcxx/include/c++/v1/experimental/type_traits161
-rw-r--r--third_party/libcxx/include/c++/v1/experimental/utility54
15 files changed, 2170 insertions, 0 deletions
diff --git a/third_party/libcxx/include/c++/v1/experimental/__simd/aligned_tag.h b/third_party/libcxx/include/c++/v1/experimental/__simd/aligned_tag.h
new file mode 100644
index 0000000..d208bf5
--- /dev/null
+++ b/third_party/libcxx/include/c++/v1/experimental/__simd/aligned_tag.h
@@ -0,0 +1,75 @@
+// -*- C++ -*-
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef _LIBCPP_EXPERIMENTAL___SIMD_ALIGNED_TAG_H
+#define _LIBCPP_EXPERIMENTAL___SIMD_ALIGNED_TAG_H
+
+#include <__config>
+#include <__cstddef/size_t.h>
+#include <__memory/assume_aligned.h>
+#include <__type_traits/remove_const.h>
+#include <experimental/__simd/traits.h>
+
+#if _LIBCPP_STD_VER >= 17 && defined(_LIBCPP_ENABLE_EXPERIMENTAL)
+
+_LIBCPP_BEGIN_NAMESPACE_EXPERIMENTAL
+inline namespace parallelism_v2 {
+// memory alignment
+struct element_aligned_tag {
+ template <class _Tp, class _Up = typename _Tp::value_type>
+ static constexpr size_t __alignment = alignof(_Up);
+
+ template <class _Tp, class _Up>
+ static _LIBCPP_HIDE_FROM_ABI constexpr _Up* __apply(_Up* __ptr) {
+ return __ptr;
+ }
+};
+
+template <>
+inline constexpr bool is_simd_flag_type_v<element_aligned_tag> = true;
+
+struct vector_aligned_tag {
+ template <class _Tp, class _Up = typename _Tp::value_type>
+ static constexpr size_t __alignment = memory_alignment_v<_Tp, remove_const_t<_Up>>;
+
+ template <class _Tp, class _Up>
+ static _LIBCPP_HIDE_FROM_ABI constexpr _Up* __apply(_Up* __ptr) {
+ return std::__assume_aligned<__alignment<_Tp, _Up>, _Up>(__ptr);
+ }
+};
+
+template <>
+inline constexpr bool is_simd_flag_type_v<vector_aligned_tag> = true;
+
+template <size_t _Np>
+struct overaligned_tag {
+ template <class _Tp, class _Up = typename _Tp::value_type>
+ static constexpr size_t __alignment = _Np;
+
+ template <class _Tp, class _Up>
+ static _LIBCPP_HIDE_FROM_ABI constexpr _Up* __apply(_Up* __ptr) {
+ return std::__assume_aligned<__alignment<_Tp, _Up>, _Up>(__ptr);
+ }
+};
+
+template <size_t _Np>
+inline constexpr bool is_simd_flag_type_v<overaligned_tag<_Np>> = true;
+
+inline constexpr element_aligned_tag element_aligned{};
+
+inline constexpr vector_aligned_tag vector_aligned{};
+
+template <size_t _Np>
+inline constexpr overaligned_tag<_Np> overaligned{};
+
+} // namespace parallelism_v2
+_LIBCPP_END_NAMESPACE_EXPERIMENTAL
+
+#endif // _LIBCPP_STD_VER >= 17 && defined(_LIBCPP_ENABLE_EXPERIMENTAL)
+#endif // _LIBCPP_EXPERIMENTAL___SIMD_ALIGNED_TAG_H
diff --git a/third_party/libcxx/include/c++/v1/experimental/__simd/declaration.h b/third_party/libcxx/include/c++/v1/experimental/__simd/declaration.h
new file mode 100644
index 0000000..d9395ba
--- /dev/null
+++ b/third_party/libcxx/include/c++/v1/experimental/__simd/declaration.h
@@ -0,0 +1,88 @@
+// -*- C++ -*-
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef _LIBCPP_EXPERIMENTAL___SIMD_DECLARATION_H
+#define _LIBCPP_EXPERIMENTAL___SIMD_DECLARATION_H
+
+#include <__config>
+#include <__cstddef/size_t.h>
+
+#if _LIBCPP_STD_VER >= 17 && defined(_LIBCPP_ENABLE_EXPERIMENTAL)
+
+// TODO: support more targets
+# if defined(__AVX__)
+# define _LIBCPP_NATIVE_SIMD_WIDTH_IN_BYTES 32
+# else
+# define _LIBCPP_NATIVE_SIMD_WIDTH_IN_BYTES 16
+# endif
+
+_LIBCPP_BEGIN_NAMESPACE_EXPERIMENTAL
+inline namespace parallelism_v2 {
+namespace simd_abi {
+template <int>
+struct __vec_ext;
+struct __scalar;
+
+using scalar = __scalar;
+
+// TODO: make this platform dependent
+template <int _Np>
+using fixed_size = __vec_ext<_Np>;
+
+template <class _Tp>
+inline constexpr int max_fixed_size = 32;
+
+// TODO: make this platform dependent
+template <class _Tp>
+using compatible = __vec_ext<16 / sizeof(_Tp)>;
+
+// TODO: make this platform dependent
+template <class _Tp>
+using native = __vec_ext<_LIBCPP_NATIVE_SIMD_WIDTH_IN_BYTES / sizeof(_Tp)>;
+
+// TODO: make this platform dependent
+template <class _Tp, size_t _Np, class... _Abis>
+struct deduce {
+ using type _LIBCPP_NODEBUG = fixed_size<_Np>;
+};
+
+// TODO: make this platform dependent
+template <class _Tp, size_t _Np, class... _Abis>
+using deduce_t = typename deduce<_Tp, _Np, _Abis...>::type;
+
+} // namespace simd_abi
+
+template <class _Tp, class _Abi>
+struct __simd_storage;
+
+template <class _Tp, class _Abi>
+struct __mask_storage;
+
+template <class _Tp, class _Abi>
+struct __simd_operations;
+
+template <class _Tp, class _Abi>
+struct __mask_operations;
+
+struct element_aligned_tag;
+struct vector_aligned_tag;
+template <size_t>
+struct overaligned_tag;
+
+template <class _Tp, class _Abi = simd_abi::compatible<_Tp>>
+class simd;
+
+template <class _Tp, class _Abi = simd_abi::compatible<_Tp>>
+class simd_mask;
+
+} // namespace parallelism_v2
+_LIBCPP_END_NAMESPACE_EXPERIMENTAL
+
+#endif // _LIBCPP_STD_VER >= 17 && defined(_LIBCPP_ENABLE_EXPERIMENTAL)
+#endif // _LIBCPP_EXPERIMENTAL___SIMD_DECLARATION_H
diff --git a/third_party/libcxx/include/c++/v1/experimental/__simd/reference.h b/third_party/libcxx/include/c++/v1/experimental/__simd/reference.h
new file mode 100644
index 0000000..b9fe962
--- /dev/null
+++ b/third_party/libcxx/include/c++/v1/experimental/__simd/reference.h
@@ -0,0 +1,192 @@
+// -*- C++ -*-
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef _LIBCPP_EXPERIMENTAL___SIMD_REFERENCE_H
+#define _LIBCPP_EXPERIMENTAL___SIMD_REFERENCE_H
+
+#include <__config>
+#include <__cstddef/size_t.h>
+#include <__type_traits/enable_if.h>
+#include <__type_traits/is_assignable.h>
+#include <__type_traits/is_same.h>
+#include <__utility/declval.h>
+#include <__utility/forward.h>
+#include <__utility/move.h>
+#include <experimental/__simd/utility.h>
+
+_LIBCPP_PUSH_MACROS
+#include <__undef_macros>
+
+#if _LIBCPP_STD_VER >= 17 && defined(_LIBCPP_ENABLE_EXPERIMENTAL)
+
+_LIBCPP_BEGIN_NAMESPACE_EXPERIMENTAL
+inline namespace parallelism_v2 {
+template <class _Tp, class _Storage, class _Vp>
+class __simd_reference {
+ template <class, class>
+ friend class simd;
+ template <class, class>
+ friend class simd_mask;
+
+ _Storage& __s_;
+ size_t __idx_;
+
+ _LIBCPP_HIDE_FROM_ABI __simd_reference(_Storage& __s, size_t __idx) : __s_(__s), __idx_(__idx) {}
+
+ _LIBCPP_HIDE_FROM_ABI _Vp __get() const noexcept { return __s_.__get(__idx_); }
+
+ _LIBCPP_HIDE_FROM_ABI void __set(_Vp __v) {
+ if constexpr (is_same_v<_Vp, bool>)
+ __s_.__set(__idx_, experimental::__set_all_bits<_Tp>(__v));
+ else
+ __s_.__set(__idx_, __v);
+ }
+
+public:
+ using value_type = _Vp;
+
+ __simd_reference() = delete;
+ __simd_reference(const __simd_reference&) = delete;
+
+ _LIBCPP_HIDE_FROM_ABI operator value_type() const noexcept { return __get(); }
+
+ template <class _Up, enable_if_t<is_assignable_v<value_type&, _Up&&>, int> = 0>
+ _LIBCPP_HIDE_FROM_ABI __simd_reference operator=(_Up&& __v) && noexcept {
+ __set(static_cast<value_type>(std::forward<_Up>(__v)));
+ return {__s_, __idx_};
+ }
+
+ // Note: This approach might not fully align with the specification,
+ // which might be a wording defect. (https://wg21.link/N4808 section 9.6.3)
+ template <class _Tp1, class _Storage1, class _Vp1>
+ friend void
+ swap(__simd_reference<_Tp1, _Storage1, _Vp1>&& __a, __simd_reference<_Tp1, _Storage1, _Vp1>&& __b) noexcept;
+
+ template <class _Tp1, class _Storage1, class _Vp1>
+ friend void swap(_Vp1& __a, __simd_reference<_Tp1, _Storage1, _Vp1>&& __b) noexcept;
+
+ template <class _Tp1, class _Storage1, class _Vp1>
+ friend void swap(__simd_reference<_Tp1, _Storage1, _Vp1>&& __a, _Vp1& __b) noexcept;
+
+ template <class _Up, class = decltype(std::declval<value_type&>() += std::declval<_Up>())>
+ _LIBCPP_HIDE_FROM_ABI __simd_reference operator+=(_Up&& __v) && noexcept {
+ __set(__get() + static_cast<value_type>(std::forward<_Up>(__v)));
+ return {__s_, __idx_};
+ }
+
+ template <class _Up, class = decltype(std::declval<value_type&>() -= std::declval<_Up>())>
+ _LIBCPP_HIDE_FROM_ABI __simd_reference operator-=(_Up&& __v) && noexcept {
+ __set(__get() - static_cast<value_type>(std::forward<_Up>(__v)));
+ return {__s_, __idx_};
+ }
+
+ template <class _Up, class = decltype(std::declval<value_type&>() *= std::declval<_Up>())>
+ _LIBCPP_HIDE_FROM_ABI __simd_reference operator*=(_Up&& __v) && noexcept {
+ __set(__get() * static_cast<value_type>(std::forward<_Up>(__v)));
+ return {__s_, __idx_};
+ }
+
+ template <class _Up, class = decltype(std::declval<value_type&>() /= std::declval<_Up>())>
+ _LIBCPP_HIDE_FROM_ABI __simd_reference operator/=(_Up&& __v) && noexcept {
+ __set(__get() / static_cast<value_type>(std::forward<_Up>(__v)));
+ return {__s_, __idx_};
+ }
+
+ template <class _Up, class = decltype(std::declval<value_type&>() %= std::declval<_Up>())>
+ _LIBCPP_HIDE_FROM_ABI __simd_reference operator%=(_Up&& __v) && noexcept {
+ __set(__get() % static_cast<value_type>(std::forward<_Up>(__v)));
+ return {__s_, __idx_};
+ }
+
+ template <class _Up, class = decltype(std::declval<value_type&>() &= std::declval<_Up>())>
+ _LIBCPP_HIDE_FROM_ABI __simd_reference operator&=(_Up&& __v) && noexcept {
+ __set(__get() & static_cast<value_type>(std::forward<_Up>(__v)));
+ return {__s_, __idx_};
+ }
+
+ template <class _Up, class = decltype(std::declval<value_type&>() |= std::declval<_Up>())>
+ _LIBCPP_HIDE_FROM_ABI __simd_reference operator|=(_Up&& __v) && noexcept {
+ __set(__get() | static_cast<value_type>(std::forward<_Up>(__v)));
+ return {__s_, __idx_};
+ }
+
+ template <class _Up, class = decltype(std::declval<value_type&>() ^= std::declval<_Up>())>
+ _LIBCPP_HIDE_FROM_ABI __simd_reference operator^=(_Up&& __v) && noexcept {
+ __set(__get() ^ static_cast<value_type>(std::forward<_Up>(__v)));
+ return {__s_, __idx_};
+ }
+
+ template <class _Up, class = decltype(std::declval<value_type&>() <<= std::declval<_Up>())>
+ _LIBCPP_HIDE_FROM_ABI __simd_reference operator<<=(_Up&& __v) && noexcept {
+ __set(__get() << static_cast<value_type>(std::forward<_Up>(__v)));
+ return {__s_, __idx_};
+ }
+
+ template <class _Up, class = decltype(std::declval<value_type&>() >>= std::declval<_Up>())>
+ _LIBCPP_HIDE_FROM_ABI __simd_reference operator>>=(_Up&& __v) && noexcept {
+ __set(__get() >> static_cast<value_type>(std::forward<_Up>(__v)));
+ return {__s_, __idx_};
+ }
+
+ // Note: All legal vectorizable types support operator++/--.
+ // There doesn't seem to be a way to trigger the constraint.
+ // Therefore, no SFINAE check is added here.
+ __simd_reference _LIBCPP_HIDE_FROM_ABI operator++() && noexcept {
+ __set(__get() + 1);
+ return {__s_, __idx_};
+ }
+
+ value_type _LIBCPP_HIDE_FROM_ABI operator++(int) && noexcept {
+ auto __r = __get();
+ __set(__get() + 1);
+ return __r;
+ }
+
+ __simd_reference _LIBCPP_HIDE_FROM_ABI operator--() && noexcept {
+ __set(__get() - 1);
+ return {__s_, __idx_};
+ }
+
+ value_type _LIBCPP_HIDE_FROM_ABI operator--(int) && noexcept {
+ auto __r = __get();
+ __set(__get() - 1);
+ return __r;
+ }
+};
+
+template <class _Tp, class _Storage, class _Vp>
+_LIBCPP_HIDE_FROM_ABI void
+swap(__simd_reference<_Tp, _Storage, _Vp>&& __a, __simd_reference<_Tp, _Storage, _Vp>&& __b) noexcept {
+ _Vp __tmp(std::move(__a));
+ std::move(__a) = std::move(__b);
+ std::move(__b) = std::move(__tmp);
+}
+
+template <class _Tp, class _Storage, class _Vp>
+_LIBCPP_HIDE_FROM_ABI void swap(_Vp& __a, __simd_reference<_Tp, _Storage, _Vp>&& __b) noexcept {
+ _Vp __tmp(std::move(__a));
+ __a = std::move(__b);
+ std::move(__b) = std::move(__tmp);
+}
+
+template <class _Tp, class _Storage, class _Vp>
+_LIBCPP_HIDE_FROM_ABI void swap(__simd_reference<_Tp, _Storage, _Vp>&& __a, _Vp& __b) noexcept {
+ _Vp __tmp(std::move(__a));
+ std::move(__a) = std::move(__b);
+ __b = std::move(__tmp);
+}
+
+} // namespace parallelism_v2
+_LIBCPP_END_NAMESPACE_EXPERIMENTAL
+
+#endif // _LIBCPP_STD_VER >= 17 && defined(_LIBCPP_ENABLE_EXPERIMENTAL)
+
+_LIBCPP_POP_MACROS
+
+#endif // _LIBCPP_EXPERIMENTAL___SIMD_REFERENCE_H
diff --git a/third_party/libcxx/include/c++/v1/experimental/__simd/scalar.h b/third_party/libcxx/include/c++/v1/experimental/__simd/scalar.h
new file mode 100644
index 0000000..20c8b02
--- /dev/null
+++ b/third_party/libcxx/include/c++/v1/experimental/__simd/scalar.h
@@ -0,0 +1,102 @@
+// -*- C++ -*-
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef _LIBCPP_EXPERIMENTAL___SIMD_SCALAR_H
+#define _LIBCPP_EXPERIMENTAL___SIMD_SCALAR_H
+
+#include <__assert>
+#include <__config>
+#include <__cstddef/size_t.h>
+#include <__type_traits/integral_constant.h>
+#include <experimental/__simd/declaration.h>
+#include <experimental/__simd/traits.h>
+
+#if _LIBCPP_STD_VER >= 17 && defined(_LIBCPP_ENABLE_EXPERIMENTAL)
+
+_LIBCPP_BEGIN_NAMESPACE_EXPERIMENTAL
+inline namespace parallelism_v2 {
+namespace simd_abi {
+struct __scalar {
+ static constexpr size_t __simd_size = 1;
+};
+} // namespace simd_abi
+
+template <>
+inline constexpr bool is_abi_tag_v<simd_abi::__scalar> = true;
+
+template <class _Tp>
+struct __simd_storage<_Tp, simd_abi::__scalar> {
+ _Tp __data;
+
+ _LIBCPP_HIDE_FROM_ABI _Tp __get([[maybe_unused]] size_t __idx) const noexcept {
+ _LIBCPP_ASSERT_UNCATEGORIZED(__idx == 0, "Index is out of bounds");
+ return __data;
+ }
+ _LIBCPP_HIDE_FROM_ABI void __set([[maybe_unused]] size_t __idx, _Tp __v) noexcept {
+ _LIBCPP_ASSERT_UNCATEGORIZED(__idx == 0, "Index is out of bounds");
+ __data = __v;
+ }
+};
+
+template <class _Tp>
+struct __mask_storage<_Tp, simd_abi::__scalar> : __simd_storage<bool, simd_abi::__scalar> {};
+
+template <class _Tp>
+struct __simd_operations<_Tp, simd_abi::__scalar> {
+ using _SimdStorage _LIBCPP_NODEBUG = __simd_storage<_Tp, simd_abi::__scalar>;
+ using _MaskStorage _LIBCPP_NODEBUG = __mask_storage<_Tp, simd_abi::__scalar>;
+
+ static _LIBCPP_HIDE_FROM_ABI _SimdStorage __broadcast(_Tp __v) noexcept { return {__v}; }
+
+ template <class _Generator>
+ static _LIBCPP_HIDE_FROM_ABI _SimdStorage __generate(_Generator&& __g) noexcept {
+ return {__g(std::integral_constant<size_t, 0>())};
+ }
+
+ template <class _Up>
+ static _LIBCPP_HIDE_FROM_ABI void __load(_SimdStorage& __s, const _Up* __mem) noexcept {
+ __s.__data = static_cast<_Tp>(__mem[0]);
+ }
+
+ template <class _Up>
+ static _LIBCPP_HIDE_FROM_ABI void __store(_SimdStorage __s, _Up* __mem) noexcept {
+ *__mem = static_cast<_Up>(__s.__data);
+ }
+
+ static _LIBCPP_HIDE_FROM_ABI void __increment(_SimdStorage& __s) noexcept { ++__s.__data; }
+
+ static _LIBCPP_HIDE_FROM_ABI void __decrement(_SimdStorage& __s) noexcept { --__s.__data; }
+
+ static _LIBCPP_HIDE_FROM_ABI _MaskStorage __negate(_SimdStorage __s) noexcept { return {!__s.__data}; }
+
+ static _LIBCPP_HIDE_FROM_ABI _SimdStorage __bitwise_not(_SimdStorage __s) noexcept {
+ return {static_cast<_Tp>(~__s.__data)};
+ }
+
+ static _LIBCPP_HIDE_FROM_ABI _SimdStorage __unary_minus(_SimdStorage __s) noexcept {
+ return {static_cast<_Tp>(-__s.__data)};
+ }
+};
+
+template <class _Tp>
+struct __mask_operations<_Tp, simd_abi::__scalar> {
+ using _MaskStorage _LIBCPP_NODEBUG = __mask_storage<_Tp, simd_abi::__scalar>;
+
+ static _LIBCPP_HIDE_FROM_ABI _MaskStorage __broadcast(bool __v) noexcept { return {__v}; }
+
+ static _LIBCPP_HIDE_FROM_ABI void __load(_MaskStorage& __s, const bool* __mem) noexcept { __s.__data = __mem[0]; }
+
+ static _LIBCPP_HIDE_FROM_ABI void __store(_MaskStorage __s, bool* __mem) noexcept { __mem[0] = __s.__data; }
+};
+
+} // namespace parallelism_v2
+_LIBCPP_END_NAMESPACE_EXPERIMENTAL
+
+#endif // _LIBCPP_STD_VER >= 17 && defined(_LIBCPP_ENABLE_EXPERIMENTAL)
+#endif // _LIBCPP_EXPERIMENTAL___SIMD_SCALAR_H
diff --git a/third_party/libcxx/include/c++/v1/experimental/__simd/simd.h b/third_party/libcxx/include/c++/v1/experimental/__simd/simd.h
new file mode 100644
index 0000000..2fd2b26
--- /dev/null
+++ b/third_party/libcxx/include/c++/v1/experimental/__simd/simd.h
@@ -0,0 +1,155 @@
+// -*- C++ -*-
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef _LIBCPP_EXPERIMENTAL___SIMD_SIMD_H
+#define _LIBCPP_EXPERIMENTAL___SIMD_SIMD_H
+
+#include <__config>
+#include <__cstddef/size_t.h>
+#include <__type_traits/enable_if.h>
+#include <__type_traits/is_integral.h>
+#include <__type_traits/is_same.h>
+#include <__type_traits/remove_cvref.h>
+#include <__utility/forward.h>
+#include <experimental/__simd/declaration.h>
+#include <experimental/__simd/reference.h>
+#include <experimental/__simd/traits.h>
+#include <experimental/__simd/utility.h>
+
+#if _LIBCPP_STD_VER >= 17 && defined(_LIBCPP_ENABLE_EXPERIMENTAL)
+
+_LIBCPP_BEGIN_NAMESPACE_EXPERIMENTAL
+inline namespace parallelism_v2 {
+
+template <class _Simd, class _Impl, bool>
+class __simd_int_operators {};
+
+template <class _Simd, class _Impl>
+class __simd_int_operators<_Simd, _Impl, true> {
+public:
+ // unary operators for integral _Tp
+ _LIBCPP_HIDE_FROM_ABI _Simd operator~() const noexcept {
+ return _Simd(_Impl::__bitwise_not((*static_cast<const _Simd*>(this)).__s_), _Simd::__storage_tag);
+ }
+};
+
+// class template simd [simd.class]
+// TODO: implement simd class
+template <class _Tp, class _Abi>
+class simd : public __simd_int_operators<simd<_Tp, _Abi>, __simd_operations<_Tp, _Abi>, is_integral_v<_Tp>> {
+ using _Impl _LIBCPP_NODEBUG = __simd_operations<_Tp, _Abi>;
+ using _Storage _LIBCPP_NODEBUG = typename _Impl::_SimdStorage;
+
+ _Storage __s_;
+
+ friend class __simd_int_operators<simd, _Impl, true>;
+
+public:
+ using value_type = _Tp;
+ using reference = __simd_reference<_Tp, _Storage, value_type>;
+ using mask_type = simd_mask<_Tp, _Abi>;
+ using abi_type = _Abi;
+
+ static _LIBCPP_HIDE_FROM_ABI constexpr size_t size() noexcept { return simd_size_v<value_type, abi_type>; }
+
+ _LIBCPP_HIDE_FROM_ABI simd() noexcept = default;
+
+ // explicit conversion from and to implementation-defined types
+ struct __storage_tag_t {};
+ static constexpr __storage_tag_t __storage_tag{};
+ explicit _LIBCPP_HIDE_FROM_ABI operator _Storage() const { return __s_; }
+ explicit _LIBCPP_HIDE_FROM_ABI simd(const _Storage& __s, __storage_tag_t) : __s_(__s) {}
+
+ // broadcast constructor
+ template <class _Up, enable_if_t<__can_broadcast_v<value_type, __remove_cvref_t<_Up>>, int> = 0>
+ _LIBCPP_HIDE_FROM_ABI simd(_Up&& __v) noexcept : __s_(_Impl::__broadcast(static_cast<value_type>(__v))) {}
+
+ // implicit type conversion constructor
+ template <class _Up,
+ enable_if_t<!is_same_v<_Up, _Tp> && is_same_v<abi_type, simd_abi::fixed_size<size()>> &&
+ __is_non_narrowing_convertible_v<_Up, value_type>,
+ int> = 0>
+ _LIBCPP_HIDE_FROM_ABI simd(const simd<_Up, simd_abi::fixed_size<size()>>& __v) noexcept {
+ for (size_t __i = 0; __i < size(); __i++) {
+ (*this)[__i] = static_cast<value_type>(__v[__i]);
+ }
+ }
+
+ // generator constructor
+ template <class _Generator, enable_if_t<__can_generate_v<value_type, _Generator, size()>, int> = 0>
+ explicit _LIBCPP_HIDE_FROM_ABI simd(_Generator&& __g) noexcept
+ : __s_(_Impl::__generate(std::forward<_Generator>(__g))) {}
+
+ // load constructor
+ template <class _Up, class _Flags, enable_if_t<__is_vectorizable_v<_Up> && is_simd_flag_type_v<_Flags>, int> = 0>
+ _LIBCPP_HIDE_FROM_ABI simd(const _Up* __mem, _Flags) {
+ _Impl::__load(__s_, _Flags::template __apply<simd>(__mem));
+ }
+
+ // copy functions
+ template <class _Up, class _Flags, enable_if_t<__is_vectorizable_v<_Up> && is_simd_flag_type_v<_Flags>, int> = 0>
+ _LIBCPP_HIDE_FROM_ABI void copy_from(const _Up* __mem, _Flags) {
+ _Impl::__load(__s_, _Flags::template __apply<simd>(__mem));
+ }
+
+ template <class _Up, class _Flags, enable_if_t<__is_vectorizable_v<_Up> && is_simd_flag_type_v<_Flags>, int> = 0>
+ _LIBCPP_HIDE_FROM_ABI void copy_to(_Up* __mem, _Flags) const {
+ _Impl::__store(__s_, _Flags::template __apply<simd>(__mem));
+ }
+
+ // scalar access [simd.subscr]
+ _LIBCPP_HIDE_FROM_ABI reference operator[](size_t __i) noexcept { return reference(__s_, __i); }
+ _LIBCPP_HIDE_FROM_ABI value_type operator[](size_t __i) const noexcept { return __s_.__get(__i); }
+
+ // simd unary operators
+ _LIBCPP_HIDE_FROM_ABI simd& operator++() noexcept {
+ _Impl::__increment(__s_);
+ return *this;
+ }
+
+ _LIBCPP_HIDE_FROM_ABI simd operator++(int) noexcept {
+ simd __r = *this;
+ _Impl::__increment(__s_);
+ return __r;
+ }
+
+ _LIBCPP_HIDE_FROM_ABI simd& operator--() noexcept {
+ _Impl::__decrement(__s_);
+ return *this;
+ }
+
+ _LIBCPP_HIDE_FROM_ABI simd operator--(int) noexcept {
+ simd __r = *this;
+ _Impl::__decrement(__s_);
+ return __r;
+ }
+
+ _LIBCPP_HIDE_FROM_ABI mask_type operator!() const noexcept {
+ return mask_type(_Impl::__negate(__s_), mask_type::__storage_tag);
+ }
+
+ _LIBCPP_HIDE_FROM_ABI simd operator+() const noexcept { return *this; }
+
+ _LIBCPP_HIDE_FROM_ABI simd operator-() const noexcept { return simd(_Impl::__unary_minus(__s_), __storage_tag); }
+};
+
+template <class _Tp, class _Abi>
+inline constexpr bool is_simd_v<simd<_Tp, _Abi>> = true;
+
+template <class _Tp>
+using native_simd = simd<_Tp, simd_abi::native<_Tp>>;
+
+template <class _Tp, int _Np>
+using fixed_size_simd = simd<_Tp, simd_abi::fixed_size<_Np>>;
+
+} // namespace parallelism_v2
+_LIBCPP_END_NAMESPACE_EXPERIMENTAL
+
+#endif // _LIBCPP_STD_VER >= 17 && defined(_LIBCPP_ENABLE_EXPERIMENTAL)
+#endif // _LIBCPP_EXPERIMENTAL___SIMD_SIMD_H
diff --git a/third_party/libcxx/include/c++/v1/experimental/__simd/simd_mask.h b/third_party/libcxx/include/c++/v1/experimental/__simd/simd_mask.h
new file mode 100644
index 0000000..a117665
--- /dev/null
+++ b/third_party/libcxx/include/c++/v1/experimental/__simd/simd_mask.h
@@ -0,0 +1,97 @@
+// -*- C++ -*-
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef _LIBCPP_EXPERIMENTAL___SIMD_SIMD_MASK_H
+#define _LIBCPP_EXPERIMENTAL___SIMD_SIMD_MASK_H
+
+#include <__config>
+#include <__cstddef/size_t.h>
+#include <__type_traits/enable_if.h>
+#include <__type_traits/is_same.h>
+#include <experimental/__simd/declaration.h>
+#include <experimental/__simd/reference.h>
+#include <experimental/__simd/traits.h>
+
+#if _LIBCPP_STD_VER >= 17 && defined(_LIBCPP_ENABLE_EXPERIMENTAL)
+
+_LIBCPP_BEGIN_NAMESPACE_EXPERIMENTAL
+inline namespace parallelism_v2 {
+
+// class template simd_mask [simd.mask.class]
+// TODO: implement simd_mask class
+template <class _Tp, class _Abi>
+class simd_mask {
+ using _Impl _LIBCPP_NODEBUG = __mask_operations<_Tp, _Abi>;
+ using _Storage _LIBCPP_NODEBUG = typename _Impl::_MaskStorage;
+
+ _Storage __s_;
+
+public:
+ using value_type = bool;
+ using reference = __simd_reference<_Tp, _Storage, value_type>;
+ using simd_type = simd<_Tp, _Abi>;
+ using abi_type = _Abi;
+
+ static _LIBCPP_HIDE_FROM_ABI constexpr size_t size() noexcept { return simd_type::size(); }
+
+ _LIBCPP_HIDE_FROM_ABI simd_mask() noexcept = default;
+
+ // explicit conversion from and to implementation-defined types
+ struct __storage_tag_t {};
+ static constexpr __storage_tag_t __storage_tag{};
+ explicit _LIBCPP_HIDE_FROM_ABI operator _Storage() const { return __s_; }
+ explicit _LIBCPP_HIDE_FROM_ABI simd_mask(const _Storage& __s, __storage_tag_t) : __s_(__s) {}
+
+ // broadcast constructor
+ _LIBCPP_HIDE_FROM_ABI explicit simd_mask(value_type __v) noexcept : __s_(_Impl::__broadcast(__v)) {}
+
+ // implicit type conversion constructor
+ template <class _Up, enable_if_t<!is_same_v<_Up, _Tp> && is_same_v<abi_type, simd_abi::fixed_size<size()>>, int> = 0>
+ _LIBCPP_HIDE_FROM_ABI simd_mask(const simd_mask<_Up, simd_abi::fixed_size<size()>>& __v) noexcept {
+ for (size_t __i = 0; __i < size(); __i++) {
+ (*this)[__i] = __v[__i];
+ }
+ }
+
+ // load constructor
+ template <class _Flags, enable_if_t<is_simd_flag_type_v<_Flags>, int> = 0>
+ _LIBCPP_HIDE_FROM_ABI simd_mask(const value_type* __mem, _Flags) {
+ _Impl::__load(__s_, _Flags::template __apply<simd_mask>(__mem));
+ }
+
+ // copy functions
+ template <class _Flags, enable_if_t<is_simd_flag_type_v<_Flags>, int> = 0>
+ _LIBCPP_HIDE_FROM_ABI void copy_from(const value_type* __mem, _Flags) {
+ _Impl::__load(__s_, _Flags::template __apply<simd_mask>(__mem));
+ }
+
+ template <class _Flags, enable_if_t<is_simd_flag_type_v<_Flags>, int> = 0>
+ _LIBCPP_HIDE_FROM_ABI void copy_to(value_type* __mem, _Flags) const {
+ _Impl::__store(__s_, _Flags::template __apply<simd_mask>(__mem));
+ }
+
+ // scalar access [simd.mask.subscr]
+ _LIBCPP_HIDE_FROM_ABI reference operator[](size_t __i) noexcept { return reference(__s_, __i); }
+ _LIBCPP_HIDE_FROM_ABI value_type operator[](size_t __i) const noexcept { return __s_.__get(__i); }
+};
+
+template <class _Tp, class _Abi>
+inline constexpr bool is_simd_mask_v<simd_mask<_Tp, _Abi>> = true;
+
+template <class _Tp>
+using native_simd_mask = simd_mask<_Tp, simd_abi::native<_Tp>>;
+
+template <class _Tp, int _Np>
+using fixed_size_simd_mask = simd_mask<_Tp, simd_abi::fixed_size<_Np>>;
+
+} // namespace parallelism_v2
+_LIBCPP_END_NAMESPACE_EXPERIMENTAL
+
+#endif // _LIBCPP_STD_VER >= 17 && defined(_LIBCPP_ENABLE_EXPERIMENTAL)
+#endif // _LIBCPP_EXPERIMENTAL___SIMD_SIMD_MASK_H
diff --git a/third_party/libcxx/include/c++/v1/experimental/__simd/traits.h b/third_party/libcxx/include/c++/v1/experimental/__simd/traits.h
new file mode 100644
index 0000000..0bcc2ee
--- /dev/null
+++ b/third_party/libcxx/include/c++/v1/experimental/__simd/traits.h
@@ -0,0 +1,75 @@
+// -*- C++ -*-
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef _LIBCPP_EXPERIMENTAL___SIMD_TRAITS_H
+#define _LIBCPP_EXPERIMENTAL___SIMD_TRAITS_H
+
+#include <__bit/bit_ceil.h>
+#include <__config>
+#include <__cstddef/size_t.h>
+#include <__type_traits/integral_constant.h>
+#include <__type_traits/is_same.h>
+#include <experimental/__simd/declaration.h>
+#include <experimental/__simd/utility.h>
+
+#if _LIBCPP_STD_VER >= 17 && defined(_LIBCPP_ENABLE_EXPERIMENTAL)
+
+_LIBCPP_BEGIN_NAMESPACE_EXPERIMENTAL
+inline namespace parallelism_v2 {
+
+// traits [simd.traits]
+template <class _Tp>
+inline constexpr bool is_abi_tag_v = false;
+
+template <class _Tp>
+struct is_abi_tag : bool_constant<is_abi_tag_v<_Tp>> {};
+
+template <class _Tp>
+inline constexpr bool is_simd_v = false;
+
+template <class _Tp>
+struct is_simd : bool_constant<is_simd_v<_Tp>> {};
+
+template <class _Tp>
+inline constexpr bool is_simd_mask_v = false;
+
+template <class _Tp>
+struct is_simd_mask : bool_constant<is_simd_mask_v<_Tp>> {};
+
+template <class _Tp>
+inline constexpr bool is_simd_flag_type_v = false;
+
+template <class _Tp>
+struct is_simd_flag_type : bool_constant<is_simd_flag_type_v<_Tp>> {};
+
+template <class _Tp, class _Abi = simd_abi::compatible<_Tp>, bool = (__is_vectorizable_v<_Tp> && is_abi_tag_v<_Abi>)>
+struct simd_size : integral_constant<size_t, _Abi::__simd_size> {};
+
+template <class _Tp, class _Abi>
+struct simd_size<_Tp, _Abi, false> {};
+
+template <class _Tp, class _Abi = simd_abi::compatible<_Tp>>
+inline constexpr size_t simd_size_v = simd_size<_Tp, _Abi>::value;
+
+template <class _Tp,
+ class _Up = typename _Tp::value_type,
+ bool = (is_simd_v<_Tp> && __is_vectorizable_v<_Up>) || (is_simd_mask_v<_Tp> && is_same_v<_Up, bool>)>
+struct memory_alignment : integral_constant<size_t, std::__bit_ceil(sizeof(_Up) * _Tp::size())> {};
+
+template <class _Tp, class _Up>
+struct memory_alignment<_Tp, _Up, false> {};
+
+template <class _Tp, class _Up = typename _Tp::value_type>
+inline constexpr size_t memory_alignment_v = memory_alignment<_Tp, _Up>::value;
+
+} // namespace parallelism_v2
+_LIBCPP_END_NAMESPACE_EXPERIMENTAL
+
+#endif // _LIBCPP_STD_VER >= 17 && defined(_LIBCPP_ENABLE_EXPERIMENTAL)
+#endif // _LIBCPP_EXPERIMENTAL___SIMD_TRAITS_H
diff --git a/third_party/libcxx/include/c++/v1/experimental/__simd/utility.h b/third_party/libcxx/include/c++/v1/experimental/__simd/utility.h
new file mode 100644
index 0000000..2af61e3
--- /dev/null
+++ b/third_party/libcxx/include/c++/v1/experimental/__simd/utility.h
@@ -0,0 +1,103 @@
+// -*- C++ -*-
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef _LIBCPP_EXPERIMENTAL___SIMD_UTILITY_H
+#define _LIBCPP_EXPERIMENTAL___SIMD_UTILITY_H
+
+#include <__config>
+#include <__cstddef/size_t.h>
+#include <__type_traits/is_arithmetic.h>
+#include <__type_traits/is_const.h>
+#include <__type_traits/is_constant_evaluated.h>
+#include <__type_traits/is_convertible.h>
+#include <__type_traits/is_same.h>
+#include <__type_traits/is_unsigned.h>
+#include <__type_traits/is_volatile.h>
+#include <__type_traits/void_t.h>
+#include <__utility/declval.h>
+#include <__utility/integer_sequence.h>
+#include <cstdint>
+#include <limits>
+
+_LIBCPP_PUSH_MACROS
+#include <__undef_macros>
+
+#if _LIBCPP_STD_VER >= 17 && defined(_LIBCPP_ENABLE_EXPERIMENTAL)
+
+_LIBCPP_BEGIN_NAMESPACE_EXPERIMENTAL
+inline namespace parallelism_v2 {
+template <class _Tp>
+inline constexpr bool __is_vectorizable_v =
+ is_arithmetic_v<_Tp> && !is_const_v<_Tp> && !is_volatile_v<_Tp> && !is_same_v<_Tp, bool>;
+
+template <class _Tp>
+_LIBCPP_HIDE_FROM_ABI auto __choose_mask_type() {
+ if constexpr (sizeof(_Tp) == 1) {
+ return uint8_t{};
+ } else if constexpr (sizeof(_Tp) == 2) {
+ return uint16_t{};
+ } else if constexpr (sizeof(_Tp) == 4) {
+ return uint32_t{};
+ } else if constexpr (sizeof(_Tp) == 8) {
+ return uint64_t{};
+ }
+# if _LIBCPP_HAS_INT128
+ else if constexpr (sizeof(_Tp) == 16) {
+ return __uint128_t{};
+ }
+# endif
+ else
+ static_assert(sizeof(_Tp) == 0, "Unexpected size");
+}
+
+template <class _Tp>
+_LIBCPP_HIDE_FROM_ABI auto constexpr __set_all_bits(bool __v) {
+ return __v ? (numeric_limits<decltype(experimental::__choose_mask_type<_Tp>())>::max()) : 0;
+}
+
+template <class _From, class _To, class = void>
+inline constexpr bool __is_non_narrowing_convertible_v = false;
+
+template <class _From, class _To>
+inline constexpr bool __is_non_narrowing_convertible_v<_From, _To, std::void_t<decltype(_To{std::declval<_From>()})>> =
+ true;
+
+template <class _Tp, class _Up>
+inline constexpr bool __can_broadcast_v =
+ (__is_vectorizable_v<_Up> && __is_non_narrowing_convertible_v<_Up, _Tp>) ||
+ (!__is_vectorizable_v<_Up> && is_convertible_v<_Up, _Tp>) || is_same_v<_Up, int> ||
+ (is_same_v<_Up, unsigned int> && is_unsigned_v<_Tp>);
+
+template <class _Tp, class _Generator, std::size_t _Idx, class = void>
+inline constexpr bool __is_well_formed = false;
+
+template <class _Tp, class _Generator, std::size_t _Idx>
+inline constexpr bool
+ __is_well_formed<_Tp,
+ _Generator,
+ _Idx,
+ std::void_t<decltype(std::declval<_Generator>()(integral_constant<size_t, _Idx>()))>> =
+ __can_broadcast_v<_Tp, decltype(std::declval<_Generator>()(integral_constant<size_t, _Idx>()))>;
+
+template <class _Tp, class _Generator, std::size_t... _Idxes>
+_LIBCPP_HIDE_FROM_ABI constexpr bool __can_generate(index_sequence<_Idxes...>) {
+ return (true && ... && __is_well_formed<_Tp, _Generator, _Idxes>);
+}
+
+template <class _Tp, class _Generator, std::size_t _Size>
+inline constexpr bool __can_generate_v = experimental::__can_generate<_Tp, _Generator>(make_index_sequence<_Size>());
+
+} // namespace parallelism_v2
+_LIBCPP_END_NAMESPACE_EXPERIMENTAL
+
+#endif // _LIBCPP_STD_VER >= 17 && defined(_LIBCPP_ENABLE_EXPERIMENTAL)
+
+_LIBCPP_POP_MACROS
+
+#endif // _LIBCPP_EXPERIMENTAL___SIMD_UTILITY_H
diff --git a/third_party/libcxx/include/c++/v1/experimental/__simd/vec_ext.h b/third_party/libcxx/include/c++/v1/experimental/__simd/vec_ext.h
new file mode 100644
index 0000000..2a4b8c7
--- /dev/null
+++ b/third_party/libcxx/include/c++/v1/experimental/__simd/vec_ext.h
@@ -0,0 +1,130 @@
+// -*- C++ -*-
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef _LIBCPP_EXPERIMENTAL___SIMD_VEC_EXT_H
+#define _LIBCPP_EXPERIMENTAL___SIMD_VEC_EXT_H
+
+#include <__assert>
+#include <__bit/bit_ceil.h>
+#include <__config>
+#include <__cstddef/size_t.h>
+#include <__type_traits/integral_constant.h>
+#include <__utility/forward.h>
+#include <__utility/integer_sequence.h>
+#include <experimental/__simd/declaration.h>
+#include <experimental/__simd/traits.h>
+#include <experimental/__simd/utility.h>
+
+#if _LIBCPP_STD_VER >= 17 && defined(_LIBCPP_ENABLE_EXPERIMENTAL)
+
+_LIBCPP_BEGIN_NAMESPACE_EXPERIMENTAL
+inline namespace parallelism_v2 {
+namespace simd_abi {
+template <int _Np>
+struct __vec_ext {
+ static constexpr size_t __simd_size = _Np;
+};
+} // namespace simd_abi
+
+template <int _Np>
+inline constexpr bool is_abi_tag_v<simd_abi::__vec_ext<_Np>> = _Np > 0 && _Np <= 32;
+
+template <class _Tp, int _Np>
+struct __simd_storage<_Tp, simd_abi::__vec_ext<_Np>> {
+ _Tp __data __attribute__((__vector_size__(std::__bit_ceil((sizeof(_Tp) * _Np)))));
+
+ _LIBCPP_HIDE_FROM_ABI _Tp __get(size_t __idx) const noexcept {
+ _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(__idx < _Np, "Index is out of bounds");
+ return __data[__idx];
+ }
+ _LIBCPP_HIDE_FROM_ABI void __set(size_t __idx, _Tp __v) noexcept {
+ _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(__idx < _Np, "Index is out of bounds");
+ __data[__idx] = __v;
+ }
+};
+
+template <class _Tp, int _Np>
+struct __mask_storage<_Tp, simd_abi::__vec_ext<_Np>>
+ : __simd_storage<decltype(experimental::__choose_mask_type<_Tp>()), simd_abi::__vec_ext<_Np>> {};
+
+template <class _Tp, int _Np>
+struct __simd_operations<_Tp, simd_abi::__vec_ext<_Np>> {
+ using _SimdStorage _LIBCPP_NODEBUG = __simd_storage<_Tp, simd_abi::__vec_ext<_Np>>;
+ using _MaskStorage _LIBCPP_NODEBUG = __mask_storage<_Tp, simd_abi::__vec_ext<_Np>>;
+
+ static _LIBCPP_HIDE_FROM_ABI _SimdStorage __broadcast(_Tp __v) noexcept {
+ _SimdStorage __result;
+ for (int __i = 0; __i < _Np; ++__i) {
+ __result.__set(__i, __v);
+ }
+ return __result;
+ }
+
+ template <class _Generator, size_t... _Is>
+ static _LIBCPP_HIDE_FROM_ABI _SimdStorage __generate_init(_Generator&& __g, std::index_sequence<_Is...>) {
+ return _SimdStorage{{__g(std::integral_constant<size_t, _Is>())...}};
+ }
+
+ template <class _Generator>
+ static _LIBCPP_HIDE_FROM_ABI _SimdStorage __generate(_Generator&& __g) noexcept {
+ return __generate_init(std::forward<_Generator>(__g), std::make_index_sequence<_Np>());
+ }
+
+ template <class _Up>
+ static _LIBCPP_HIDE_FROM_ABI void __load(_SimdStorage& __s, const _Up* __mem) noexcept {
+ for (size_t __i = 0; __i < _Np; __i++)
+ __s.__data[__i] = static_cast<_Tp>(__mem[__i]);
+ }
+
+ template <class _Up>
+ static _LIBCPP_HIDE_FROM_ABI void __store(_SimdStorage __s, _Up* __mem) noexcept {
+ for (size_t __i = 0; __i < _Np; __i++)
+ __mem[__i] = static_cast<_Up>(__s.__data[__i]);
+ }
+
+ static _LIBCPP_HIDE_FROM_ABI void __increment(_SimdStorage& __s) noexcept { __s.__data = __s.__data + 1; }
+
+ static _LIBCPP_HIDE_FROM_ABI void __decrement(_SimdStorage& __s) noexcept { __s.__data = __s.__data - 1; }
+
+ static _LIBCPP_HIDE_FROM_ABI _MaskStorage __negate(_SimdStorage __s) noexcept { return {!__s.__data}; }
+
+ static _LIBCPP_HIDE_FROM_ABI _SimdStorage __bitwise_not(_SimdStorage __s) noexcept { return {~__s.__data}; }
+
+ static _LIBCPP_HIDE_FROM_ABI _SimdStorage __unary_minus(_SimdStorage __s) noexcept { return {-__s.__data}; }
+};
+
+template <class _Tp, int _Np>
+struct __mask_operations<_Tp, simd_abi::__vec_ext<_Np>> {
+ using _MaskStorage _LIBCPP_NODEBUG = __mask_storage<_Tp, simd_abi::__vec_ext<_Np>>;
+
+ static _LIBCPP_HIDE_FROM_ABI _MaskStorage __broadcast(bool __v) noexcept {
+ _MaskStorage __result;
+ auto __all_bits_v = experimental::__set_all_bits<_Tp>(__v);
+ for (int __i = 0; __i < _Np; ++__i) {
+ __result.__set(__i, __all_bits_v);
+ }
+ return __result;
+ }
+
+ static _LIBCPP_HIDE_FROM_ABI void __load(_MaskStorage& __s, const bool* __mem) noexcept {
+ for (size_t __i = 0; __i < _Np; __i++)
+ __s.__data[__i] = experimental::__set_all_bits<_Tp>(__mem[__i]);
+ }
+
+ static _LIBCPP_HIDE_FROM_ABI void __store(_MaskStorage __s, bool* __mem) noexcept {
+ for (size_t __i = 0; __i < _Np; __i++)
+ __mem[__i] = static_cast<bool>(__s.__data[__i]);
+ }
+};
+
+} // namespace parallelism_v2
+_LIBCPP_END_NAMESPACE_EXPERIMENTAL
+
+#endif // _LIBCPP_STD_VER >= 17 && defined(_LIBCPP_ENABLE_EXPERIMENTAL)
+#endif // _LIBCPP_EXPERIMENTAL___SIMD_VEC_EXT_H
diff --git a/third_party/libcxx/include/c++/v1/experimental/iterator b/third_party/libcxx/include/c++/v1/experimental/iterator
new file mode 100644
index 0000000..0ed9518
--- /dev/null
+++ b/third_party/libcxx/include/c++/v1/experimental/iterator
@@ -0,0 +1,140 @@
+// -*- C++ -*-
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef _LIBCPP_EXPERIMENTAL_ITERATOR
+#define _LIBCPP_EXPERIMENTAL_ITERATOR
+
+/*
+namespace std {
+ namespace experimental {
+ inline namespace fundamentals_v2 {
+
+ template <class DelimT, class charT = char, class traits = char_traits<charT>>
+ class ostream_joiner {
+ public:
+ typedef charT char_type;
+ typedef traits traits_type;
+ typedef basic_ostream<charT, traits> ostream_type;
+ typedef output_iterator_tag iterator_category;
+ typedef void value_type;
+ typedef void difference_type;
+ typedef void pointer;
+ typedef void reference;
+
+ ostream_joiner(ostream_type& s, const DelimT& delimiter);
+ ostream_joiner(ostream_type& s, DelimT&& delimiter);
+
+ template<typename T>
+ ostream_joiner& operator=(const T& value);
+
+ ostream_joiner& operator*() noexcept;
+ ostream_joiner& operator++() noexcept;
+ ostream_joiner& operator++(int) noexcept;
+ private:
+ ostream_type* out_stream; // exposition only
+ DelimT delim; // exposition only
+ bool first_element; // exposition only
+ };
+
+ template <class charT, class traits, class DelimT>
+ ostream_joiner<decay_t<DelimT>, charT, traits>
+ make_ostream_joiner(basic_ostream<charT, traits>& os, DelimT&& delimiter);
+
+ } // inline namespace fundamentals_v2
+ } // namespace experimental
+} // namespace std
+
+*/
+
+#if __cplusplus < 201103L && defined(_LIBCPP_USE_FROZEN_CXX03_HEADERS)
+# include <__cxx03/__config>
+#else
+# include <__config>
+# include <__memory/addressof.h>
+# include <__ostream/basic_ostream.h>
+# include <__string/char_traits.h>
+# include <__type_traits/decay.h>
+# include <__utility/forward.h>
+# include <__utility/move.h>
+# include <iterator>
+
+# if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
+# pragma GCC system_header
+# endif
+
+_LIBCPP_PUSH_MACROS
+# include <__undef_macros>
+
+# if _LIBCPP_STD_VER >= 14
+
+_LIBCPP_BEGIN_NAMESPACE_LFTS
+
+template <class _Delim, class _CharT = char, class _Traits = char_traits<_CharT>>
+class ostream_joiner {
+public:
+ typedef _CharT char_type;
+ typedef _Traits traits_type;
+ typedef basic_ostream<char_type, traits_type> ostream_type;
+ typedef output_iterator_tag iterator_category;
+ typedef void value_type;
+ typedef void difference_type;
+ typedef void pointer;
+ typedef void reference;
+
+ _LIBCPP_HIDE_FROM_ABI ostream_joiner(ostream_type& __os, _Delim&& __d)
+ : __output_iter_(std::addressof(__os)), __delim_(std::move(__d)), __first_(true) {}
+
+ _LIBCPP_HIDE_FROM_ABI ostream_joiner(ostream_type& __os, const _Delim& __d)
+ : __output_iter_(std::addressof(__os)), __delim_(__d), __first_(true) {}
+
+ template <typename _Tp>
+ _LIBCPP_HIDE_FROM_ABI ostream_joiner& operator=(const _Tp& __v) {
+ if (!__first_)
+ *__output_iter_ << __delim_;
+ __first_ = false;
+ *__output_iter_ << __v;
+ return *this;
+ }
+
+ _LIBCPP_HIDE_FROM_ABI ostream_joiner& operator*() _NOEXCEPT { return *this; }
+ _LIBCPP_HIDE_FROM_ABI ostream_joiner& operator++() _NOEXCEPT { return *this; }
+ _LIBCPP_HIDE_FROM_ABI ostream_joiner& operator++(int) _NOEXCEPT { return *this; }
+
+private:
+ ostream_type* __output_iter_;
+ _Delim __delim_;
+ bool __first_;
+};
+
+template <class _CharT, class _Traits, class _Delim>
+_LIBCPP_HIDE_FROM_ABI ostream_joiner<__decay_t<_Delim>, _CharT, _Traits>
+make_ostream_joiner(basic_ostream<_CharT, _Traits>& __os, _Delim&& __d) {
+ return ostream_joiner<__decay_t<_Delim>, _CharT, _Traits>(__os, std::forward<_Delim>(__d));
+}
+
+_LIBCPP_END_NAMESPACE_LFTS
+
+# endif // _LIBCPP_STD_VER >= 14
+
+_LIBCPP_POP_MACROS
+
+# if !defined(_LIBCPP_REMOVE_TRANSITIVE_INCLUDES) && _LIBCPP_STD_VER <= 20
+# include <cstddef>
+# include <iosfwd>
+# include <optional>
+# include <type_traits>
+# endif
+
+# if !defined(_LIBCPP_REMOVE_TRANSITIVE_INCLUDES) && _LIBCPP_STD_VER <= 23
+# include <locale>
+# endif
+
+#endif // __cplusplus < 201103L && defined(_LIBCPP_USE_FROZEN_CXX03_HEADERS)
+
+#endif // _LIBCPP_EXPERIMENTAL_ITERATOR
diff --git a/third_party/libcxx/include/c++/v1/experimental/memory b/third_party/libcxx/include/c++/v1/experimental/memory
new file mode 100644
index 0000000..ffbd8f3
--- /dev/null
+++ b/third_party/libcxx/include/c++/v1/experimental/memory
@@ -0,0 +1,205 @@
+// -*- C++ -*-
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef _LIBCPP_EXPERIMENTAL_MEMORY
+#define _LIBCPP_EXPERIMENTAL_MEMORY
+
+/*
+ experimental/memory synopsis
+
+namespace std::experimental::inline fundamentals_v2 {
+
+template <class W> class observer_ptr {
+public:
+ using element_type = W;
+ using pointer = add_pointer_t<W>; // exposition-only
+ using reference = add_lvalue_reference_t<W>; // exposition-only
+
+ // default ctor
+ constexpr observer_ptr() noexcept;
+
+ // pointer-accepting ctors
+ constexpr observer_ptr(nullptr_t) noexcept;
+ constexpr explicit observer_ptr(pointer) noexcept;
+
+ // copying ctors (in addition to compiler-generated copy ctor)
+ template <class W2> constexpr observer_ptr(observer_ptr<W2>) noexcept;
+
+ // observers
+ constexpr pointer get() const noexcept;
+ constexpr reference operator*() const;
+ constexpr pointer operator->() const noexcept;
+ constexpr explicit operator bool() const noexcept;
+
+ // conversions
+ constexpr explicit operator pointer() const noexcept;
+
+ // modifiers
+ constexpr pointer release() noexcept;
+ constexpr void reset(pointer = nullptr) noexcept;
+ constexpr void swap(observer_ptr&) noexcept;
+};
+
+}
+*/
+
+#if __cplusplus < 201103L && defined(_LIBCPP_USE_FROZEN_CXX03_HEADERS)
+# include <__cxx03/__config>
+#else
+# include <__config>
+# include <__cstddef/nullptr_t.h>
+# include <__cstddef/size_t.h>
+# include <__functional/hash.h>
+# include <__functional/operations.h>
+# include <__type_traits/add_pointer.h>
+# include <__type_traits/add_reference.h>
+# include <__type_traits/common_type.h>
+# include <__type_traits/enable_if.h>
+# include <__type_traits/is_convertible.h>
+# include <version>
+
+# if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
+# pragma GCC system_header
+# endif
+
+# ifdef _LIBCPP_ENABLE_EXPERIMENTAL
+
+_LIBCPP_BEGIN_NAMESPACE_LFTS_V2
+
+# if _LIBCPP_STD_VER >= 17
+
+template <class _Wp>
+class observer_ptr {
+public:
+ using element_type = _Wp;
+
+ // constructors
+ _LIBCPP_HIDE_FROM_ABI constexpr observer_ptr() noexcept : __ptr_(nullptr) {}
+ _LIBCPP_HIDE_FROM_ABI constexpr observer_ptr(nullptr_t) noexcept : __ptr_(nullptr) {}
+ _LIBCPP_HIDE_FROM_ABI constexpr explicit observer_ptr(element_type* __p) noexcept : __ptr_(__p) {}
+
+ template <class _W2, __enable_if_t<is_convertible<_W2*, _Wp*>::value, int> = 0>
+ _LIBCPP_HIDE_FROM_ABI constexpr observer_ptr(observer_ptr<_W2> __other) noexcept : __ptr_(__other.get()) {}
+
+ // observers
+ _LIBCPP_HIDE_FROM_ABI constexpr element_type* get() const noexcept { return __ptr_; }
+ _LIBCPP_HIDE_FROM_ABI constexpr add_lvalue_reference_t<_Wp> operator*() const { return *__ptr_; }
+ _LIBCPP_HIDE_FROM_ABI constexpr element_type* operator->() const noexcept { return __ptr_; }
+ _LIBCPP_HIDE_FROM_ABI constexpr explicit operator bool() const noexcept { return __ptr_ != nullptr; }
+
+ // conversions
+ _LIBCPP_HIDE_FROM_ABI constexpr explicit operator element_type*() const noexcept { return __ptr_; }
+
+ // modifiers
+ _LIBCPP_HIDE_FROM_ABI constexpr void reset(element_type* __p = nullptr) noexcept { __ptr_ = __p; }
+ _LIBCPP_HIDE_FROM_ABI constexpr void swap(observer_ptr& __other) noexcept {
+ observer_ptr __tmp = __other;
+ __other = *this;
+ *this = __tmp;
+ }
+ _LIBCPP_HIDE_FROM_ABI constexpr element_type* release() noexcept {
+ observer_ptr __p;
+ __p.swap(*this);
+ return __p.get();
+ }
+
+private:
+ element_type* __ptr_;
+};
+
+// specializations
+
+template <class _Wp>
+_LIBCPP_HIDE_FROM_ABI constexpr void swap(observer_ptr<_Wp>& __a, observer_ptr<_Wp>& __b) noexcept {
+ __a.swap(__b);
+}
+
+template <class _Wp>
+_LIBCPP_HIDE_FROM_ABI observer_ptr<_Wp> make_observer(_Wp* __ptr) noexcept {
+ return observer_ptr<_Wp>{__ptr};
+}
+
+template <class _W1, class _W2>
+_LIBCPP_HIDE_FROM_ABI bool operator==(observer_ptr<_W1> __a, observer_ptr<_W2> __b) {
+ return __a.get() == __b.get();
+}
+
+template <class _W1, class _W2>
+_LIBCPP_HIDE_FROM_ABI bool operator!=(observer_ptr<_W1> __a, observer_ptr<_W2> __b) {
+ return !(__a == __b);
+}
+
+template <class _Wp>
+_LIBCPP_HIDE_FROM_ABI bool operator==(observer_ptr<_Wp> __p, nullptr_t) {
+ return !__p;
+}
+
+template <class _Wp>
+_LIBCPP_HIDE_FROM_ABI bool operator==(nullptr_t, observer_ptr<_Wp> __p) {
+ return !__p;
+}
+
+template <class _Wp>
+_LIBCPP_HIDE_FROM_ABI bool operator!=(observer_ptr<_Wp> __p, nullptr_t) {
+ return (bool)__p;
+}
+
+template <class _Wp>
+_LIBCPP_HIDE_FROM_ABI bool operator!=(nullptr_t, observer_ptr<_Wp> __p) {
+ return (bool)__p;
+}
+
+template <class _W1, class _W2>
+_LIBCPP_HIDE_FROM_ABI bool operator<(observer_ptr<_W1> __a, observer_ptr<_W2> __b) {
+ return std::less<typename std::common_type<_W1*, _W2*>::type>()(__a.get(), __b.get());
+}
+
+template <class _W1, class _W2>
+_LIBCPP_HIDE_FROM_ABI bool operator>(observer_ptr<_W1> __a, observer_ptr<_W2> __b) {
+ return __b < __a;
+}
+
+template <class _W1, class _W2>
+_LIBCPP_HIDE_FROM_ABI bool operator<=(observer_ptr<_W1> __a, observer_ptr<_W2> __b) {
+ return !(__a > __b);
+}
+
+template <class _W1, class _W2>
+_LIBCPP_HIDE_FROM_ABI bool operator>=(observer_ptr<_W1> __a, observer_ptr<_W2> __b) {
+ return !(__a < __b);
+}
+
+# endif // _LIBCPP_STD_VER >= 17
+
+_LIBCPP_END_NAMESPACE_LFTS_V2
+
+_LIBCPP_BEGIN_NAMESPACE_STD
+
+// hash
+
+# if _LIBCPP_STD_VER >= 17
+template <class _Tp>
+struct hash<experimental::observer_ptr<_Tp>> {
+ _LIBCPP_HIDE_FROM_ABI size_t operator()(const experimental::observer_ptr<_Tp>& __ptr) const noexcept {
+ return hash<_Tp*>()(__ptr.get());
+ }
+};
+# endif // _LIBCPP_STD_VER >= 17
+
+_LIBCPP_END_NAMESPACE_STD
+
+# endif // _LIBCPP_ENABLE_EXPERIMENTAL
+
+# if !defined(_LIBCPP_REMOVE_TRANSITIVE_INCLUDES) && _LIBCPP_STD_VER <= 20
+# include <cstddef>
+# include <limits>
+# endif
+#endif // __cplusplus < 201103L && defined(_LIBCPP_USE_FROZEN_CXX03_HEADERS)
+
+#endif /* _LIBCPP_EXPERIMENTAL_MEMORY */
diff --git a/third_party/libcxx/include/c++/v1/experimental/propagate_const b/third_party/libcxx/include/c++/v1/experimental/propagate_const
new file mode 100644
index 0000000..6a7f8ae
--- /dev/null
+++ b/third_party/libcxx/include/c++/v1/experimental/propagate_const
@@ -0,0 +1,497 @@
+// -*- C++ -*-
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef _LIBCPP_EXPERIMENTAL_PROPAGATE_CONST
+#define _LIBCPP_EXPERIMENTAL_PROPAGATE_CONST
+
+/*
+ propagate_const synopsis
+
+ namespace std { namespace experimental { inline namespace fundamentals_v2 {
+
+ // [propagate_const]
+ template <class T> class propagate_const;
+
+ // [propagate_const.underlying], underlying pointer access
+ constexpr const _Tp& get_underlying(const propagate_const<T>& pt) noexcept;
+ constexpr T& get_underlying(propagate_const<T>& pt) noexcept;
+
+ // [propagate_const.relational], relational operators
+ template <class T> constexpr bool operator==(const propagate_const<T>& pt, nullptr_t);
+ template <class T> constexpr bool operator==(nullptr_t, const propagate_const<T>& pu);
+ template <class T> constexpr bool operator!=(const propagate_const<T>& pt, nullptr_t);
+ template <class T> constexpr bool operator!=(nullptr_t, const propagate_const<T>& pu);
+ template <class T, class U> constexpr bool operator==(const propagate_const<T>& pt, const propagate_const<_Up>& pu);
+ template <class T, class U> constexpr bool operator!=(const propagate_const<T>& pt, const propagate_const<_Up>& pu);
+ template <class T, class U> constexpr bool operator<(const propagate_const<T>& pt, const propagate_const<_Up>& pu);
+ template <class T, class U> constexpr bool operator>(const propagate_const<T>& pt, const propagate_const<_Up>& pu);
+ template <class T, class U> constexpr bool operator<=(const propagate_const<T>& pt, const propagate_const<_Up>& pu);
+ template <class T, class U> constexpr bool operator>=(const propagate_const<T>& pt, const propagate_const<_Up>& pu);
+ template <class T, class U> constexpr bool operator==(const propagate_const<T>& pt, const _Up& u);
+ template <class T, class U> constexpr bool operator!=(const propagate_const<T>& pt, const _Up& u);
+ template <class T, class U> constexpr bool operator<(const propagate_const<T>& pt, const _Up& u);
+ template <class T, class U> constexpr bool operator>(const propagate_const<T>& pt, const _Up& u);
+ template <class T, class U> constexpr bool operator<=(const propagate_const<T>& pt, const _Up& u);
+ template <class T, class U> constexpr bool operator>=(const propagate_const<T>& pt, const _Up& u);
+ template <class T, class U> constexpr bool operator==(const _Tp& t, const propagate_const<_Up>& pu);
+ template <class T, class U> constexpr bool operator!=(const _Tp& t, const propagate_const<_Up>& pu);
+ template <class T, class U> constexpr bool operator<(const _Tp& t, const propagate_const<_Up>& pu);
+ template <class T, class U> constexpr bool operator>(const _Tp& t, const propagate_const<_Up>& pu);
+ template <class T, class U> constexpr bool operator<=(const _Tp& t, const propagate_const<_Up>& pu);
+ template <class T, class U> constexpr bool operator>=(const _Tp& t, const propagate_const<_Up>& pu);
+
+ // [propagate_const.algorithms], specialized algorithms
+ template <class T> constexpr void swap(propagate_const<T>& pt, propagate_const<T>& pu) noexcept(see below);
+
+ template <class T>
+ class propagate_const
+ {
+
+ public:
+ typedef remove_reference_t<decltype(*declval<T&>())> element_type;
+
+ // [propagate_const.ctor], constructors
+ constexpr propagate_const() = default;
+ propagate_const(const propagate_const& p) = delete;
+ constexpr propagate_const(propagate_const&& p) = default;
+ template <class U> EXPLICIT constexpr propagate_const(propagate_const<_Up>&& pu); // see below
+ template <class U> EXPLICIT constexpr propagate_const(U&& u); // see below
+
+ // [propagate_const.assignment], assignment
+ propagate_const& operator=(const propagate_const& p) = delete;
+ constexpr propagate_const& operator=(propagate_const&& p) = default;
+ template <class U> constexpr propagate_const& operator=(propagate_const<_Up>&& pu);
+ template <class U> constexpr propagate_const& operator=(U&& u); // see below
+
+ // [propagate_const.const_observers], const observers
+ explicit constexpr operator bool() const;
+ constexpr const element_type* operator->() const;
+ constexpr operator const element_type*() const; // Not always defined
+ constexpr const element_type& operator*() const;
+ constexpr const element_type* get() const;
+
+ // [propagate_const.non_const_observers], non-const observers
+ constexpr element_type* operator->();
+ constexpr operator element_type*(); // Not always defined
+ constexpr element_type& operator*();
+ constexpr element_type* get();
+
+ // [propagate_const.modifiers], modifiers
+ constexpr void swap(propagate_const& pt) noexcept(see below)
+
+ private:
+ T t_; // exposition only
+ };
+
+ } // namespace fundamentals_v2
+ } // namespace experimental
+
+ // [propagate_const.hash], hash support
+ template <class T> struct hash<experimental::propagate_const<T>>;
+
+ // [propagate_const.comparison_function_objects], comparison function objects
+ template <class T> struct equal_to<experimental::propagate_const<T>>;
+ template <class T> struct not_equal_to<experimental::propagate_const<T>>;
+ template <class T> struct less<experimental::propagate_const<T>>;
+ template <class T> struct greater<experimental::propagate_const<T>>;
+ template <class T> struct less_equal<experimental::propagate_const<T>>;
+ template <class T> struct greater_equal<experimental::propagate_const<T>>;
+
+} // namespace std
+
+*/
+
+#if __cplusplus < 201103L && defined(_LIBCPP_USE_FROZEN_CXX03_HEADERS)
+# include <__cxx03/__config>
+#else
+# include <__config>
+# include <__cstddef/nullptr_t.h>
+# include <__cstddef/size_t.h>
+# include <__functional/operations.h>
+# include <__fwd/functional.h>
+# include <__type_traits/conditional.h>
+# include <__type_traits/decay.h>
+# include <__type_traits/enable_if.h>
+# include <__type_traits/is_array.h>
+# include <__type_traits/is_constructible.h>
+# include <__type_traits/is_convertible.h>
+# include <__type_traits/is_function.h>
+# include <__type_traits/is_pointer.h>
+# include <__type_traits/is_reference.h>
+# include <__type_traits/is_same.h>
+# include <__type_traits/is_swappable.h>
+# include <__type_traits/remove_cv.h>
+# include <__type_traits/remove_pointer.h>
+# include <__type_traits/remove_reference.h>
+# include <__utility/declval.h>
+# include <__utility/forward.h>
+# include <__utility/move.h>
+# include <__utility/swap.h>
+# include <version>
+
+# if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
+# pragma GCC system_header
+# endif
+
+_LIBCPP_PUSH_MACROS
+# include <__undef_macros>
+
+# if _LIBCPP_STD_VER >= 14
+
+_LIBCPP_BEGIN_NAMESPACE_LFTS_V2
+
+template <class _Tp>
+class propagate_const;
+
+template <class _Up>
+inline _LIBCPP_HIDE_FROM_ABI constexpr const _Up& get_underlying(const propagate_const<_Up>& __pu) _NOEXCEPT;
+
+template <class _Up>
+inline _LIBCPP_HIDE_FROM_ABI constexpr _Up& get_underlying(propagate_const<_Up>& __pu) _NOEXCEPT;
+
+template <class _Tp>
+class propagate_const {
+public:
+ typedef remove_reference_t<decltype(*std::declval<_Tp&>())> element_type;
+
+ static_assert(!is_array<_Tp>::value, "Instantiation of propagate_const with an array type is ill-formed.");
+ static_assert(!is_reference<_Tp>::value, "Instantiation of propagate_const with a reference type is ill-formed.");
+ static_assert(!(is_pointer<_Tp>::value && is_function<__remove_pointer_t<_Tp> >::value),
+ "Instantiation of propagate_const with a function-pointer type is ill-formed.");
+ static_assert(!(is_pointer<_Tp>::value && is_same<__remove_cv_t<__remove_pointer_t<_Tp> >, void>::value),
+ "Instantiation of propagate_const with a pointer to (possibly cv-qualified) void is ill-formed.");
+
+private:
+ template <class _Up>
+ static _LIBCPP_HIDE_FROM_ABI constexpr element_type* __get_pointer(_Up* __u) {
+ return __u;
+ }
+
+ template <class _Up>
+ static _LIBCPP_HIDE_FROM_ABI constexpr element_type* __get_pointer(_Up& __u) {
+ return __get_pointer(__u.get());
+ }
+
+ template <class _Up>
+ static _LIBCPP_HIDE_FROM_ABI constexpr const element_type* __get_pointer(const _Up* __u) {
+ return __u;
+ }
+
+ template <class _Up>
+ static _LIBCPP_HIDE_FROM_ABI constexpr const element_type* __get_pointer(const _Up& __u) {
+ return __get_pointer(__u.get());
+ }
+
+ template <class _Up>
+ struct __is_propagate_const : false_type {};
+
+ template <class _Up>
+ struct __is_propagate_const<propagate_const<_Up>> : true_type {};
+
+ _Tp __t_;
+
+public:
+ template <class _Up>
+ friend constexpr const _Up& experimental::fundamentals_v2::get_underlying(const propagate_const<_Up>& __pu) _NOEXCEPT;
+ template <class _Up>
+ friend constexpr _Up& experimental::fundamentals_v2::get_underlying(propagate_const<_Up>& __pu) _NOEXCEPT;
+
+ _LIBCPP_HIDE_FROM_ABI constexpr propagate_const() = default;
+
+ propagate_const(const propagate_const&) = delete;
+
+ _LIBCPP_HIDE_FROM_ABI constexpr propagate_const(propagate_const&&) = default;
+
+ template <class _Up,
+ enable_if_t<!is_convertible<_Up, _Tp>::value && is_constructible<_Tp, _Up&&>::value, bool> = true>
+ explicit _LIBCPP_HIDE_FROM_ABI constexpr propagate_const(propagate_const<_Up>&& __pu)
+ : __t_(std::move(experimental::get_underlying(__pu))) {}
+
+ template <class _Up,
+ enable_if_t<is_convertible<_Up&&, _Tp>::value && is_constructible<_Tp, _Up&&>::value, bool> = false>
+ _LIBCPP_HIDE_FROM_ABI constexpr propagate_const(propagate_const<_Up>&& __pu)
+ : __t_(std::move(experimental::get_underlying(__pu))) {}
+
+ template <class _Up,
+ enable_if_t<!is_convertible<_Up&&, _Tp>::value && is_constructible<_Tp, _Up&&>::value &&
+ !__is_propagate_const<decay_t<_Up>>::value,
+ bool> = true>
+ explicit _LIBCPP_HIDE_FROM_ABI constexpr propagate_const(_Up&& __u) : __t_(std::forward<_Up>(__u)) {}
+
+ template <class _Up,
+ enable_if_t<is_convertible<_Up&&, _Tp>::value && is_constructible<_Tp, _Up&&>::value &&
+ !__is_propagate_const<decay_t<_Up>>::value,
+ bool> = false>
+ _LIBCPP_HIDE_FROM_ABI constexpr propagate_const(_Up&& __u) : __t_(std::forward<_Up>(__u)) {}
+
+ propagate_const& operator=(const propagate_const&) = delete;
+
+ _LIBCPP_HIDE_FROM_ABI constexpr propagate_const& operator=(propagate_const&&) = default;
+
+ template <class _Up>
+ _LIBCPP_HIDE_FROM_ABI constexpr propagate_const& operator=(propagate_const<_Up>&& __pu) {
+ __t_ = std::move(experimental::get_underlying(__pu));
+ return *this;
+ }
+
+ template <class _Up, class _Vp = enable_if_t<!__is_propagate_const<decay_t<_Up>>::value>>
+ _LIBCPP_HIDE_FROM_ABI constexpr propagate_const& operator=(_Up&& __u) {
+ __t_ = std::forward<_Up>(__u);
+ return *this;
+ }
+
+ _LIBCPP_HIDE_FROM_ABI constexpr const element_type* get() const { return __get_pointer(__t_); }
+
+ _LIBCPP_HIDE_FROM_ABI constexpr element_type* get() { return __get_pointer(__t_); }
+
+ _LIBCPP_HIDE_FROM_ABI explicit constexpr operator bool() const { return get() != nullptr; }
+
+ _LIBCPP_HIDE_FROM_ABI constexpr const element_type* operator->() const { return get(); }
+
+ template <class _Dummy = _Tp, class _Up = enable_if_t<is_convertible< const _Dummy, const element_type*>::value>>
+ _LIBCPP_HIDE_FROM_ABI constexpr operator const element_type*() const {
+ return get();
+ }
+
+ _LIBCPP_HIDE_FROM_ABI constexpr const element_type& operator*() const { return *get(); }
+
+ _LIBCPP_HIDE_FROM_ABI constexpr element_type* operator->() { return get(); }
+
+ template <class _Dummy = _Tp, class _Up = enable_if_t< is_convertible<_Dummy, element_type*>::value>>
+ _LIBCPP_HIDE_FROM_ABI constexpr operator element_type*() {
+ return get();
+ }
+
+ _LIBCPP_HIDE_FROM_ABI constexpr element_type& operator*() { return *get(); }
+
+ _LIBCPP_HIDE_FROM_ABI constexpr void swap(propagate_const& __pt) noexcept(__is_nothrow_swappable_v<_Tp>) {
+ using std::swap;
+ swap(__t_, __pt.__t_);
+ }
+};
+
+template <class _Tp>
+_LIBCPP_HIDE_FROM_ABI constexpr bool operator==(const propagate_const<_Tp>& __pt, nullptr_t) {
+ return experimental::get_underlying(__pt) == nullptr;
+}
+
+template <class _Tp>
+_LIBCPP_HIDE_FROM_ABI constexpr bool operator==(nullptr_t, const propagate_const<_Tp>& __pt) {
+ return nullptr == experimental::get_underlying(__pt);
+}
+
+template <class _Tp>
+_LIBCPP_HIDE_FROM_ABI constexpr bool operator!=(const propagate_const<_Tp>& __pt, nullptr_t) {
+ return experimental::get_underlying(__pt) != nullptr;
+}
+
+template <class _Tp>
+_LIBCPP_HIDE_FROM_ABI constexpr bool operator!=(nullptr_t, const propagate_const<_Tp>& __pt) {
+ return nullptr != experimental::get_underlying(__pt);
+}
+
+template <class _Tp, class _Up>
+_LIBCPP_HIDE_FROM_ABI constexpr bool operator==(const propagate_const<_Tp>& __pt, const propagate_const<_Up>& __pu) {
+ return experimental::get_underlying(__pt) == experimental::get_underlying(__pu);
+}
+
+template <class _Tp, class _Up>
+_LIBCPP_HIDE_FROM_ABI constexpr bool operator!=(const propagate_const<_Tp>& __pt, const propagate_const<_Up>& __pu) {
+ return experimental::get_underlying(__pt) != experimental::get_underlying(__pu);
+}
+
+template <class _Tp, class _Up>
+_LIBCPP_HIDE_FROM_ABI constexpr bool operator<(const propagate_const<_Tp>& __pt, const propagate_const<_Up>& __pu) {
+ return experimental::get_underlying(__pt) < experimental::get_underlying(__pu);
+}
+
+template <class _Tp, class _Up>
+_LIBCPP_HIDE_FROM_ABI constexpr bool operator>(const propagate_const<_Tp>& __pt, const propagate_const<_Up>& __pu) {
+ return experimental::get_underlying(__pt) > experimental::get_underlying(__pu);
+}
+
+template <class _Tp, class _Up>
+_LIBCPP_HIDE_FROM_ABI constexpr bool operator<=(const propagate_const<_Tp>& __pt, const propagate_const<_Up>& __pu) {
+ return experimental::get_underlying(__pt) <= experimental::get_underlying(__pu);
+}
+
+template <class _Tp, class _Up>
+_LIBCPP_HIDE_FROM_ABI constexpr bool operator>=(const propagate_const<_Tp>& __pt, const propagate_const<_Up>& __pu) {
+ return experimental::get_underlying(__pt) >= experimental::get_underlying(__pu);
+}
+
+template <class _Tp, class _Up>
+_LIBCPP_HIDE_FROM_ABI constexpr bool operator==(const propagate_const<_Tp>& __pt, const _Up& __u) {
+ return experimental::get_underlying(__pt) == __u;
+}
+
+template <class _Tp, class _Up>
+_LIBCPP_HIDE_FROM_ABI constexpr bool operator!=(const propagate_const<_Tp>& __pt, const _Up& __u) {
+ return experimental::get_underlying(__pt) != __u;
+}
+
+template <class _Tp, class _Up>
+_LIBCPP_HIDE_FROM_ABI constexpr bool operator<(const propagate_const<_Tp>& __pt, const _Up& __u) {
+ return experimental::get_underlying(__pt) < __u;
+}
+
+template <class _Tp, class _Up>
+_LIBCPP_HIDE_FROM_ABI constexpr bool operator>(const propagate_const<_Tp>& __pt, const _Up& __u) {
+ return experimental::get_underlying(__pt) > __u;
+}
+
+template <class _Tp, class _Up>
+_LIBCPP_HIDE_FROM_ABI constexpr bool operator<=(const propagate_const<_Tp>& __pt, const _Up& __u) {
+ return experimental::get_underlying(__pt) <= __u;
+}
+
+template <class _Tp, class _Up>
+_LIBCPP_HIDE_FROM_ABI constexpr bool operator>=(const propagate_const<_Tp>& __pt, const _Up& __u) {
+ return experimental::get_underlying(__pt) >= __u;
+}
+
+template <class _Tp, class _Up>
+_LIBCPP_HIDE_FROM_ABI constexpr bool operator==(const _Tp& __t, const propagate_const<_Up>& __pu) {
+ return __t == experimental::get_underlying(__pu);
+}
+
+template <class _Tp, class _Up>
+_LIBCPP_HIDE_FROM_ABI constexpr bool operator!=(const _Tp& __t, const propagate_const<_Up>& __pu) {
+ return __t != experimental::get_underlying(__pu);
+}
+
+template <class _Tp, class _Up>
+_LIBCPP_HIDE_FROM_ABI constexpr bool operator<(const _Tp& __t, const propagate_const<_Up>& __pu) {
+ return __t < experimental::get_underlying(__pu);
+}
+
+template <class _Tp, class _Up>
+_LIBCPP_HIDE_FROM_ABI constexpr bool operator>(const _Tp& __t, const propagate_const<_Up>& __pu) {
+ return __t > experimental::get_underlying(__pu);
+}
+
+template <class _Tp, class _Up>
+_LIBCPP_HIDE_FROM_ABI constexpr bool operator<=(const _Tp& __t, const propagate_const<_Up>& __pu) {
+ return __t <= experimental::get_underlying(__pu);
+}
+
+template <class _Tp, class _Up>
+_LIBCPP_HIDE_FROM_ABI constexpr bool operator>=(const _Tp& __t, const propagate_const<_Up>& __pu) {
+ return __t >= experimental::get_underlying(__pu);
+}
+
+template <class _Tp>
+_LIBCPP_HIDE_FROM_ABI constexpr void
+swap(propagate_const<_Tp>& __pc1, propagate_const<_Tp>& __pc2) noexcept(__is_nothrow_swappable_v<_Tp>) {
+ __pc1.swap(__pc2);
+}
+
+template <class _Tp>
+constexpr const _Tp& get_underlying(const propagate_const<_Tp>& __pt) _NOEXCEPT {
+ return __pt.__t_;
+}
+
+template <class _Tp>
+constexpr _Tp& get_underlying(propagate_const<_Tp>& __pt) _NOEXCEPT {
+ return __pt.__t_;
+}
+
+_LIBCPP_END_NAMESPACE_LFTS_V2
+
+_LIBCPP_BEGIN_NAMESPACE_STD
+
+template <class _Tp>
+struct hash<experimental::propagate_const<_Tp>> {
+ typedef size_t result_type;
+ typedef experimental::propagate_const<_Tp> argument_type;
+
+ _LIBCPP_HIDE_FROM_ABI size_t operator()(const experimental::propagate_const<_Tp>& __pc1) const {
+ return std::hash<_Tp>()(experimental::get_underlying(__pc1));
+ }
+};
+
+template <class _Tp>
+struct equal_to<experimental::propagate_const<_Tp>> {
+ typedef experimental::propagate_const<_Tp> first_argument_type;
+ typedef experimental::propagate_const<_Tp> second_argument_type;
+
+ _LIBCPP_HIDE_FROM_ABI bool
+ operator()(const experimental::propagate_const<_Tp>& __pc1, const experimental::propagate_const<_Tp>& __pc2) const {
+ return std::equal_to<_Tp>()(experimental::get_underlying(__pc1), experimental::get_underlying(__pc2));
+ }
+};
+
+template <class _Tp>
+struct not_equal_to<experimental::propagate_const<_Tp>> {
+ typedef experimental::propagate_const<_Tp> first_argument_type;
+ typedef experimental::propagate_const<_Tp> second_argument_type;
+
+ _LIBCPP_HIDE_FROM_ABI bool
+ operator()(const experimental::propagate_const<_Tp>& __pc1, const experimental::propagate_const<_Tp>& __pc2) const {
+ return std::not_equal_to<_Tp>()(experimental::get_underlying(__pc1), experimental::get_underlying(__pc2));
+ }
+};
+
+template <class _Tp>
+struct less<experimental::propagate_const<_Tp>> {
+ typedef experimental::propagate_const<_Tp> first_argument_type;
+ typedef experimental::propagate_const<_Tp> second_argument_type;
+
+ _LIBCPP_HIDE_FROM_ABI bool
+ operator()(const experimental::propagate_const<_Tp>& __pc1, const experimental::propagate_const<_Tp>& __pc2) const {
+ return std::less<_Tp>()(experimental::get_underlying(__pc1), experimental::get_underlying(__pc2));
+ }
+};
+
+template <class _Tp>
+struct greater<experimental::propagate_const<_Tp>> {
+ typedef experimental::propagate_const<_Tp> first_argument_type;
+ typedef experimental::propagate_const<_Tp> second_argument_type;
+
+ _LIBCPP_HIDE_FROM_ABI bool
+ operator()(const experimental::propagate_const<_Tp>& __pc1, const experimental::propagate_const<_Tp>& __pc2) const {
+ return std::greater<_Tp>()(experimental::get_underlying(__pc1), experimental::get_underlying(__pc2));
+ }
+};
+
+template <class _Tp>
+struct less_equal<experimental::propagate_const<_Tp>> {
+ typedef experimental::propagate_const<_Tp> first_argument_type;
+ typedef experimental::propagate_const<_Tp> second_argument_type;
+
+ _LIBCPP_HIDE_FROM_ABI bool
+ operator()(const experimental::propagate_const<_Tp>& __pc1, const experimental::propagate_const<_Tp>& __pc2) const {
+ return std::less_equal<_Tp>()(experimental::get_underlying(__pc1), experimental::get_underlying(__pc2));
+ }
+};
+
+template <class _Tp>
+struct greater_equal<experimental::propagate_const<_Tp>> {
+ typedef experimental::propagate_const<_Tp> first_argument_type;
+ typedef experimental::propagate_const<_Tp> second_argument_type;
+
+ _LIBCPP_HIDE_FROM_ABI bool
+ operator()(const experimental::propagate_const<_Tp>& __pc1, const experimental::propagate_const<_Tp>& __pc2) const {
+ return std::greater_equal<_Tp>()(experimental::get_underlying(__pc1), experimental::get_underlying(__pc2));
+ }
+};
+
+_LIBCPP_END_NAMESPACE_STD
+
+# endif // _LIBCPP_STD_VER >= 14
+
+_LIBCPP_POP_MACROS
+
+# if !defined(_LIBCPP_REMOVE_TRANSITIVE_INCLUDES) && _LIBCPP_STD_VER <= 20
+# include <cstddef>
+# include <type_traits>
+# endif
+#endif // __cplusplus < 201103L && defined(_LIBCPP_USE_FROZEN_CXX03_HEADERS)
+
+#endif // _LIBCPP_EXPERIMENTAL_PROPAGATE_CONST
diff --git a/third_party/libcxx/include/c++/v1/experimental/simd b/third_party/libcxx/include/c++/v1/experimental/simd
new file mode 100644
index 0000000..2e1c781
--- /dev/null
+++ b/third_party/libcxx/include/c++/v1/experimental/simd
@@ -0,0 +1,96 @@
+// -*- C++ -*-
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef _LIBCPP_EXPERIMENTAL_SIMD
+#define _LIBCPP_EXPERIMENTAL_SIMD
+
+/*
+ experimental/simd synopsis
+
+namespace std::experimental {
+inline namespace parallelism_v2 {
+ namespace simd_abi {
+ using scalar = see below;
+ template<int N> using fixed_size = see below;
+ template<class T> inline constexpr int max_fixed_size = implementation-defined;
+ template<class T> using compatible = implementation-defined;
+ template<class T> using native = implementation-defined;
+
+ template<class T, size_t N, class... Abis> struct deduce { using type = see below; };
+ template<class T, size_t N, class... Abis> using deduce_t =
+ typename deduce<T, N, Abis...>::type;
+ } // namespace simd_abi
+
+ // class template simd [simd.class]
+ template <class T, class Abi = simd_abi::compatible<T>> class simd;
+ template <class T> using native_simd = simd<T, simd_abi::native<T>>;
+ template <class T, int N> using fixed_size_simd = simd<T, simd_abi::fixed_size<N>>;
+
+ // class template simd_mask [simd.mask.class]
+ template <class T, class Abi = simd_abi::compatible<T>> class simd_mask;
+ template <class T> using native_simd_mask = simd_mask<T, simd_abi::native<T>>;
+ template <class T, int N> using fixed_size_simd_mask = simd_mask<T, simd_abi::fixed_size<N>>;
+
+ // memory alignment
+ struct element_aligned_tag {};
+ struct vector_aligned_tag {};
+ template <size_t> struct overaligned_tag {};
+ inline constexpr element_aligned_tag element_aligned{};
+ inline constexpr vector_aligned_tag vector_aligned{};
+ template <size_t N> inline constexpr overaligned_tag<N> overaligned{};
+
+ // traits [simd.traits]
+ template<class T> struct is_abi_tag;
+ template<class T> inline constexpr bool is_abi_tag_v = is_abi_tag<T>::value;
+
+ template <class T> struct is_simd;
+ template <class T> inline constexpr bool is_simd_v = is_simd<T>::value;
+
+ template <class T> struct is_simd_mask;
+ template <class T> inline constexpr bool is_simd_mask_v = is_simd_mask<T>::value;
+
+ template<class T> struct is_simd_flag_type;
+ template<class T> inline constexpr bool is_simd_flag_type_v = is_simd_flag_type<T>::value;
+
+ template<class T, class Abi = simd_abi::compatible<T>> struct simd_size;
+ template<class T, class Abi = simd_abi::compatible<T>>
+ inline constexpr size_t simd_size_v = simd_size<T,Abi>::value;
+
+ template<class T, class U = typename T::value_type> struct memory_alignment;
+ template<class T, class U = typename T::value_type>
+ inline constexpr size_t memory_alignment_v = memory_alignment<T,U>::value;
+
+} // namespace parallelism_v2
+} // namespace std::experimental
+
+*/
+
+#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
+# pragma GCC system_header
+#endif
+
+#if __cplusplus < 201103L && defined(_LIBCPP_USE_FROZEN_CXX03_HEADERS)
+# include <__cxx03/__config>
+#else
+# include <__config>
+# include <experimental/__simd/aligned_tag.h>
+# include <experimental/__simd/declaration.h>
+# include <experimental/__simd/reference.h>
+# include <experimental/__simd/scalar.h>
+# include <experimental/__simd/simd.h>
+# include <experimental/__simd/simd_mask.h>
+# include <experimental/__simd/traits.h>
+# include <experimental/__simd/vec_ext.h>
+
+# if !defined(_LIBCPP_REMOVE_TRANSITIVE_INCLUDES) && _LIBCPP_STD_VER <= 20
+# include <cstddef>
+# endif
+#endif // __cplusplus < 201103L && defined(_LIBCPP_USE_FROZEN_CXX03_HEADERS)
+
+#endif /* _LIBCPP_EXPERIMENTAL_SIMD */
diff --git a/third_party/libcxx/include/c++/v1/experimental/type_traits b/third_party/libcxx/include/c++/v1/experimental/type_traits
new file mode 100644
index 0000000..fd03546
--- /dev/null
+++ b/third_party/libcxx/include/c++/v1/experimental/type_traits
@@ -0,0 +1,161 @@
+// -*- C++ -*-
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef _LIBCPP_EXPERIMENTAL_TYPE_TRAITS
+#define _LIBCPP_EXPERIMENTAL_TYPE_TRAITS
+
+/**
+ experimental/type_traits synopsis
+
+// C++1y
+#include <type_traits>
+
+namespace std {
+namespace experimental {
+inline namespace fundamentals_v1 {
+
+ // 3.3.2, Other type transformations
+ template <class> class invocation_type; // not defined
+ template <class F, class... ArgTypes> class invocation_type<F(ArgTypes...)>;
+ template <class> class raw_invocation_type; // not defined
+ template <class F, class... ArgTypes> class raw_invocation_type<F(ArgTypes...)>;
+
+ template <class T>
+ using invocation_type_t = typename invocation_type<T>::type;
+ template <class T>
+ using raw_invocation_type_t = typename raw_invocation_type<T>::type;
+
+ // 3.3.4, Detection idiom
+ template <class...> using void_t = void;
+
+ struct nonesuch {
+ nonesuch() = delete;
+ ~nonesuch() = delete;
+ nonesuch(nonesuch const&) = delete;
+ void operator=(nonesuch const&) = delete;
+ };
+
+ template <template<class...> class Op, class... Args>
+ using is_detected = see below;
+ template <template<class...> class Op, class... Args>
+ constexpr bool is_detected_v = is_detected<Op, Args...>::value;
+ template <template<class...> class Op, class... Args>
+ using detected_t = see below;
+ template <class Default, template<class...> class Op, class... Args>
+ using detected_or = see below;
+ template <class Default, template<class...> class Op, class... Args>
+ using detected_or_t = typename detected_or<Default, Op, Args...>::type;
+ template <class Expected, template<class...> class Op, class... Args>
+ using is_detected_exact = is_same<Expected, detected_t<Op, Args...>>;
+ template <class Expected, template<class...> class Op, class... Args>
+ constexpr bool is_detected_exact_v
+ = is_detected_exact<Expected, Op, Args...>::value;
+ template <class To, template<class...> class Op, class... Args>
+ using is_detected_convertible = is_convertible<detected_t<Op, Args...>, To>;
+ template <class To, template<class...> class Op, class... Args>
+ constexpr bool is_detected_convertible_v
+ = is_detected_convertible<To, Op, Args...>::value;
+
+} // namespace fundamentals_v1
+} // namespace experimental
+} // namespace std
+
+ */
+
+#if __cplusplus < 201103L && defined(_LIBCPP_USE_FROZEN_CXX03_HEADERS)
+# include <__cxx03/__config>
+#else
+# include <__config>
+
+# if _LIBCPP_STD_VER >= 14
+
+# include <initializer_list>
+# include <type_traits>
+
+# if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
+# pragma GCC system_header
+# endif
+
+_LIBCPP_BEGIN_NAMESPACE_LFTS
+
+// 3.3.2, Other type transformations
+/*
+template <class>
+class raw_invocation_type;
+
+template <class _Fn, class ..._Args>
+class raw_invocation_type<_Fn(_Args...)>;
+
+template <class>
+class invokation_type;
+
+template <class _Fn, class ..._Args>
+class invokation_type<_Fn(_Args...)>;
+
+template <class _Tp>
+using invokation_type_t = typename invokation_type<_Tp>::type;
+
+template <class _Tp>
+using raw_invocation_type_t = typename raw_invocation_type<_Tp>::type;
+*/
+
+// 3.3.4, Detection idiom
+template <class...>
+using void_t = void;
+
+struct nonesuch : private __nat { // make nonesuch "not an aggregate"
+ ~nonesuch() = delete;
+ nonesuch(nonesuch const&) = delete;
+ void operator=(nonesuch const&) = delete;
+};
+
+template <class _Default, class _AlwaysVoid, template <class...> class _Op, class... _Args>
+struct _DETECTOR {
+ using value_t = false_type;
+ using type = _Default;
+};
+
+template <class _Default, template <class...> class _Op, class... _Args>
+struct _DETECTOR<_Default, void_t<_Op<_Args...>>, _Op, _Args...> {
+ using value_t = true_type;
+ using type = _Op<_Args...>;
+};
+
+template <template <class...> class _Op, class... _Args>
+using is_detected = typename _DETECTOR<nonesuch, void, _Op, _Args...>::value_t;
+template <template <class...> class _Op, class... _Args>
+using detected_t = typename _DETECTOR<nonesuch, void, _Op, _Args...>::type;
+template <template <class...> class _Op, class... _Args>
+constexpr bool is_detected_v = is_detected<_Op, _Args...>::value;
+
+template <class _Default, template <class...> class _Op, class... _Args>
+using detected_or = _DETECTOR<_Default, void, _Op, _Args...>;
+template <class _Default, template <class...> class _Op, class... _Args>
+using detected_or_t = typename detected_or<_Default, _Op, _Args...>::type;
+
+template <class _Expected, template <class...> class _Op, class... _Args>
+using is_detected_exact = is_same<_Expected, detected_t<_Op, _Args...>>;
+template <class _Expected, template <class...> class _Op, class... _Args>
+constexpr bool is_detected_exact_v = is_detected_exact<_Expected, _Op, _Args...>::value;
+
+template <class _To, template <class...> class _Op, class... _Args>
+using is_detected_convertible = is_convertible<detected_t<_Op, _Args...>, _To>;
+template <class _To, template <class...> class _Op, class... _Args>
+constexpr bool is_detected_convertible_v = is_detected_convertible<_To, _Op, _Args...>::value;
+
+_LIBCPP_END_NAMESPACE_LFTS
+
+# if !defined(_LIBCPP_REMOVE_TRANSITIVE_INCLUDES) && _LIBCPP_STD_VER <= 20
+# include <cstddef>
+# endif
+
+# endif /* _LIBCPP_STD_VER >= 14 */
+#endif // __cplusplus < 201103L && defined(_LIBCPP_USE_FROZEN_CXX03_HEADERS)
+
+#endif /* _LIBCPP_EXPERIMENTAL_TYPE_TRAITS */
diff --git a/third_party/libcxx/include/c++/v1/experimental/utility b/third_party/libcxx/include/c++/v1/experimental/utility
new file mode 100644
index 0000000..fb0537f
--- /dev/null
+++ b/third_party/libcxx/include/c++/v1/experimental/utility
@@ -0,0 +1,54 @@
+// -*- C++ -*-
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef _LIBCPP_EXPERIMENTAL_UTILITY
+#define _LIBCPP_EXPERIMENTAL_UTILITY
+
+/*
+ experimental/utility synopsis
+
+// C++1y
+
+#include <utility>
+
+namespace std {
+namespace experimental {
+inline namespace fundamentals_v1 {
+
+ 3.1.2, erased-type placeholder
+ struct erased_type { };
+
+} // namespace fundamentals_v1
+} // namespace experimental
+} // namespace std
+
+ */
+
+#if __cplusplus < 201103L && defined(_LIBCPP_USE_FROZEN_CXX03_HEADERS)
+# include <__cxx03/experimental/utility>
+#else
+# include <__config>
+# include <utility>
+
+# if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
+# pragma GCC system_header
+# endif
+
+_LIBCPP_BEGIN_NAMESPACE_LFTS
+
+struct erased_type {};
+
+_LIBCPP_END_NAMESPACE_LFTS
+
+# if !defined(_LIBCPP_REMOVE_TRANSITIVE_INCLUDES) && _LIBCPP_STD_VER <= 20
+# include <cstddef>
+# endif
+#endif // __cplusplus < 201103L && defined(_LIBCPP_USE_FROZEN_CXX03_HEADERS)
+
+#endif /* _LIBCPP_EXPERIMENTAL_UTILITY */