From 81bdbcb3e093feddc1df46e4d9ee51201ef4663a Mon Sep 17 00:00:00 2001 From: trcrsired Date: Mon, 19 Jan 2026 18:19:23 +0800 Subject: [PATCH 01/42] implement something for fast_io deque --- include/fast_io_dsal/impl/deque.h | 43 +++++++++++++++++++++++++++---- 1 file changed, 38 insertions(+), 5 deletions(-) diff --git a/include/fast_io_dsal/impl/deque.h b/include/fast_io_dsal/impl/deque.h index e0746405..95bfde0c 100644 --- a/include/fast_io_dsal/impl/deque.h +++ b/include/fast_io_dsal/impl/deque.h @@ -1419,13 +1419,34 @@ inline constexpr void deque_reserve_back_blocks_impl(dequecontroltype &controlle controller.back_end_ptr = begin_ptr + blockbytes; } -#if 0 template inline constexpr void deque_reserve_back_spaces(dequecontroltype &controller, ::std::size_t n) { + if (!n) + { + return; + } + ::std::size_t blocksn{static_cast<::std::size_t>(controller.back_block.end_ptr - controller.back_block.curr_ptr)}; + if (n <= blocksn) + { + controller.back_block.curr_ptr += n; + return; + } + ::std::size_t back_more_blocks{static_cast<::std::size_t>(n - blocksn) / block_size}; + if consteval + { + ::fast_io::containers::details::deque_rebalance_or_grow_insertation_impl(controller, + back_more_blocks, align, block_size); + } + else + { + constexpr ::std::size_t block_bytes{block_size * sz}; + ::fast_io::containers::details::deque_rebalance_or_grow_insertation_impl(*reinterpret_cast<::fast_io::containers::details::deque_controller_common *>( + __builtin_addressof(controller), + back_more_blocks, align, block_bytes)); + } } #endif -#endif } // namespace details @@ -2189,21 +2210,33 @@ class deque FAST_IO_TRIVIALLY_RELOCATABLE_IF_ELIGIBLE requires ::std::constructible_from> inline constexpr insert_range_result insert_range_impl(size_type pos, R &&rg, size_type old_size) noexcept(::std::is_nothrow_constructible_v>) { -#if 0 - if constexpr(::std::ranges::sized_range) + if constexpr (::std::ranges::sized_range && 0) { size_type const rgsize{::std::ranges::size(rg)}; + if (!rgsize) + { + return {pos, this->begin() + pos}; + } +#if 0 size_type const half_size{old_size >> 1u}; if (pos < half_size) { } else +#endif { + ::fast_io::containers::details::deque_reserve_back_spaces(this->controller, rgsize); + auto posit{this->begin() + pos}; + auto thisend{this->end()}; + ::fast_io::freestanding::uninitialized_relocate_backward(posit, + thisend - rgsize, thisend); + ::fast_io::freestanding::uninitialized_copy_n(::std::ranges::cbegin(rg), rgsize, posit); + return {pos, posit}; } } else -#endif { size_type const quarterold_size{old_size >> 2u}; size_type retpos; From 71697ee5d02d7bbc5a2fbdac9fb93e324cc7bade Mon Sep 17 00:00:00 2001 From: trcrsired Date: Tue, 20 Jan 2026 05:06:24 +0800 Subject: [PATCH 02/42] [skip ci] deque fixes the compilation issues --- include/fast_io_dsal/impl/deque.h | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/include/fast_io_dsal/impl/deque.h b/include/fast_io_dsal/impl/deque.h index 95bfde0c..f3cdbaea 100644 --- a/include/fast_io_dsal/impl/deque.h +++ b/include/fast_io_dsal/impl/deque.h @@ -1426,7 +1426,7 @@ inline constexpr void deque_reserve_back_spaces(dequecontroltype &controller, :: { return; } - ::std::size_t blocksn{static_cast<::std::size_t>(controller.back_block.end_ptr - controller.back_block.curr_ptr)}; + ::std::size_t blocksn{static_cast<::std::size_t>(controller.back_end_ptr - controller.back_block.curr_ptr)}; if (n <= blocksn) { controller.back_block.curr_ptr += n; @@ -1435,15 +1435,15 @@ inline constexpr void deque_reserve_back_spaces(dequecontroltype &controller, :: ::std::size_t back_more_blocks{static_cast<::std::size_t>(n - blocksn) / block_size}; if consteval { - ::fast_io::containers::details::deque_rebalance_or_grow_insertation_impl(controller, - back_more_blocks, align, block_size); + ::fast_io::containers::details::deque_reserve_back_blocks_impl(controller, + back_more_blocks, align, block_size); } else { constexpr ::std::size_t block_bytes{block_size * sz}; - ::fast_io::containers::details::deque_rebalance_or_grow_insertation_impl(*reinterpret_cast<::fast_io::containers::details::deque_controller_common *>( - __builtin_addressof(controller), - back_more_blocks, align, block_bytes)); + ::fast_io::containers::details::deque_reserve_back_blocks_impl(*reinterpret_cast<::fast_io::containers::details::deque_controller_common *>( + __builtin_addressof(controller)), + back_more_blocks, align, block_bytes); } } #endif From cd207892347297731f11341c384275be50d95b32 Mon Sep 17 00:00:00 2001 From: trcrsired Date: Tue, 20 Jan 2026 05:51:39 +0800 Subject: [PATCH 03/42] [skip ci] the insert still has logic bugs --- include/fast_io_dsal/impl/deque.h | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/include/fast_io_dsal/impl/deque.h b/include/fast_io_dsal/impl/deque.h index f3cdbaea..3c167e16 100644 --- a/include/fast_io_dsal/impl/deque.h +++ b/include/fast_io_dsal/impl/deque.h @@ -1409,7 +1409,9 @@ inline constexpr void deque_reserve_back_blocks_impl(dequecontroltype &controlle controller.front_block.curr_ptr = controller.front_block.begin_ptr = front_begin_ptr; controller.front_end_ptr = front_begin_ptr + blockbytes; } - +#if 0 + ::fast_io::io::debug_println(::std::source_location::current()," \tnb=",nb); +#endif controller.back_block.controller_ptr += nb; auto begin_ptr = static_cast(*controller.back_block.controller_ptr); @@ -1432,7 +1434,9 @@ inline constexpr void deque_reserve_back_spaces(dequecontroltype &controller, :: controller.back_block.curr_ptr += n; return; } - ::std::size_t back_more_blocks{static_cast<::std::size_t>(n - blocksn) / block_size}; + ::std::size_t nmblocksn{n - blocksn}; + ::std::size_t const back_more_blocks{nmblocksn / block_size}; + ::std::size_t const back_more_blocks_mod{nmblocksn % block_size}; if consteval { ::fast_io::containers::details::deque_reserve_back_blocks_impl(controller, @@ -1445,6 +1449,7 @@ inline constexpr void deque_reserve_back_spaces(dequecontroltype &controller, :: __builtin_addressof(controller)), back_more_blocks, align, block_bytes); } + controller.back_block.curr_ptr = controller.front_block.begin_ptr + back_more_blocks_mod; } #endif @@ -2226,9 +2231,15 @@ class deque FAST_IO_TRIVIALLY_RELOCATABLE_IF_ELIGIBLE else #endif { +#if 0 + ::fast_io::io::debug_println(::std::source_location::current(),"\tthis->size()=", this->size()," rgsize=",rgsize); +#endif ::fast_io::containers::details::deque_reserve_back_spaces(this->controller, rgsize); auto posit{this->begin() + pos}; +#if 0 + ::fast_io::io::debug_println(::std::source_location::current(),"\tthis->size()=", this->size()," rgsize=",rgsize); +#endif auto thisend{this->end()}; ::fast_io::freestanding::uninitialized_relocate_backward(posit, thisend - rgsize, thisend); From d0105a53a3f06f66f8b42ea14b6eeefd65da1c9d Mon Sep 17 00:00:00 2001 From: trcrsired Date: Thu, 22 Jan 2026 03:55:20 +0800 Subject: [PATCH 04/42] deque insertation deal with back --- include/fast_io_dsal/impl/deque.h | 29 ++++++++++++++++++++++------- 1 file changed, 22 insertions(+), 7 deletions(-) diff --git a/include/fast_io_dsal/impl/deque.h b/include/fast_io_dsal/impl/deque.h index 3c167e16..e05ed3f5 100644 --- a/include/fast_io_dsal/impl/deque.h +++ b/include/fast_io_dsal/impl/deque.h @@ -1419,6 +1419,9 @@ inline constexpr void deque_reserve_back_blocks_impl(dequecontroltype &controlle controller.back_block.begin_ptr = begin_ptr; controller.back_block.curr_ptr = begin_ptr; controller.back_end_ptr = begin_ptr + blockbytes; +#if 0 + ::fast_io::io::debug_println(::std::source_location::current()," \tbegin_ptr=",::fast_io::mnp::pointervw(begin_ptr)); +#endif } template @@ -1428,28 +1431,35 @@ inline constexpr void deque_reserve_back_spaces(dequecontroltype &controller, :: { return; } - ::std::size_t blocksn{static_cast<::std::size_t>(controller.back_end_ptr - controller.back_block.curr_ptr)}; + auto back_curr_ptr{controller.back_block.curr_ptr}; + ::std::size_t blocksn{static_cast<::std::size_t>(controller.back_end_ptr - back_curr_ptr)}; if (n <= blocksn) { - controller.back_block.curr_ptr += n; + controller.back_block.curr_ptr = back_curr_ptr + n; return; } + ::std::size_t startpos{static_cast<::std::size_t>(back_curr_ptr - controller.back_block.begin_ptr)}; ::std::size_t nmblocksn{n - blocksn}; - ::std::size_t const back_more_blocks{nmblocksn / block_size}; + ::std::size_t back_more_blocks{nmblocksn / block_size}; ::std::size_t const back_more_blocks_mod{nmblocksn % block_size}; + ::std::size_t toallocate{back_more_blocks}; + if (back_more_blocks_mod) + { + ++toallocate; + } if consteval { ::fast_io::containers::details::deque_reserve_back_blocks_impl(controller, - back_more_blocks, align, block_size); + toallocate, align, block_size); } else { constexpr ::std::size_t block_bytes{block_size * sz}; ::fast_io::containers::details::deque_reserve_back_blocks_impl(*reinterpret_cast<::fast_io::containers::details::deque_controller_common *>( __builtin_addressof(controller)), - back_more_blocks, align, block_bytes); + toallocate, align, block_bytes); } - controller.back_block.curr_ptr = controller.front_block.begin_ptr + back_more_blocks_mod; + controller.back_block.curr_ptr = controller.back_block.begin_ptr + back_more_blocks_mod; } #endif @@ -2215,7 +2225,12 @@ class deque FAST_IO_TRIVIALLY_RELOCATABLE_IF_ELIGIBLE requires ::std::constructible_from> inline constexpr insert_range_result insert_range_impl(size_type pos, R &&rg, size_type old_size) noexcept(::std::is_nothrow_constructible_v>) { - if constexpr (::std::ranges::sized_range && 0) + constexpr bool enable_size_insertation{ +#ifdef FAST_IO_DEBUG_ENABLE_SIZE_INSERTATION + true // we haven't yet finished this so we use a macro. will remove it later on +#endif + }; + if constexpr (::std::ranges::sized_range && enable_size_insertation) { size_type const rgsize{::std::ranges::size(rg)}; if (!rgsize) From b405c0ece86aa8fb6c5e8a021c047bcc9e6b1cf3 Mon Sep 17 00:00:00 2001 From: trcrsired Date: Thu, 22 Jan 2026 04:06:06 +0800 Subject: [PATCH 05/42] add deque insert fuzzing --- .../deque/fuzz_deque_insert.cc | 87 +++++++++++++++++++ include/fast_io_dsal/impl/deque.h | 2 +- 2 files changed, 88 insertions(+), 1 deletion(-) create mode 100644 fuzzing/0007.containers/deque/fuzz_deque_insert.cc diff --git a/fuzzing/0007.containers/deque/fuzz_deque_insert.cc b/fuzzing/0007.containers/deque/fuzz_deque_insert.cc new file mode 100644 index 00000000..1c0e5463 --- /dev/null +++ b/fuzzing/0007.containers/deque/fuzz_deque_insert.cc @@ -0,0 +1,87 @@ +#include +#include +#include +#include +#include +#include +#include +#include + +extern "C" int LLVMFuzzerTestOneInput(uint8_t const *data, size_t size) +{ + ::fast_io::deque dq; + std::deque ref; + + for (size_t i{}; i != size; ++i) + { + uint8_t b = data[i]; + + uint8_t op = b & 0x3u; // 4 operations + std::size_t len = (b >> 2) & 0x7u; // insert 0–7 elements + + // Always valid position: [0, size] + std::size_t pos = dq.size() == 0 ? 0 : (static_cast(b) * 37u) % (dq.size() + 1); + + // Build deterministic range + std::vector rg; + rg.reserve(len); + for (std::size_t j{}; j < len; ++j) + { + rg.push_back(i * 1315423911ull + j); + } + + switch (op) + { + case 0: // insert_range_index + { + dq.insert_range_index(pos, rg); + ref.insert(ref.begin() + pos, rg.begin(), rg.end()); + break; + } + + case 1: // insert_range using iterator + { + auto it = dq.insert_range(dq.cbegin() + pos, rg); + (void)it; + ref.insert(ref.begin() + pos, rg.begin(), rg.end()); + break; + } + + case 2: // erase single element (to keep sizes bounded) + { + if (!ref.empty()) + { + std::size_t p = pos % ref.size(); + dq.erase_index(p); + ref.erase(ref.begin() + p); + } + break; + } + + case 3: // erase small range + { + if (!ref.empty()) + { + std::size_t p = pos % ref.size(); + std::size_t rlen = len % (ref.size() - p); + dq.erase_index(p, p + rlen); + ref.erase(ref.begin() + p, ref.begin() + p + rlen); + } + break; + } + } + + // Validate correctness + if (dq.size() != ref.size()) + { + __builtin_trap(); + } + + if (!std::ranges::equal(dq, ref)) + { + __builtin_trap(); + } + } + + return 0; +} diff --git a/include/fast_io_dsal/impl/deque.h b/include/fast_io_dsal/impl/deque.h index e05ed3f5..d3d4761b 100644 --- a/include/fast_io_dsal/impl/deque.h +++ b/include/fast_io_dsal/impl/deque.h @@ -2299,7 +2299,7 @@ class deque FAST_IO_TRIVIALLY_RELOCATABLE_IF_ELIGIBLE inline constexpr iterator insert_range(const_iterator pos, R &&rg) noexcept(::std::is_nothrow_constructible_v>) { return this->insert_range_impl( - ::fast_io::containers::details::deque_iter_difference_unsigned_common(pos, this->cbegin()), rg, this->size()) + ::fast_io::containers::details::deque_iter_difference_unsigned_common(pos.itercontent, this->controller.front_block), rg, this->size()) .it; } From df7c6ab7d2a971209b3643d6db2c5c82f38e0e56 Mon Sep 17 00:00:00 2001 From: trcrsired Date: Fri, 23 Jan 2026 03:54:18 +0800 Subject: [PATCH 06/42] [skip ci] deque iterator +, -, +=, -=, [] etc should take a fast path First, it avoids the issue with end()+0 on an empty() deque which is currently would dereference UB pointer. Second, it should also help reduce cache misses since the + - etc would move inside a block itself. We will do it later on. --- include/fast_io_dsal/impl/deque.h | 40 ++++++++++++++++++++++++------- 1 file changed, 32 insertions(+), 8 deletions(-) diff --git a/include/fast_io_dsal/impl/deque.h b/include/fast_io_dsal/impl/deque.h index d3d4761b..cba468ad 100644 --- a/include/fast_io_dsal/impl/deque.h +++ b/include/fast_io_dsal/impl/deque.h @@ -102,6 +102,11 @@ inline constexpr void deque_add_assign_signed_impl(::fast_io::containers::detail else { diff += unsignedpos; + if (diff < blocksize) + { + itercontent.curr_ptr = curr_ptr + unsignedpos; + return; + } curr_ptr = (begin_ptr = *(controllerptr += diff / blocksize)) + diff % blocksize; } itercontent.begin_ptr = begin_ptr; @@ -115,8 +120,15 @@ inline constexpr void deque_add_assign_unsigned_impl(::fast_io::containers::deta using size_type = ::std::size_t; constexpr size_type blocksize{::fast_io::containers::details::deque_block_size}; - size_type diff{static_cast(itercontent.curr_ptr - itercontent.begin_ptr) + unsignedpos}; - auto begin_ptr{*(itercontent.controller_ptr += diff / blocksize)}; + auto begin_ptr{itercontent.begin_ptr}; + auto curr_ptr{itercontent.curr_ptr}; + size_type diff{static_cast(curr_ptr - begin_ptr) + unsignedpos}; + if (diff < blocksize) + { + itercontent.curr_ptr = curr_ptr + unsignedpos; + return; + } + begin_ptr = *(itercontent.controller_ptr += diff / blocksize); itercontent.begin_ptr = begin_ptr; itercontent.curr_ptr = begin_ptr + diff % blocksize; } @@ -141,6 +153,11 @@ inline constexpr void deque_sub_assign_signed_impl(::fast_io::containers::detail } else { + if (unsignedpos <= diff) + { + itercontent.curr_ptr = curr_ptr - unsignedpos; + return; + } diff = blocksizem1 + unsignedpos - diff; curr_ptr = (begin_ptr = *(controllerptr -= diff / blocksize)) + (blocksizem1 - diff % blocksize); } @@ -155,11 +172,18 @@ inline constexpr void deque_sub_assign_unsigned_impl(::fast_io::containers::deta using size_type = ::std::size_t; constexpr size_type blocksize{::fast_io::containers::details::deque_block_size}; constexpr size_type blocksizem1{blocksize - 1u}; - size_type diff{blocksizem1 + unsignedpos - - static_cast(itercontent.curr_ptr - itercontent.begin_ptr)}; - auto begin_ptr{*(itercontent.controller_ptr -= diff / blocksize)}; - itercontent.begin_ptr = begin_ptr; - itercontent.curr_ptr = begin_ptr + (blocksizem1 - diff % blocksize); + auto begin_ptr{itercontent.begin_ptr}; + auto curr_ptr{itercontent.curr_ptr}; + size_type offset{static_cast(curr_ptr - begin_ptr)}; + if (unsignedpos <= offset) + { + itercontent.curr_ptr = curr_ptr - unsignedpos; + return; + } + size_type diff{blocksizem1 + unsignedpos - offset}; + auto new_begin_ptr{*(itercontent.controller_ptr -= diff / blocksize)}; + itercontent.begin_ptr = new_begin_ptr; + itercontent.curr_ptr = new_begin_ptr + (blocksizem1 - diff % blocksize); } template @@ -2264,9 +2288,9 @@ class deque FAST_IO_TRIVIALLY_RELOCATABLE_IF_ELIGIBLE } else { - size_type const quarterold_size{old_size >> 2u}; size_type retpos; iterator retit, rotfirst, rotmid, rotlast; + size_type const quarterold_size{old_size >> 2u}; if (pos < quarterold_size) { this->prepend_range(rg); From 62e10ff536462e00765ca2c2388805526b0975d8 Mon Sep 17 00:00:00 2001 From: trcrsired Date: Fri, 23 Jan 2026 05:56:14 +0800 Subject: [PATCH 07/42] [skip ci] reimplement deque's iterator random access operations with fast path. also to test the performance of [] --- include/fast_io_dsal/impl/deque.h | 153 +++++++++++++++--------------- 1 file changed, 79 insertions(+), 74 deletions(-) diff --git a/include/fast_io_dsal/impl/deque.h b/include/fast_io_dsal/impl/deque.h index cba468ad..58db9896 100644 --- a/include/fast_io_dsal/impl/deque.h +++ b/include/fast_io_dsal/impl/deque.h @@ -82,36 +82,48 @@ struct }; template -inline constexpr void deque_add_assign_signed_impl(::fast_io::containers::details::deque_control_block &itercontent, ::std::ptrdiff_t pos) noexcept +inline constexpr void deque_add_assign_signed_impl( + ::fast_io::containers::details::deque_control_block &itercontent, + ::std::ptrdiff_t pos) noexcept { - using size_type = ::std::size_t; - constexpr size_type blocksize{::fast_io::containers::details::deque_block_size}; - constexpr size_type blocksizem1{blocksize - 1u}; - size_type unsignedpos{static_cast(pos)}; - auto begin_ptr{itercontent.begin_ptr}; + constexpr ::std::size_t blocksize{::fast_io::containers::details::deque_block_size}; + constexpr ::std::ptrdiff_t signedblocksize{static_cast<::std::ptrdiff_t>(blocksize)}; + auto curr_ptr{itercontent.curr_ptr}; - auto controllerptr{itercontent.controller_ptr}; - size_type diff{static_cast(curr_ptr - begin_ptr)}; - if (pos < 0) + // Signed offset inside current block + ::std::ptrdiff_t offset{pos + (curr_ptr - itercontent.begin_ptr)}; + + // Fast path: stays inside the same block + if (static_cast<::std::size_t>(offset) < blocksize) { - constexpr size_type zero{}; - size_type abspos{static_cast(zero - unsignedpos)}; - diff = (blocksizem1 + abspos) - diff; - curr_ptr = (begin_ptr = *(controllerptr -= diff / blocksize)) + (blocksizem1 - diff % blocksize); + itercontent.curr_ptr = curr_ptr + pos; } else { - diff += unsignedpos; - if (diff < blocksize) + // Compute block jump with correct signed semantics + ::std::ptrdiff_t node_offset; + if (offset < 0) { - itercontent.curr_ptr = curr_ptr + unsignedpos; - return; + node_offset = (offset + 1) / signedblocksize - 1; } - curr_ptr = (begin_ptr = *(controllerptr += diff / blocksize)) + diff % blocksize; + else + { + node_offset = static_cast<::std::ptrdiff_t>(static_cast<::std::size_t>(offset) / blocksize); + } + + // Move to the correct block + auto begin_ptr{*(itercontent.controller_ptr += node_offset)}; + itercontent.begin_ptr = begin_ptr; + + // Normalize pointer inside the block + itercontent.curr_ptr = begin_ptr + (offset - node_offset * signedblocksize); } - itercontent.begin_ptr = begin_ptr; - itercontent.curr_ptr = curr_ptr; - itercontent.controller_ptr = controllerptr; +} + +template +inline constexpr void deque_sub_assign_signed_impl(::fast_io::containers::details::deque_control_block &it, ::std::ptrdiff_t pos) noexcept +{ + ::fast_io::containers::details::deque_add_assign_signed_impl(it, -pos); } template @@ -126,44 +138,13 @@ inline constexpr void deque_add_assign_unsigned_impl(::fast_io::containers::deta if (diff < blocksize) { itercontent.curr_ptr = curr_ptr + unsignedpos; - return; - } - begin_ptr = *(itercontent.controller_ptr += diff / blocksize); - itercontent.begin_ptr = begin_ptr; - itercontent.curr_ptr = begin_ptr + diff % blocksize; -} - -template -inline constexpr void deque_sub_assign_signed_impl(::fast_io::containers::details::deque_control_block &itercontent, ::std::ptrdiff_t pos) noexcept -{ - using size_type = ::std::size_t; - constexpr size_type blocksize{::fast_io::containers::details::deque_block_size}; - constexpr size_type blocksizem1{blocksize - 1u}; - size_type unsignedpos{static_cast(pos)}; - auto begin_ptr{itercontent.begin_ptr}; - auto curr_ptr{itercontent.curr_ptr}; - auto controllerptr{itercontent.controller_ptr}; - size_type diff{static_cast(curr_ptr - begin_ptr)}; - if (pos < 0) - { - constexpr size_type zero{}; - size_type abspos{static_cast(zero - unsignedpos)}; - diff += abspos; - curr_ptr = (begin_ptr = *(controllerptr += diff / blocksize)) + diff % blocksize; } else { - if (unsignedpos <= diff) - { - itercontent.curr_ptr = curr_ptr - unsignedpos; - return; - } - diff = blocksizem1 + unsignedpos - diff; - curr_ptr = (begin_ptr = *(controllerptr -= diff / blocksize)) + (blocksizem1 - diff % blocksize); + begin_ptr = *(itercontent.controller_ptr += diff / blocksize); + itercontent.begin_ptr = begin_ptr; + itercontent.curr_ptr = begin_ptr + diff % blocksize; } - itercontent.begin_ptr = begin_ptr; - itercontent.curr_ptr = curr_ptr; - itercontent.controller_ptr = controllerptr; } template @@ -178,12 +159,14 @@ inline constexpr void deque_sub_assign_unsigned_impl(::fast_io::containers::deta if (unsignedpos <= offset) { itercontent.curr_ptr = curr_ptr - unsignedpos; - return; } - size_type diff{blocksizem1 + unsignedpos - offset}; - auto new_begin_ptr{*(itercontent.controller_ptr -= diff / blocksize)}; - itercontent.begin_ptr = new_begin_ptr; - itercontent.curr_ptr = new_begin_ptr + (blocksizem1 - diff % blocksize); + else + { + size_type diff{blocksizem1 + unsignedpos - offset}; + begin_ptr = (*(itercontent.controller_ptr -= diff / blocksize)); + itercontent.begin_ptr = begin_ptr; + itercontent.curr_ptr = begin_ptr + (blocksizem1 - diff % blocksize); + } } template @@ -191,23 +174,36 @@ inline constexpr T &deque_index_signed(::fast_io::containers::details::deque_con { using size_type = ::std::size_t; constexpr size_type blocksize{::fast_io::containers::details::deque_block_size}; - constexpr size_type blocksizem1{blocksize - 1u}; - size_type unsignedpos{static_cast(pos)}; - auto begin_ptr{itercontent.begin_ptr}; + constexpr ::std::ptrdiff_t signedblocksize{static_cast<::std::ptrdiff_t>(blocksize)}; + auto curr_ptr{itercontent.curr_ptr}; - auto controllerptr{itercontent.controller_ptr}; - size_type diff{static_cast(curr_ptr - begin_ptr)}; - if (pos < 0) + // Signed offset inside current block + ::std::ptrdiff_t offset{pos + (curr_ptr - itercontent.begin_ptr)}; + + // Fast path: stays inside the same block + if (static_cast<::std::size_t>(offset) < blocksize) { - constexpr size_type zero{}; - size_type abspos{static_cast(zero - unsignedpos)}; - diff = blocksizem1 + abspos - diff; - return (*(controllerptr - diff / blocksize))[blocksizem1 - diff % blocksize]; + return curr_ptr[pos]; } else { - diff += unsignedpos; - return controllerptr[diff / blocksize][diff % blocksize]; + // Compute block jump with correct signed semantics + ::std::ptrdiff_t node_offset; + if (offset < 0) + { + node_offset = (offset + 1) / signedblocksize - 1; + } + else + { + node_offset = static_cast<::std::ptrdiff_t>(static_cast<::std::size_t>(offset) / blocksize); + } + + // Move to the correct block + auto begin_ptr{*(itercontent.controller_ptr += node_offset)}; + itercontent.begin_ptr = begin_ptr; + + // Normalize pointer inside the block + itercontent.curr_ptr = begin_ptr + (offset - node_offset * signedblocksize); } } @@ -216,8 +212,17 @@ inline constexpr T &deque_index_unsigned(::fast_io::containers::details::deque_c { using size_type = ::std::size_t; constexpr size_type blocksize{::fast_io::containers::details::deque_block_size}; - size_type const diff{static_cast(itercontent.curr_ptr - itercontent.begin_ptr) + unsignedpos}; - return itercontent.controller_ptr[diff / blocksize][diff % blocksize]; + auto curr_ptr{itercontent.curr_ptr}; + size_type const diff{static_cast(curr_ptr - itercontent.begin_ptr) + unsignedpos}; + if (diff < blocksize) + { + // Fast path: stays inside the same block + return curr_ptr[unsignedpos]; + } + else + { + return itercontent.controller_ptr[diff / blocksize][diff % blocksize]; + } } template From 9d2c073f7e25f46cb1712375cf9f6fa366be2e16 Mon Sep 17 00:00:00 2001 From: trcrsired Date: Fri, 23 Jan 2026 06:30:49 +0800 Subject: [PATCH 08/42] deque add benchmarks for indexing --- .../deque/0005.indexing/fast_io.cc | 26 ++++++++++++++++++ .../0005.indexing/fast_io_index_unchecked.cc | 26 ++++++++++++++++++ .../deque/0005.indexing/fast_io_vec.cc | 26 ++++++++++++++++++ .../0005.indexing/fast_io_vec_reserve.cc | 27 +++++++++++++++++++ .../0005.indexing/fast_io_vec_unchecked.cc | 27 +++++++++++++++++++ .../deque/0005.indexing/std.cc | 26 ++++++++++++++++++ include/fast_io_dsal/impl/deque.h | 19 ++++++++++--- 7 files changed, 173 insertions(+), 4 deletions(-) create mode 100644 benchmark/0011.containers/deque/0005.indexing/fast_io.cc create mode 100644 benchmark/0011.containers/deque/0005.indexing/fast_io_index_unchecked.cc create mode 100644 benchmark/0011.containers/deque/0005.indexing/fast_io_vec.cc create mode 100644 benchmark/0011.containers/deque/0005.indexing/fast_io_vec_reserve.cc create mode 100644 benchmark/0011.containers/deque/0005.indexing/fast_io_vec_unchecked.cc create mode 100644 benchmark/0011.containers/deque/0005.indexing/std.cc diff --git a/benchmark/0011.containers/deque/0005.indexing/fast_io.cc b/benchmark/0011.containers/deque/0005.indexing/fast_io.cc new file mode 100644 index 00000000..f640003c --- /dev/null +++ b/benchmark/0011.containers/deque/0005.indexing/fast_io.cc @@ -0,0 +1,26 @@ +#include +#include +#include + +int main() +{ + ::fast_io::timer tm(u8"fast_io::deque"); + ::fast_io::deque deq; + constexpr std::size_t n{100000000}; + { + ::fast_io::timer tm1(u8"push_back"); + for (std::size_t i{}; i != n; ++i) + { + deq.push_back(i); + } + } + ::std::size_t sum{}; + { + ::fast_io::timer tm1(u8"indexing loop"); + for (::std::size_t i{}, n{deq.size()}; i != n; ++i) + { + sum += deq[i]; + } + } + ::fast_io::io::perrln("sum=", sum); +} diff --git a/benchmark/0011.containers/deque/0005.indexing/fast_io_index_unchecked.cc b/benchmark/0011.containers/deque/0005.indexing/fast_io_index_unchecked.cc new file mode 100644 index 00000000..4ce5836d --- /dev/null +++ b/benchmark/0011.containers/deque/0005.indexing/fast_io_index_unchecked.cc @@ -0,0 +1,26 @@ +#include +#include +#include + +int main() +{ + ::fast_io::timer tm(u8"fast_io::deque unchecked"); + ::fast_io::deque deq; + constexpr std::size_t n{100000000}; + { + ::fast_io::timer tm1(u8"push_back"); + for (std::size_t i{}; i != n; ++i) + { + deq.push_back(i); + } + } + ::std::size_t sum{}; + { + ::fast_io::timer tm1(u8"indexing unchecked loop"); + for (::std::size_t i{}, n{deq.size()}; i != n; ++i) + { + sum += deq.index_unchecked(i); + } + } + ::fast_io::io::perrln("sum=", sum); +} diff --git a/benchmark/0011.containers/deque/0005.indexing/fast_io_vec.cc b/benchmark/0011.containers/deque/0005.indexing/fast_io_vec.cc new file mode 100644 index 00000000..76877832 --- /dev/null +++ b/benchmark/0011.containers/deque/0005.indexing/fast_io_vec.cc @@ -0,0 +1,26 @@ +#include +#include +#include + +int main() +{ + ::fast_io::timer tm(u8"fast_io::vector"); + ::fast_io::vector vec; + constexpr std::size_t n{100000000}; + { + ::fast_io::timer tm1(u8"push_back"); + for (std::size_t i{}; i != n; ++i) + { + vec.push_back(i); + } + } + ::std::size_t sum{}; + { + ::fast_io::timer tm1(u8"indexing loop"); + for (::std::size_t i{}, n{vec.size()}; i != n; ++i) + { + sum += vec[i]; + } + } + ::fast_io::io::perrln("sum=", sum); +} diff --git a/benchmark/0011.containers/deque/0005.indexing/fast_io_vec_reserve.cc b/benchmark/0011.containers/deque/0005.indexing/fast_io_vec_reserve.cc new file mode 100644 index 00000000..8395fe97 --- /dev/null +++ b/benchmark/0011.containers/deque/0005.indexing/fast_io_vec_reserve.cc @@ -0,0 +1,27 @@ +#include +#include +#include + +int main() +{ + ::fast_io::timer tm(u8"fast_io::vector reserve"); + ::fast_io::vector vec; + constexpr std::size_t n{100000000}; + vec.reserve(n); + { + fast_io::timer tm1(u8"push_back"); + for (std::size_t i{}; i != n; ++i) + { + vec.push_back(i); + } + } + ::std::size_t sum{}; + { + fast_io::timer tm1(u8"indexing loop"); + for (::std::size_t i{}, n{vec.size()}; i != n; ++i) + { + sum += vec[i]; + } + } + ::fast_io::io::perrln("sum=", sum); +} diff --git a/benchmark/0011.containers/deque/0005.indexing/fast_io_vec_unchecked.cc b/benchmark/0011.containers/deque/0005.indexing/fast_io_vec_unchecked.cc new file mode 100644 index 00000000..41dcb0da --- /dev/null +++ b/benchmark/0011.containers/deque/0005.indexing/fast_io_vec_unchecked.cc @@ -0,0 +1,27 @@ +#include +#include +#include + +int main() +{ + ::fast_io::timer tm(u8"fast_io::vector unchecked"); + ::fast_io::vector vec; + constexpr std::size_t n{100000000}; + vec.reserve(n); + { + fast_io::timer tm1(u8"push_back_unchecked"); + for (std::size_t i{}; i != n; ++i) + { + vec.push_back_unchecked(i); + } + } + ::std::size_t sum{}; + { + fast_io::timer tm1(u8"indexing unchecked loop"); + for (::std::size_t i{}, n{vec.size()}; i != n; ++i) + { + sum += vec.index_unchecked(i); + } + } + ::fast_io::io::perrln("sum=", sum); +} diff --git a/benchmark/0011.containers/deque/0005.indexing/std.cc b/benchmark/0011.containers/deque/0005.indexing/std.cc new file mode 100644 index 00000000..2dfcf75b --- /dev/null +++ b/benchmark/0011.containers/deque/0005.indexing/std.cc @@ -0,0 +1,26 @@ +#include +#include +#include + +int main() +{ + fast_io::timer tm(u8"std::deque"); + ::std::deque deq; + constexpr std::size_t n{100000000}; + { + fast_io::timer tm1(u8"push_back"); + for (std::size_t i{}; i != n; ++i) + { + deq.push_back(i); + } + } + ::std::size_t sum{}; + { + fast_io::timer tm1(u8"indexing loop"); + for (::std::size_t i{}, n{deq.size()}; i != n; ++i) + { + sum += deq[i]; + } + } + ::fast_io::io::perrln("sum=", sum); +} diff --git a/include/fast_io_dsal/impl/deque.h b/include/fast_io_dsal/impl/deque.h index 58db9896..8973c694 100644 --- a/include/fast_io_dsal/impl/deque.h +++ b/include/fast_io_dsal/impl/deque.h @@ -225,6 +225,17 @@ inline constexpr T &deque_index_unsigned(::fast_io::containers::details::deque_c } } +template +inline constexpr T &deque_index_container_unsigned(::fast_io::containers::details::deque_control_block const &itercontent, ::std::size_t unsignedpos) noexcept +{ + using size_type = ::std::size_t; + constexpr size_type blocksize{::fast_io::containers::details::deque_block_size}; + auto curr_ptr{itercontent.curr_ptr}; + size_type const diff{static_cast(curr_ptr - itercontent.begin_ptr) + unsignedpos}; + // Container should not have fast path because container cannot have locality like iterator[] does + return itercontent.controller_ptr[diff / blocksize][diff % blocksize]; +} + template struct deque_iterator { @@ -2109,7 +2120,7 @@ class deque FAST_IO_TRIVIALLY_RELOCATABLE_IF_ELIGIBLE { ::fast_io::fast_terminate(); } - return ::fast_io::containers::details::deque_index_unsigned(controller.front_block, index); + return ::fast_io::containers::details::deque_index_container_unsigned(controller.front_block, index); } inline constexpr const_reference operator[](size_type index) const noexcept @@ -2118,17 +2129,17 @@ class deque FAST_IO_TRIVIALLY_RELOCATABLE_IF_ELIGIBLE { ::fast_io::fast_terminate(); } - return ::fast_io::containers::details::deque_index_unsigned(controller.front_block, index); + return ::fast_io::containers::details::deque_index_container_unsigned(controller.front_block, index); } inline constexpr reference index_unchecked(size_type index) noexcept { - return ::fast_io::containers::details::deque_index_unsigned(controller.front_block, index); + return ::fast_io::containers::details::deque_index_container_unsigned(controller.front_block, index); } inline constexpr const_reference index_unchecked(size_type index) const noexcept { - return ::fast_io::containers::details::deque_index_unsigned(controller.front_block, index); + return ::fast_io::containers::details::deque_index_container_unsigned(controller.front_block, index); } static inline constexpr size_type max_size() noexcept From c35b71f4772d3bffba077a67c6e39f9af167ef08 Mon Sep 17 00:00:00 2001 From: trcrsired Date: Fri, 23 Jan 2026 07:08:16 +0800 Subject: [PATCH 09/42] deque should not shadow variables --- benchmark/0011.containers/deque/0005.indexing/fast_io.cc | 2 +- .../deque/0005.indexing/fast_io_index_unchecked.cc | 2 +- benchmark/0011.containers/deque/0005.indexing/fast_io_vec.cc | 2 +- .../0011.containers/deque/0005.indexing/fast_io_vec_reserve.cc | 2 +- .../deque/0005.indexing/fast_io_vec_unchecked.cc | 2 +- benchmark/0011.containers/deque/0005.indexing/std.cc | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/benchmark/0011.containers/deque/0005.indexing/fast_io.cc b/benchmark/0011.containers/deque/0005.indexing/fast_io.cc index f640003c..a4ba655d 100644 --- a/benchmark/0011.containers/deque/0005.indexing/fast_io.cc +++ b/benchmark/0011.containers/deque/0005.indexing/fast_io.cc @@ -17,7 +17,7 @@ int main() ::std::size_t sum{}; { ::fast_io::timer tm1(u8"indexing loop"); - for (::std::size_t i{}, n{deq.size()}; i != n; ++i) + for (::std::size_t i{}, sz{deq.size()}; i != sz; ++i) { sum += deq[i]; } diff --git a/benchmark/0011.containers/deque/0005.indexing/fast_io_index_unchecked.cc b/benchmark/0011.containers/deque/0005.indexing/fast_io_index_unchecked.cc index 4ce5836d..1fffc100 100644 --- a/benchmark/0011.containers/deque/0005.indexing/fast_io_index_unchecked.cc +++ b/benchmark/0011.containers/deque/0005.indexing/fast_io_index_unchecked.cc @@ -17,7 +17,7 @@ int main() ::std::size_t sum{}; { ::fast_io::timer tm1(u8"indexing unchecked loop"); - for (::std::size_t i{}, n{deq.size()}; i != n; ++i) + for (::std::size_t i{}, sz{deq.size()}; i != sz; ++i) { sum += deq.index_unchecked(i); } diff --git a/benchmark/0011.containers/deque/0005.indexing/fast_io_vec.cc b/benchmark/0011.containers/deque/0005.indexing/fast_io_vec.cc index 76877832..f63bc208 100644 --- a/benchmark/0011.containers/deque/0005.indexing/fast_io_vec.cc +++ b/benchmark/0011.containers/deque/0005.indexing/fast_io_vec.cc @@ -17,7 +17,7 @@ int main() ::std::size_t sum{}; { ::fast_io::timer tm1(u8"indexing loop"); - for (::std::size_t i{}, n{vec.size()}; i != n; ++i) + for (::std::size_t i{}, sz{vec.size()}; i != sz; ++i) { sum += vec[i]; } diff --git a/benchmark/0011.containers/deque/0005.indexing/fast_io_vec_reserve.cc b/benchmark/0011.containers/deque/0005.indexing/fast_io_vec_reserve.cc index 8395fe97..c756605f 100644 --- a/benchmark/0011.containers/deque/0005.indexing/fast_io_vec_reserve.cc +++ b/benchmark/0011.containers/deque/0005.indexing/fast_io_vec_reserve.cc @@ -18,7 +18,7 @@ int main() ::std::size_t sum{}; { fast_io::timer tm1(u8"indexing loop"); - for (::std::size_t i{}, n{vec.size()}; i != n; ++i) + for (::std::size_t i{}, sz{vec.size()}; i != sz; ++i) { sum += vec[i]; } diff --git a/benchmark/0011.containers/deque/0005.indexing/fast_io_vec_unchecked.cc b/benchmark/0011.containers/deque/0005.indexing/fast_io_vec_unchecked.cc index 41dcb0da..9095eea0 100644 --- a/benchmark/0011.containers/deque/0005.indexing/fast_io_vec_unchecked.cc +++ b/benchmark/0011.containers/deque/0005.indexing/fast_io_vec_unchecked.cc @@ -18,7 +18,7 @@ int main() ::std::size_t sum{}; { fast_io::timer tm1(u8"indexing unchecked loop"); - for (::std::size_t i{}, n{vec.size()}; i != n; ++i) + for (::std::size_t i{}, sz{vec.size()}; i != sz; ++i) { sum += vec.index_unchecked(i); } diff --git a/benchmark/0011.containers/deque/0005.indexing/std.cc b/benchmark/0011.containers/deque/0005.indexing/std.cc index 2dfcf75b..95b7494f 100644 --- a/benchmark/0011.containers/deque/0005.indexing/std.cc +++ b/benchmark/0011.containers/deque/0005.indexing/std.cc @@ -17,7 +17,7 @@ int main() ::std::size_t sum{}; { fast_io::timer tm1(u8"indexing loop"); - for (::std::size_t i{}, n{deq.size()}; i != n; ++i) + for (::std::size_t i{}, sz{deq.size()}; i != sz; ++i) { sum += deq[i]; } From 456049a793820dfff08c5b11ed1e2e99284d85ba Mon Sep 17 00:00:00 2001 From: trcrsired Date: Sat, 24 Jan 2026 03:41:32 +0800 Subject: [PATCH 10/42] add a test to test sorting of deque iterators to ensure deque's iterator works as random access iterator --- include/fast_io_dsal/impl/deque.h | 16 +++++-------- tests/0026.container/0003.deque/iterator.cc | 25 +++++++++++++++++++++ 2 files changed, 30 insertions(+), 11 deletions(-) create mode 100644 tests/0026.container/0003.deque/iterator.cc diff --git a/include/fast_io_dsal/impl/deque.h b/include/fast_io_dsal/impl/deque.h index 8973c694..db3faa00 100644 --- a/include/fast_io_dsal/impl/deque.h +++ b/include/fast_io_dsal/impl/deque.h @@ -197,13 +197,7 @@ inline constexpr T &deque_index_signed(::fast_io::containers::details::deque_con { node_offset = static_cast<::std::ptrdiff_t>(static_cast<::std::size_t>(offset) / blocksize); } - - // Move to the correct block - auto begin_ptr{*(itercontent.controller_ptr += node_offset)}; - itercontent.begin_ptr = begin_ptr; - - // Normalize pointer inside the block - itercontent.curr_ptr = begin_ptr + (offset - node_offset * signedblocksize); + return itercontent.controller_ptr[node_offset][offset - node_offset * signedblocksize]; } } @@ -2286,14 +2280,14 @@ class deque FAST_IO_TRIVIALLY_RELOCATABLE_IF_ELIGIBLE else #endif { -#if 0 - ::fast_io::io::debug_println(::std::source_location::current(),"\tthis->size()=", this->size()," rgsize=",rgsize); +#if 1 + ::fast_io::io::debug_println(::std::source_location::current(), "\tthis->size()=", this->size(), " rgsize=", rgsize); #endif ::fast_io::containers::details::deque_reserve_back_spaces(this->controller, rgsize); auto posit{this->begin() + pos}; -#if 0 - ::fast_io::io::debug_println(::std::source_location::current(),"\tthis->size()=", this->size()," rgsize=",rgsize); +#if 1 + ::fast_io::io::debug_println(::std::source_location::current(), "\tthis->size()=", this->size(), " rgsize=", rgsize); #endif auto thisend{this->end()}; ::fast_io::freestanding::uninitialized_relocate_backward(posit, diff --git a/tests/0026.container/0003.deque/iterator.cc b/tests/0026.container/0003.deque/iterator.cc new file mode 100644 index 00000000..0967a9c8 --- /dev/null +++ b/tests/0026.container/0003.deque/iterator.cc @@ -0,0 +1,25 @@ +#include +#include +#include + +int main() +{ + ::fast_io::deque<::std::size_t> dq{30zu, 40zu, 20zu, 10zu}; + ::fast_io::deque<::std::size_t> dq2{30zu, 40zu, 20zu, 10zu}; + + // auto dq2(dq); + ::std::sort(dq.begin(), dq.end()); + ::std::sort(dq2.rbegin(), dq2.rend()); + ::fast_io::out_buf_type obf(::fast_io::out()); + using namespace ::fast_io::iomnp; + print(obf, "dq:\n"); + for (auto const &e : dq) + { + println(obf, e); + } + print(obf, "\ndq2:\n"); + for (auto const &e : dq2) + { + println(obf, e); + } +} From cf0ef981de617dbe862c1f0134ebbbc42a9ab7d9 Mon Sep 17 00:00:00 2001 From: trcrsired Date: Sat, 24 Jan 2026 04:59:17 +0800 Subject: [PATCH 11/42] deque's clone method contains bug which should be fromcontrollerwq --- include/fast_io_dsal/impl/deque.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/fast_io_dsal/impl/deque.h b/include/fast_io_dsal/impl/deque.h index db3faa00..05d9f4d5 100644 --- a/include/fast_io_dsal/impl/deque.h +++ b/include/fast_io_dsal/impl/deque.h @@ -1066,7 +1066,7 @@ inline constexpr void deque_clone_trivial_impl(dequecontroltype &controller, deq begin_ptrtype lastblockbegin; if (front_controller_ptr == back_controller_ptr) { - lastblockbegin = controller.front_block.curr_ptr; + lastblockbegin = fromcontroller.front_block.curr_ptr; } else { From 610e45b680a08d19cbb5f13ef0c06d195c7d6fd6 Mon Sep 17 00:00:00 2001 From: trcrsired Date: Sat, 24 Jan 2026 05:07:23 +0800 Subject: [PATCH 12/42] deque add a sorting benchmark --- .../deque/0006.sort/fast_io.cc | 35 +++++++++++++++++++ .../deque/0006.sort/fast_io_vec.cc | 35 +++++++++++++++++++ .../0011.containers/deque/0006.sort/std.cc | 35 +++++++++++++++++++ 3 files changed, 105 insertions(+) create mode 100644 benchmark/0011.containers/deque/0006.sort/fast_io.cc create mode 100644 benchmark/0011.containers/deque/0006.sort/fast_io_vec.cc create mode 100644 benchmark/0011.containers/deque/0006.sort/std.cc diff --git a/benchmark/0011.containers/deque/0006.sort/fast_io.cc b/benchmark/0011.containers/deque/0006.sort/fast_io.cc new file mode 100644 index 00000000..6ec51290 --- /dev/null +++ b/benchmark/0011.containers/deque/0006.sort/fast_io.cc @@ -0,0 +1,35 @@ +#include +#include +#include +#include +#include + +int main() +{ + constexpr std::size_t n{1000000}; + ::std::mt19937_64 eng; + ::std::uniform_int_distribution<::std::size_t> dis(0,SIZE_MAX); + + ::fast_io::timer tm(u8"fast_io::deque"); + ::fast_io::deque deq; + { + ::fast_io::timer tm1(u8"push_back"); + for (std::size_t i{}; i != n; ++i) + { + deq.push_back(dis(eng)); + } + } + { + ::fast_io::timer tm1(u8"sort"); + ::std::ranges::sort(deq); + } + ::std::size_t sum{}; + { + ::fast_io::timer tm1(u8"loop"); + for (auto const & e : deq) + { + sum += e; + } + } + ::fast_io::io::perrln("sum=", sum); +} diff --git a/benchmark/0011.containers/deque/0006.sort/fast_io_vec.cc b/benchmark/0011.containers/deque/0006.sort/fast_io_vec.cc new file mode 100644 index 00000000..71ac370e --- /dev/null +++ b/benchmark/0011.containers/deque/0006.sort/fast_io_vec.cc @@ -0,0 +1,35 @@ +#include +#include +#include +#include +#include + +int main() +{ + constexpr std::size_t n{1000000}; + ::std::mt19937_64 eng; + ::std::uniform_int_distribution<::std::size_t> dis(0,SIZE_MAX); + + ::fast_io::timer tm(u8"fast_io::vector"); + ::fast_io::vector deq; + { + ::fast_io::timer tm1(u8"push_back"); + for (std::size_t i{}; i != n; ++i) + { + deq.push_back(dis(eng)); + } + } + { + ::fast_io::timer tm1(u8"sort"); + ::std::ranges::sort(deq); + } + ::std::size_t sum{}; + { + ::fast_io::timer tm1(u8"loop"); + for (auto const & e : deq) + { + sum += e; + } + } + ::fast_io::io::perrln("sum=", sum); +} diff --git a/benchmark/0011.containers/deque/0006.sort/std.cc b/benchmark/0011.containers/deque/0006.sort/std.cc new file mode 100644 index 00000000..565ccfd6 --- /dev/null +++ b/benchmark/0011.containers/deque/0006.sort/std.cc @@ -0,0 +1,35 @@ +#include +#include +#include +#include +#include + +int main() +{ + constexpr std::size_t n{1000000}; + ::std::mt19937_64 eng; + ::std::uniform_int_distribution<::std::size_t> dis(0,SIZE_MAX); + + ::fast_io::timer tm(u8"std::deque"); + ::std::deque deq; + { + ::fast_io::timer tm1(u8"push_back"); + for (std::size_t i{}; i != n; ++i) + { + deq.push_back(dis(eng)); + } + } + { + ::fast_io::timer tm1(u8"sort"); + ::std::ranges::sort(deq); + } + ::std::size_t sum{}; + { + ::fast_io::timer tm1(u8"loop"); + for (auto const & e : deq) + { + sum += e; + } + } + ::fast_io::io::perrln("sum=", sum); +} From 3594322c5be61459466a0160cf80c020ef8755b7 Mon Sep 17 00:00:00 2001 From: trcrsired Date: Sat, 24 Jan 2026 05:11:39 +0800 Subject: [PATCH 13/42] deque iterator test for deque should just use copy. and use clang-format -i for sort --- benchmark/0011.containers/deque/0006.sort/fast_io.cc | 8 ++++---- benchmark/0011.containers/deque/0006.sort/fast_io_vec.cc | 8 ++++---- benchmark/0011.containers/deque/0006.sort/std.cc | 8 ++++---- tests/0026.container/0003.deque/iterator.cc | 4 +--- 4 files changed, 13 insertions(+), 15 deletions(-) diff --git a/benchmark/0011.containers/deque/0006.sort/fast_io.cc b/benchmark/0011.containers/deque/0006.sort/fast_io.cc index 6ec51290..c6503033 100644 --- a/benchmark/0011.containers/deque/0006.sort/fast_io.cc +++ b/benchmark/0011.containers/deque/0006.sort/fast_io.cc @@ -7,8 +7,8 @@ int main() { constexpr std::size_t n{1000000}; - ::std::mt19937_64 eng; - ::std::uniform_int_distribution<::std::size_t> dis(0,SIZE_MAX); + ::std::mt19937_64 eng; + ::std::uniform_int_distribution<::std::size_t> dis(0, SIZE_MAX); ::fast_io::timer tm(u8"fast_io::deque"); ::fast_io::deque deq; @@ -21,12 +21,12 @@ int main() } { ::fast_io::timer tm1(u8"sort"); - ::std::ranges::sort(deq); + ::std::ranges::sort(deq); } ::std::size_t sum{}; { ::fast_io::timer tm1(u8"loop"); - for (auto const & e : deq) + for (auto const &e : deq) { sum += e; } diff --git a/benchmark/0011.containers/deque/0006.sort/fast_io_vec.cc b/benchmark/0011.containers/deque/0006.sort/fast_io_vec.cc index 71ac370e..946ed4c3 100644 --- a/benchmark/0011.containers/deque/0006.sort/fast_io_vec.cc +++ b/benchmark/0011.containers/deque/0006.sort/fast_io_vec.cc @@ -7,8 +7,8 @@ int main() { constexpr std::size_t n{1000000}; - ::std::mt19937_64 eng; - ::std::uniform_int_distribution<::std::size_t> dis(0,SIZE_MAX); + ::std::mt19937_64 eng; + ::std::uniform_int_distribution<::std::size_t> dis(0, SIZE_MAX); ::fast_io::timer tm(u8"fast_io::vector"); ::fast_io::vector deq; @@ -21,12 +21,12 @@ int main() } { ::fast_io::timer tm1(u8"sort"); - ::std::ranges::sort(deq); + ::std::ranges::sort(deq); } ::std::size_t sum{}; { ::fast_io::timer tm1(u8"loop"); - for (auto const & e : deq) + for (auto const &e : deq) { sum += e; } diff --git a/benchmark/0011.containers/deque/0006.sort/std.cc b/benchmark/0011.containers/deque/0006.sort/std.cc index 565ccfd6..ce8262ee 100644 --- a/benchmark/0011.containers/deque/0006.sort/std.cc +++ b/benchmark/0011.containers/deque/0006.sort/std.cc @@ -7,8 +7,8 @@ int main() { constexpr std::size_t n{1000000}; - ::std::mt19937_64 eng; - ::std::uniform_int_distribution<::std::size_t> dis(0,SIZE_MAX); + ::std::mt19937_64 eng; + ::std::uniform_int_distribution<::std::size_t> dis(0, SIZE_MAX); ::fast_io::timer tm(u8"std::deque"); ::std::deque deq; @@ -21,12 +21,12 @@ int main() } { ::fast_io::timer tm1(u8"sort"); - ::std::ranges::sort(deq); + ::std::ranges::sort(deq); } ::std::size_t sum{}; { ::fast_io::timer tm1(u8"loop"); - for (auto const & e : deq) + for (auto const &e : deq) { sum += e; } diff --git a/tests/0026.container/0003.deque/iterator.cc b/tests/0026.container/0003.deque/iterator.cc index 0967a9c8..66832a5a 100644 --- a/tests/0026.container/0003.deque/iterator.cc +++ b/tests/0026.container/0003.deque/iterator.cc @@ -5,9 +5,7 @@ int main() { ::fast_io::deque<::std::size_t> dq{30zu, 40zu, 20zu, 10zu}; - ::fast_io::deque<::std::size_t> dq2{30zu, 40zu, 20zu, 10zu}; - - // auto dq2(dq); + auto dq2(dq); ::std::sort(dq.begin(), dq.end()); ::std::sort(dq2.rbegin(), dq2.rend()); ::fast_io::out_buf_type obf(::fast_io::out()); From 8be93d035c32783d442921d8f358c4d2df2d7db3 Mon Sep 17 00:00:00 2001 From: trcrsired Date: Sat, 24 Jan 2026 19:21:27 +0800 Subject: [PATCH 14/42] deque fix the insertation size part not entire insertation still going on --- include/fast_io_dsal/impl/deque.h | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/include/fast_io_dsal/impl/deque.h b/include/fast_io_dsal/impl/deque.h index 05d9f4d5..9fa125e9 100644 --- a/include/fast_io_dsal/impl/deque.h +++ b/include/fast_io_dsal/impl/deque.h @@ -634,6 +634,7 @@ inline constexpr void deque_allocate_on_empty_common_with_n_impl(dequecontroltyp #endif using block_typed_allocator = ::fast_io::typed_generic_allocator_adapter; auto [allocated_blocks_ptr, allocated_blocks_count] = block_typed_allocator::allocate_at_least(initial_allocated_block_counts_with_sentinel); + // we need a null terminator as sentinel like c style string does --allocated_blocks_count; auto &controller_block{controller.controller_block}; @@ -1377,7 +1378,6 @@ inline constexpr void deque_reserve_back_blocks_impl(dequecontroltype &controlle controller, align, blockbytes, nb); return; } - using replacetype = typename dequecontroltype::replacetype; using begin_ptrtype = replacetype *; @@ -1446,13 +1446,7 @@ inline constexpr void deque_reserve_back_blocks_impl(dequecontroltype &controlle #if 0 ::fast_io::io::debug_println(::std::source_location::current()," \tnb=",nb); #endif - controller.back_block.controller_ptr += nb; - auto begin_ptr = - static_cast(*controller.back_block.controller_ptr); - controller.back_block.begin_ptr = begin_ptr; - controller.back_block.curr_ptr = begin_ptr; - controller.back_end_ptr = begin_ptr + blockbytes; #if 0 ::fast_io::io::debug_println(::std::source_location::current()," \tbegin_ptr=",::fast_io::mnp::pointervw(begin_ptr)); #endif @@ -1493,7 +1487,6 @@ inline constexpr void deque_reserve_back_spaces(dequecontroltype &controller, :: __builtin_addressof(controller)), toallocate, align, block_bytes); } - controller.back_block.curr_ptr = controller.back_block.begin_ptr + back_more_blocks_mod; } #endif @@ -2280,19 +2273,27 @@ class deque FAST_IO_TRIVIALLY_RELOCATABLE_IF_ELIGIBLE else #endif { -#if 1 +#if 0 ::fast_io::io::debug_println(::std::source_location::current(), "\tthis->size()=", this->size(), " rgsize=", rgsize); #endif ::fast_io::containers::details::deque_reserve_back_spaces(this->controller, rgsize); auto posit{this->begin() + pos}; -#if 1 +#if 0 ::fast_io::io::debug_println(::std::source_location::current(), "\tthis->size()=", this->size(), " rgsize=", rgsize); #endif auto thisend{this->end()}; + auto thisendrgsize{thisend + rgsize}; ::fast_io::freestanding::uninitialized_relocate_backward(posit, - thisend - rgsize, thisend); + thisend, thisendrgsize); ::fast_io::freestanding::uninitialized_copy_n(::std::ranges::cbegin(rg), rgsize, posit); + if (thisendrgsize.itercontent.begin_ptr == thisendrgsize.itercontent.curr_ptr) + { + thisendrgsize.itercontent.curr_ptr = + (thisendrgsize.itercontent.begin_ptr = *--thisendrgsize.itercontent.controller_ptr) + block_size; + } + this->controller.back_block = thisendrgsize.itercontent; + this->controller.back_end_ptr = thisendrgsize.itercontent.begin_ptr + block_size; return {pos, posit}; } } From 8fbc2daf6c14af70387206857e1ffcfac6c8c145 Mon Sep 17 00:00:00 2001 From: trcrsired Date: Sat, 24 Jan 2026 19:59:38 +0800 Subject: [PATCH 15/42] deque should not move +n if it is the same block --- include/fast_io_dsal/impl/deque.h | 1 - 1 file changed, 1 deletion(-) diff --git a/include/fast_io_dsal/impl/deque.h b/include/fast_io_dsal/impl/deque.h index 9fa125e9..cc585dc0 100644 --- a/include/fast_io_dsal/impl/deque.h +++ b/include/fast_io_dsal/impl/deque.h @@ -1463,7 +1463,6 @@ inline constexpr void deque_reserve_back_spaces(dequecontroltype &controller, :: ::std::size_t blocksn{static_cast<::std::size_t>(controller.back_end_ptr - back_curr_ptr)}; if (n <= blocksn) { - controller.back_block.curr_ptr = back_curr_ptr + n; return; } ::std::size_t startpos{static_cast<::std::size_t>(back_curr_ptr - controller.back_block.begin_ptr)}; From f4cc41407b41b56a547cece2942a957609912d6c Mon Sep 17 00:00:00 2001 From: trcrsired Date: Tue, 27 Jan 2026 04:31:49 +0800 Subject: [PATCH 16/42] [skip ci] backup deque code for boundary conditions for insert --- include/fast_io_dsal/impl/deque.h | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/include/fast_io_dsal/impl/deque.h b/include/fast_io_dsal/impl/deque.h index cc585dc0..de02b64e 100644 --- a/include/fast_io_dsal/impl/deque.h +++ b/include/fast_io_dsal/impl/deque.h @@ -1390,7 +1390,7 @@ inline constexpr void deque_reserve_back_blocks_impl(dequecontroltype &controlle std::size_t distance_back_to_reserve{ static_cast(controller.controller_block.controller_after_reserved_ptr - controller.back_block.controller_ptr)}; - if (distance_back_to_reserve < nb) + if (distance_back_to_reserve <= nb) { ::fast_io::containers::details::deque_rebalance_or_grow_insertation_impl(controller, nb); } @@ -1414,7 +1414,6 @@ inline constexpr void deque_reserve_back_blocks_impl(dequecontroltype &controlle { to_allocate_blocks -= front_borrowed_blocks_count; } - auto controller_start_reserved_ptr{ controller.controller_block.controller_start_reserved_ptr}; @@ -1425,7 +1424,6 @@ inline constexpr void deque_reserve_back_blocks_impl(dequecontroltype &controlle pos); controller.controller_block.controller_start_reserved_ptr = controller_start_reserved_ptr + front_borrowed_blocks_count; - for (auto e{pos + to_allocate_blocks}; pos != e; ++pos) { ::std::construct_at(pos, static_cast(allocator::allocate_aligned(align, blockbytes))); @@ -1443,13 +1441,6 @@ inline constexpr void deque_reserve_back_blocks_impl(dequecontroltype &controlle controller.front_block.curr_ptr = controller.front_block.begin_ptr = front_begin_ptr; controller.front_end_ptr = front_begin_ptr + blockbytes; } -#if 0 - ::fast_io::io::debug_println(::std::source_location::current()," \tnb=",nb); -#endif - -#if 0 - ::fast_io::io::debug_println(::std::source_location::current()," \tbegin_ptr=",::fast_io::mnp::pointervw(begin_ptr)); -#endif } template From 008ba44b1b41aeb9073e41bd69a3615217c6fd58 Mon Sep 17 00:00:00 2001 From: trcrsired Date: Tue, 27 Jan 2026 07:18:12 +0800 Subject: [PATCH 17/42] [skip ci] have figured out where the bug is --- include/fast_io_dsal/impl/deque.h | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) diff --git a/include/fast_io_dsal/impl/deque.h b/include/fast_io_dsal/impl/deque.h index de02b64e..804a4b91 100644 --- a/include/fast_io_dsal/impl/deque.h +++ b/include/fast_io_dsal/impl/deque.h @@ -1324,9 +1324,6 @@ inline constexpr void deque_rebalance_or_grow_insertation_impl(dequecontroltype } else { -#if 0 - ::fast_io::iomnp::debug_println(::std::source_location::current()); -#endif // balance blocks auto start_reserved_ptr{controller.controller_block.controller_start_reserved_ptr}; auto after_reserved_ptr{controller.controller_block.controller_after_reserved_ptr}; @@ -1336,15 +1333,11 @@ inline constexpr void deque_rebalance_or_grow_insertation_impl(dequecontroltype static_cast<::std::size_t>(reserved_blocks_count >> 1u)}; auto reserved_pivot{start_reserved_ptr + half_reserved_blocks_count}; auto const half_used_blocks_count{ - static_cast<::std::size_t>(new_used_blocks_count >> 1u)}; + static_cast<::std::size_t>(used_blocks_count >> 1u)}; // this place needs to deal with extra block auto used_blocks_pivot{controller.front_block.controller_ptr + half_used_blocks_count}; if (used_blocks_pivot != reserved_pivot) { ::std::ptrdiff_t diff{reserved_pivot - used_blocks_pivot}; -#if 0 - ::fast_io::iomnp::debug_println(::std::source_location::current(), - "\tdiff=",diff); -#endif auto rotate_pivot{diff < 0 ? start_reserved_ptr : after_reserved_ptr}; rotate_pivot -= diff; ::std::rotate(start_reserved_ptr, rotate_pivot, after_reserved_ptr); @@ -1355,9 +1348,6 @@ inline constexpr void deque_rebalance_or_grow_insertation_impl(dequecontroltype auto slots_pivot{controller.controller_block.controller_start_ptr + half_slots_count}; if (slots_pivot != reserved_pivot) { -#if 0 - ::fast_io::iomnp::debug_println(::std::source_location::current()); -#endif ::std::ptrdiff_t diff{slots_pivot - reserved_pivot}; ::fast_io::freestanding::overlapped_copy(start_reserved_ptr, after_reserved_ptr, start_reserved_ptr + diff); From e3cc7f6921f0cb68db5e52e6a4b5a89ca2d460b2 Mon Sep 17 00:00:00 2001 From: trcrsired Date: Tue, 27 Jan 2026 08:03:03 +0800 Subject: [PATCH 18/42] [skip ci] deque insert balancing with extra blocks --- include/fast_io_dsal/impl/deque.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/fast_io_dsal/impl/deque.h b/include/fast_io_dsal/impl/deque.h index 804a4b91..12caa205 100644 --- a/include/fast_io_dsal/impl/deque.h +++ b/include/fast_io_dsal/impl/deque.h @@ -1344,8 +1344,8 @@ inline constexpr void deque_rebalance_or_grow_insertation_impl(dequecontroltype controller.front_block.controller_ptr += diff; controller.back_block.controller_ptr += diff; } - - auto slots_pivot{controller.controller_block.controller_start_ptr + half_slots_count}; + auto const half_slotsextra_count{static_cast<::std::size_t>((total_slots_count + extrablocks) >> 1u)}; + auto slots_pivot{controller.controller_block.controller_start_ptr + half_slotsextra_count}; if (slots_pivot != reserved_pivot) { ::std::ptrdiff_t diff{slots_pivot - reserved_pivot}; From dca8e83b25ce192ef03b95f4b293cb067e71d16c Mon Sep 17 00:00:00 2001 From: trcrsired Date: Tue, 27 Jan 2026 08:08:46 +0800 Subject: [PATCH 19/42] [skip ci] trying to merge deque_reserve_back_blocks_impl into deque_grow_back_common so that push_back/front and insert can share code --- include/fast_io_dsal/impl/deque.h | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/include/fast_io_dsal/impl/deque.h b/include/fast_io_dsal/impl/deque.h index 12caa205..e39dfc99 100644 --- a/include/fast_io_dsal/impl/deque.h +++ b/include/fast_io_dsal/impl/deque.h @@ -885,13 +885,6 @@ inline constexpr void deque_grow_front_common(dequecontroltype &controller) noex ::fast_io::containers::details::deque_grow_front_common_impl(controller, align, blockbytes); } -template -inline constexpr void deque_grow_back_common(dequecontroltype &controller) noexcept -{ - constexpr ::std::size_t blockbytes{sz * block_size}; - ::fast_io::containers::details::deque_grow_back_common_impl(controller, align, blockbytes); -} - template inline constexpr void deque_clear_common_impl(dequecontroltype &controller, ::std::size_t blockbytes) { @@ -1433,6 +1426,20 @@ inline constexpr void deque_reserve_back_blocks_impl(dequecontroltype &controlle } } +template +inline constexpr void deque_grow_back_common(dequecontroltype &controller) noexcept +{ + constexpr ::std::size_t blockbytes{sz * block_size}; + if constexpr (false) + { + ::fast_io::containers::details::deque_reserve_back_blocks_impl(controller, 1zu, align, blockbytes); + } + else + { + ::fast_io::containers::details::deque_grow_back_common_impl(controller, align, blockbytes); + } +} + template inline constexpr void deque_reserve_back_spaces(dequecontroltype &controller, ::std::size_t n) { From 2ee58aadcfb8665e00d69a49b8d9eb4103d14ac5 Mon Sep 17 00:00:00 2001 From: trcrsired Date: Tue, 27 Jan 2026 08:26:29 +0800 Subject: [PATCH 20/42] [deque] try to merge insert code with push and then run code --- include/fast_io_dsal/impl/deque.h | 41 ++++++++++++++++++++++++++----- 1 file changed, 35 insertions(+), 6 deletions(-) diff --git a/include/fast_io_dsal/impl/deque.h b/include/fast_io_dsal/impl/deque.h index e39dfc99..a2d53f89 100644 --- a/include/fast_io_dsal/impl/deque.h +++ b/include/fast_io_dsal/impl/deque.h @@ -668,8 +668,9 @@ inline constexpr void deque_allocate_on_empty_common_impl(dequecontroltype &cont ::fast_io::containers::details::deque_allocate_on_empty_common_with_n_impl(controller, align, bytes, initial_allocated_block_counts); } +// To remove template -inline constexpr void deque_grow_back_common_impl( +inline constexpr void deque_grow_back_common_old_impl( dequecontroltype &controller, std::size_t align, std::size_t bytes) noexcept @@ -1353,13 +1354,13 @@ inline constexpr void deque_rebalance_or_grow_insertation_impl(dequecontroltype } template -inline constexpr void deque_reserve_back_blocks_impl(dequecontroltype &controller, ::std::size_t nb, ::std::size_t align, ::std::size_t blockbytes) noexcept +inline constexpr bool deque_reserve_back_blocks_impl(dequecontroltype &controller, ::std::size_t nb, ::std::size_t align, ::std::size_t blockbytes) noexcept { if (controller.controller_block.controller_start_ptr == nullptr) { ::fast_io::containers::details::deque_allocate_on_empty_common_with_n_impl( controller, align, blockbytes, nb); - return; + return false; } using replacetype = typename dequecontroltype::replacetype; using begin_ptrtype = replacetype *; @@ -1424,19 +1425,47 @@ inline constexpr void deque_reserve_back_blocks_impl(dequecontroltype &controlle controller.front_block.curr_ptr = controller.front_block.begin_ptr = front_begin_ptr; controller.front_end_ptr = front_begin_ptr + blockbytes; } + + return true; +} + +template +inline constexpr void deque_grow_back_common_impl( + dequecontroltype &controller, + std::size_t align, + std::size_t bytes) noexcept +{ + if (!::fast_io::containers::details::deque_reserve_back_blocks_impl(controller, 1zu, align, bytes)) + { + return; + } + /** + * At this point, we have guaranteed controller capacity. + * Advance back_block.controller_ptr to the new block slot. + */ + ++controller.back_block.controller_ptr; + + /** + * Load the block pointer and initialize begin/curr/end pointers. + */ + auto begin_ptr{*controller.back_block.controller_ptr}; + + controller.back_block.begin_ptr = begin_ptr; + controller.back_block.curr_ptr = begin_ptr; + controller.back_end_ptr = begin_ptr + bytes; } template inline constexpr void deque_grow_back_common(dequecontroltype &controller) noexcept { constexpr ::std::size_t blockbytes{sz * block_size}; - if constexpr (false) + if constexpr (true) { - ::fast_io::containers::details::deque_reserve_back_blocks_impl(controller, 1zu, align, blockbytes); + ::fast_io::containers::details::deque_grow_back_common_impl(controller, align, blockbytes); } else { - ::fast_io::containers::details::deque_grow_back_common_impl(controller, align, blockbytes); + ::fast_io::containers::details::deque_grow_back_common_old_impl(controller, align, blockbytes); } } From a059ac33895072da655e03e4e6637e6e1446f92c Mon Sep 17 00:00:00 2001 From: trcrsired Date: Tue, 27 Jan 2026 08:34:11 +0800 Subject: [PATCH 21/42] [skip ci] the implementation is still buggy, let's use the old one first --- include/fast_io_dsal/impl/deque.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/fast_io_dsal/impl/deque.h b/include/fast_io_dsal/impl/deque.h index a2d53f89..d19d252f 100644 --- a/include/fast_io_dsal/impl/deque.h +++ b/include/fast_io_dsal/impl/deque.h @@ -1459,7 +1459,7 @@ template (controller, align, blockbytes); } From 3e8a7f1a286076d87bc5ce70690fc52c83a717ea Mon Sep 17 00:00:00 2001 From: trcrsired Date: Wed, 28 Jan 2026 04:59:02 +0800 Subject: [PATCH 22/42] [deque] deque push_back try to reuse the code from insertation --- include/fast_io_dsal/impl/deque.h | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/include/fast_io_dsal/impl/deque.h b/include/fast_io_dsal/impl/deque.h index d19d252f..514bc8e2 100644 --- a/include/fast_io_dsal/impl/deque.h +++ b/include/fast_io_dsal/impl/deque.h @@ -1365,21 +1365,21 @@ inline constexpr bool deque_reserve_back_blocks_impl(dequecontroltype &controlle using replacetype = typename dequecontroltype::replacetype; using begin_ptrtype = replacetype *; - std::size_t diff_to_after_ptr = - static_cast( + ::std::size_t diff_to_after_ptr = + static_cast<::std::size_t>( controller.controller_block.controller_after_reserved_ptr - controller.back_block.controller_ptr); if (diff_to_after_ptr <= nb) { - std::size_t distance_back_to_reserve{ - static_cast(controller.controller_block.controller_after_reserved_ptr - - controller.back_block.controller_ptr)}; - if (distance_back_to_reserve <= nb) + ::std::size_t distance_back_to_after{ + static_cast<::std::size_t>(controller.controller_block.controller_after_ptr - + controller.back_block.controller_ptr)}; + if (distance_back_to_after <= nb) { ::fast_io::containers::details::deque_rebalance_or_grow_insertation_impl(controller, nb); } - std::size_t diff_to_after_ptr2 = - static_cast( + ::std::size_t diff_to_after_ptr2 = + static_cast<::std::size_t>( controller.controller_block.controller_after_reserved_ptr - controller.back_block.controller_ptr); if (diff_to_after_ptr2 <= nb) @@ -1459,7 +1459,7 @@ template (controller, align, blockbytes); } From 0c61d4f3d2da5a625916f1d8eccd1df2f17e8308 Mon Sep 17 00:00:00 2001 From: trcrsired Date: Thu, 29 Jan 2026 06:46:21 +0800 Subject: [PATCH 23/42] [skip ci] implement push_front with nb function to allow insert at begin --- include/fast_io_dsal/impl/deque.h | 149 ++++++++++++++++++++++-------- 1 file changed, 110 insertions(+), 39 deletions(-) diff --git a/include/fast_io_dsal/impl/deque.h b/include/fast_io_dsal/impl/deque.h index 514bc8e2..0d4e911a 100644 --- a/include/fast_io_dsal/impl/deque.h +++ b/include/fast_io_dsal/impl/deque.h @@ -796,16 +796,11 @@ inline constexpr void deque_grow_back_common_old_impl( } template -inline constexpr void deque_grow_front_common_impl( +inline constexpr void deque_grow_front_common_old_impl( dequecontroltype &controller, std::size_t align, std::size_t bytes) noexcept { - /** - * If the deque is empty, allocate the initial controller array - * and a single data block. This sets up the initial front/back - * block pointers and the sentinel. - */ if (controller.controller_block.controller_start_ptr == nullptr) { ::fast_io::containers::details:: @@ -820,24 +815,15 @@ inline constexpr void deque_grow_front_common_impl( if (controller.front_block.controller_ptr == controller.controller_block.controller_start_reserved_ptr) { -#if 0 - ::fast_io::iomnp::debug_println(::std::source_location::current()); -#endif if (controller.controller_block.controller_start_reserved_ptr == controller.controller_block.controller_start_ptr) { -#if 0 - ::fast_io::iomnp::debug_println(::std::source_location::current()); -#endif ::fast_io::containers::details:: deque_rebalance_or_grow_2x_after_blocks_impl(controller); } if (controller.front_block.controller_ptr == controller.controller_block.controller_start_reserved_ptr) { -#if 0 - ::fast_io::iomnp::debug_println(::std::source_location::current()); -#endif begin_ptrtype new_block; auto after_reserved_ptr = controller.controller_block.controller_after_reserved_ptr; @@ -868,24 +854,10 @@ inline constexpr void deque_grow_front_common_impl( auto begin_ptr = static_cast(*controller.front_block.controller_ptr); -#if 0 - ::fast_io::iomnp::debug_println(::std::source_location::current(), - "\n\tcontroller_ptr:", ::fast_io::iomnp::pointervw(controller.front_block.controller_ptr), - "\n\tbegin_ptr:", ::fast_io::iomnp::pointervw(begin_ptr), - "\n\tstart_reserved_ptr:", ::fast_io::iomnp::pointervw(controller.controller_block.controller_start_reserved_ptr), - "\n\tstart_ptr:", ::fast_io::iomnp::pointervw(controller.controller_block.controller_start_ptr)); -#endif controller.front_block.begin_ptr = begin_ptr; controller.front_end_ptr = (controller.front_block.curr_ptr = (begin_ptr + bytes)); } -template -inline constexpr void deque_grow_front_common(dequecontroltype &controller) noexcept -{ - constexpr ::std::size_t blockbytes{sz * block_size}; - ::fast_io::containers::details::deque_grow_front_common_impl(controller, align, blockbytes); -} - template inline constexpr void deque_clear_common_impl(dequecontroltype &controller, ::std::size_t blockbytes) { @@ -1439,17 +1411,8 @@ inline constexpr void deque_grow_back_common_impl( { return; } - /** - * At this point, we have guaranteed controller capacity. - * Advance back_block.controller_ptr to the new block slot. - */ ++controller.back_block.controller_ptr; - - /** - * Load the block pointer and initialize begin/curr/end pointers. - */ auto begin_ptr{*controller.back_block.controller_ptr}; - controller.back_block.begin_ptr = begin_ptr; controller.back_block.curr_ptr = begin_ptr; controller.back_end_ptr = begin_ptr + bytes; @@ -1459,7 +1422,7 @@ template (controller, align, blockbytes); } @@ -1504,6 +1467,114 @@ inline constexpr void deque_reserve_back_spaces(dequecontroltype &controller, :: toallocate, align, block_bytes); } } + + +template +inline constexpr bool deque_reserve_front_blocks_impl(dequecontroltype &controller, ::std::size_t nb, ::std::size_t align, ::std::size_t blockbytes) noexcept +{ + if (controller.controller_block.controller_start_ptr == nullptr) + { + ::fast_io::containers::details::deque_allocate_on_empty_common_with_n_impl( + controller, align, blockbytes, nb); + return false; + } + using replacetype = typename dequecontroltype::replacetype; + using begin_ptrtype = replacetype *; + + ::std::size_t diff_to_start_ptr = + static_cast<::std::size_t>( + controller.front_block.controller_ptr - + controller.controller_block.controller_start_reserved_ptr); + if (diff_to_start_ptr < nb) + { + ::std::size_t distance_front_to_start{ + static_cast<::std::size_t>(controller.front_block.controller_ptr - + controller.controller_block.controller_start_ptr)}; + if (distance_front_to_start < nb) + { + ::fast_io::containers::details::deque_rebalance_or_grow_insertation_impl(controller, nb); + } + ::std::size_t diff_to_start_ptr2 = + static_cast<::std::size_t>( + controller.front_block.controller_ptr - + controller.controller_block.controller_start_reserved_ptr); + if (diff_to_start_ptr2 < nb) + { + ::std::size_t back_reserved_blocks{ + static_cast<::std::size_t>(controller.controller_block.controller_after_reserved_ptr - + controller.back_block.controller_ptr - 1)}; + + ::std::size_t back_borrowed_blocks_count{back_reserved_blocks}; + ::std::size_t to_allocate_blocks{nb}; + if (nb < back_reserved_blocks) + { + back_borrowed_blocks_count = nb; + to_allocate_blocks = 0u; + } + else + { + to_allocate_blocks -= back_borrowed_blocks_count; + } + + auto controller_after_reserved_ptr{ + controller.controller_block.controller_after_reserved_ptr}; + + auto controller_start_reserved_ptr{ + controller.controller_block.controller_start_reserved_ptr}; + + auto new_controller_start_reserved_ptr{ + controller_start_reserved_ptr - back_borrowed_blocks_count}; + auto new_controller_after_reserved_ptr{ + controller_after_reserved_ptr - back_borrowed_blocks_count}; + ::fast_io::freestanding::non_overlapped_copy_n(new_controller_after_reserved_ptr, + back_borrowed_blocks_count, + new_controller_start_reserved_ptr); + *(controller.controller_block.controller_after_reserved_ptr = new_controller_after_reserved_ptr) = nullptr; + // after this line Todo + + auto ed{new_controller_start_reserved_ptr}; + new_controller_start_reserved_ptr -= to_allocate_blocks; + for (auto i{new_controller_start_reserved_ptr}; i != ed; ++i) + { + ::std::construct_at(i, static_cast(allocator::allocate_aligned(align, blockbytes))); + } + controller.controller_block.controller_start_reserved_ptr = new_controller_start_reserved_ptr; + } + } + return true; +} + +template +inline constexpr void deque_grow_front_common_impl( + dequecontroltype &controller, + std::size_t align, + std::size_t bytes) noexcept +{ + if (!::fast_io::containers::details::deque_reserve_front_blocks_impl(controller, 1zu, align, bytes)) + { + return; + } + auto begin_ptr{*(--controller.front_block.controller_ptr)}; + controller.front_block.begin_ptr = begin_ptr; + auto end_ptr{begin_ptr + bytes}; + controller.front_block.curr_ptr = end_ptr; + controller.front_end_ptr = end_ptr; +} + +template +inline constexpr void deque_grow_front_common(dequecontroltype &controller) noexcept +{ + constexpr ::std::size_t blockbytes{sz * block_size}; + if constexpr (false) + { + ::fast_io::containers::details::deque_grow_front_common_impl(controller, align, blockbytes); + } + else + { + ::fast_io::containers::details::deque_grow_front_common_old_impl(controller, align, blockbytes); + } +} + #endif } // namespace details From 13debbf648990c9b1d7ef08e253f877914d74c36 Mon Sep 17 00:00:00 2001 From: trcrsired Date: Thu, 29 Jan 2026 06:57:25 +0800 Subject: [PATCH 24/42] [skip] backup deque code --- include/fast_io_dsal/impl/deque.h | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/include/fast_io_dsal/impl/deque.h b/include/fast_io_dsal/impl/deque.h index 0d4e911a..008e5a34 100644 --- a/include/fast_io_dsal/impl/deque.h +++ b/include/fast_io_dsal/impl/deque.h @@ -1422,11 +1422,13 @@ template (controller, align, blockbytes); } else +#endif { ::fast_io::containers::details::deque_grow_back_common_old_impl(controller, align, blockbytes); } @@ -1565,11 +1567,13 @@ template (controller, align, blockbytes); } else +#endif { ::fast_io::containers::details::deque_grow_front_common_old_impl(controller, align, blockbytes); } From af0181fd16ee061c608f8ddb9bdd034ec7dc2dfd Mon Sep 17 00:00:00 2001 From: trcrsired Date: Fri, 30 Jan 2026 01:34:10 +0800 Subject: [PATCH 25/42] front_backspaces should prevent end() goes before begin() --- include/fast_io_dsal/impl/deque.h | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/include/fast_io_dsal/impl/deque.h b/include/fast_io_dsal/impl/deque.h index 008e5a34..10a49d86 100644 --- a/include/fast_io_dsal/impl/deque.h +++ b/include/fast_io_dsal/impl/deque.h @@ -1423,7 +1423,7 @@ inline constexpr void deque_grow_back_common(dequecontroltype &controller) noexc { constexpr ::std::size_t blockbytes{sz * block_size}; #if 1 - if constexpr (true) + if constexpr (false) { ::fast_io::containers::details::deque_grow_back_common_impl(controller, align, blockbytes); } @@ -1568,7 +1568,7 @@ inline constexpr void deque_grow_front_common(dequecontroltype &controller) noex { constexpr ::std::size_t blockbytes{sz * block_size}; #if 1 - if constexpr (true) + if constexpr (false) { ::fast_io::containers::details::deque_grow_front_common_impl(controller, align, blockbytes); } @@ -1978,6 +1978,9 @@ class deque FAST_IO_TRIVIALLY_RELOCATABLE_IF_ELIGIBLE auto front_controller_ptr{controller.front_block.controller_ptr}; if (front_controller_ptr == controller.back_block.controller_ptr) [[unlikely]] { + auto begin_ptr{controller.front_block.begin_ptr}; + constexpr ::std::size_t half_blocks_size{block_size >> 1u}; + controller.back_block.curr_ptr = (controller.front_block.curr_ptr = begin_ptr + half_blocks_size); return; } controller.front_end_ptr = (controller.front_block.curr_ptr = controller.front_block.begin_ptr = *(controller.front_block.controller_ptr = front_controller_ptr + 1)) + block_size; From 9f297581485c4b3301a56e66ec9fab4cbe548add Mon Sep 17 00:00:00 2001 From: trcrsired Date: Fri, 30 Jan 2026 02:43:15 +0800 Subject: [PATCH 26/42] add allocate_conditional_zero to win32_heapalloc as example for future allocator design --- .../fast_io_core_impl/allocation/win32_heapalloc.h | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/include/fast_io_core_impl/allocation/win32_heapalloc.h b/include/fast_io_core_impl/allocation/win32_heapalloc.h index 82596bee..ea8fa37b 100644 --- a/include/fast_io_core_impl/allocation/win32_heapalloc.h +++ b/include/fast_io_core_impl/allocation/win32_heapalloc.h @@ -154,6 +154,14 @@ class win32_heapalloc_allocator { return ::fast_io::details::win32_heapalloc_common_impl(n, 0x00000008u); } +#if __has_cpp_attribute(__gnu__::__malloc__) + [[__gnu__::__malloc__]] +#endif + static inline void *allocate_conditional_zero(::std::size_t n, bool zeroing) noexcept + { + return ::fast_io::details::win32_heapalloc_common_impl(n, zeroing ? 0x00000008u : 0u); + } + static inline void *reallocate(void *addr, ::std::size_t n) noexcept { return ::fast_io::details::win32_heaprealloc_common_impl(addr, n, 0u); @@ -162,6 +170,10 @@ class win32_heapalloc_allocator { return ::fast_io::details::win32_heaprealloc_common_impl(addr, n, 0x00000008u); } + static inline void *reallocate_conditional_zero(void *addr, ::std::size_t n, bool zeroing) noexcept + { + return ::fast_io::details::win32_heaprealloc_common_impl(addr, n, zeroing ? 0x00000008u : 0u); + } static inline void deallocate(void *addr) noexcept { if (addr == nullptr) [[unlikely]] From 74a83d7ccf7f22aea1452318861f1c404d08a844 Mon Sep 17 00:00:00 2001 From: trcrsired Date: Fri, 30 Jan 2026 03:02:07 +0800 Subject: [PATCH 27/42] [skip ci] deque add a toggle for switching to new implementation that shares with insert. all these useless garbage will be removed after the container finishes --- include/fast_io_dsal/impl/deque.h | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/include/fast_io_dsal/impl/deque.h b/include/fast_io_dsal/impl/deque.h index 10a49d86..fa74bb00 100644 --- a/include/fast_io_dsal/impl/deque.h +++ b/include/fast_io_dsal/impl/deque.h @@ -1422,13 +1422,16 @@ template (controller, align, blockbytes); } else -#endif { ::fast_io::containers::details::deque_grow_back_common_old_impl(controller, align, blockbytes); } @@ -1567,13 +1570,17 @@ template (controller, align, blockbytes); } else -#endif { ::fast_io::containers::details::deque_grow_front_common_old_impl(controller, align, blockbytes); } From 3907d9afa0c9254cb7954e45f2daa92018951b2e Mon Sep 17 00:00:00 2001 From: trcrsired Date: Fri, 30 Jan 2026 05:50:08 +0800 Subject: [PATCH 28/42] back_backspace may also go too far --- include/fast_io_dsal/impl/deque.h | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/include/fast_io_dsal/impl/deque.h b/include/fast_io_dsal/impl/deque.h index fa74bb00..a15bd4e5 100644 --- a/include/fast_io_dsal/impl/deque.h +++ b/include/fast_io_dsal/impl/deque.h @@ -849,7 +849,6 @@ inline constexpr void deque_grow_front_common_old_impl( std::construct_at(pos, new_block); } } - --controller.front_block.controller_ptr; auto begin_ptr = @@ -1995,7 +1994,15 @@ class deque FAST_IO_TRIVIALLY_RELOCATABLE_IF_ELIGIBLE inline constexpr void back_backspace() noexcept { - controller.back_block.curr_ptr = (controller.back_end_ptr = ((controller.back_block.begin_ptr = *--controller.back_block.controller_ptr) + block_size)); + auto back_controller_ptr{controller.back_block.controller_ptr}; + if (back_controller_ptr == controller.front_block.controller_ptr) [[unlikely]] + { + auto begin_ptr{controller.back_block.begin_ptr}; + constexpr ::std::size_t half_blocks_size{block_size >> 1u}; + controller.front_block.curr_ptr = (controller.back_block.curr_ptr = begin_ptr + half_blocks_size); + return; + } + controller.back_block.curr_ptr = (controller.back_end_ptr = ((controller.back_block.begin_ptr = *(controller.back_block.controller_ptr = back_controller_ptr - 1)) + block_size)); } public: @@ -2044,7 +2051,6 @@ class deque FAST_IO_TRIVIALLY_RELOCATABLE_IF_ELIGIBLE { ::fast_io::fast_terminate(); } - pop_back_unchecked(); } From 41f5858a0fd4231a07260811f5c9f24fb75c88c3 Mon Sep 17 00:00:00 2001 From: trcrsired Date: Fri, 30 Jan 2026 06:32:51 +0800 Subject: [PATCH 29/42] [skip ci] deque insert implementing front decision --- include/fast_io_dsal/impl/deque.h | 58 ++++++++++++++++++++++++++----- 1 file changed, 49 insertions(+), 9 deletions(-) diff --git a/include/fast_io_dsal/impl/deque.h b/include/fast_io_dsal/impl/deque.h index a15bd4e5..c6e604bb 100644 --- a/include/fast_io_dsal/impl/deque.h +++ b/include/fast_io_dsal/impl/deque.h @@ -1472,7 +1472,6 @@ inline constexpr void deque_reserve_back_spaces(dequecontroltype &controller, :: } } - template inline constexpr bool deque_reserve_front_blocks_impl(dequecontroltype &controller, ::std::size_t nb, ::std::size_t align, ::std::size_t blockbytes) noexcept { @@ -1548,6 +1547,42 @@ inline constexpr bool deque_reserve_front_blocks_impl(dequecontroltype &controll return true; } +template +inline constexpr void deque_reserve_front_spaces(dequecontroltype &controller, ::std::size_t n) +{ + if (!n) + { + return; + } + auto front_curr_ptr{controller.front_block.curr_ptr}; + ::std::size_t blocksn{static_cast<::std::size_t>(front_curr_ptr - controller.front_block.begin_ptr)}; + if (n <= blocksn) + { + return; + } + ::std::size_t startpos{static_cast<::std::size_t>(controller.front_end_ptr - front_curr_ptr)}; + ::std::size_t nmblocksn{n - blocksn}; + ::std::size_t front_more_blocks{nmblocksn / block_size}; + ::std::size_t const front_more_blocks_mod{nmblocksn % block_size}; + ::std::size_t toallocate{front_more_blocks}; + if (front_more_blocks_mod) + { + ++toallocate; + } + if consteval + { + ::fast_io::containers::details::deque_reserve_front_blocks_impl(controller, + toallocate, align, block_size); + } + else + { + constexpr ::std::size_t block_bytes{block_size * sz}; + ::fast_io::containers::details::deque_reserve_front_blocks_impl(*reinterpret_cast<::fast_io::containers::details::deque_controller_common *>( + __builtin_addressof(controller)), + toallocate, align, block_bytes); + } +} + template inline constexpr void deque_grow_front_common_impl( dequecontroltype &controller, @@ -2371,24 +2406,29 @@ class deque FAST_IO_TRIVIALLY_RELOCATABLE_IF_ELIGIBLE { return {pos, this->begin() + pos}; } -#if 0 +#if 1 size_type const half_size{old_size >> 1u}; if (pos < half_size) { - + ::fast_io::containers::details::deque_reserve_front_spaces(this->controller, rgsize); + auto thisbg{this->begin()}; + auto posit{thisbg + pos}; + auto thisbgrgsize{thisbg - rgsize}; + auto thisbgrgsizenew{::fast_io::freestanding::uninitialized_relocate(thisbg, + posit, thisbgrgsize)}; + ::fast_io::freestanding::uninitialized_copy_n(::std::ranges::cbegin(rg), rgsize, thisbgrgsizenew); + + this->controller.front_block = thisbgrgsize.itercontent; + this->controller.front_end_ptr = thisbgrgsize.itercontent.begin_ptr + block_size; + return {pos, thisbgrgsizenew}; } else #endif { -#if 0 - ::fast_io::io::debug_println(::std::source_location::current(), "\tthis->size()=", this->size(), " rgsize=", rgsize); -#endif ::fast_io::containers::details::deque_reserve_back_spaces(this->controller, rgsize); auto posit{this->begin() + pos}; -#if 0 - ::fast_io::io::debug_println(::std::source_location::current(), "\tthis->size()=", this->size(), " rgsize=", rgsize); -#endif auto thisend{this->end()}; auto thisendrgsize{thisend + rgsize}; ::fast_io::freestanding::uninitialized_relocate_backward(posit, From 5e6ee56c5cc994083550afd1fde6bb4fe4d8d2d6 Mon Sep 17 00:00:00 2001 From: trcrsired Date: Fri, 30 Jan 2026 06:36:22 +0800 Subject: [PATCH 30/42] deque removes all old push back/front code but just using insert --- include/fast_io_dsal/impl/deque.h | 236 +----------------------------- 1 file changed, 3 insertions(+), 233 deletions(-) diff --git a/include/fast_io_dsal/impl/deque.h b/include/fast_io_dsal/impl/deque.h index c6e604bb..b8b3cfcb 100644 --- a/include/fast_io_dsal/impl/deque.h +++ b/include/fast_io_dsal/impl/deque.h @@ -661,202 +661,6 @@ inline constexpr void deque_allocate_on_empty_common_with_n_impl(dequecontroltyp back_block.curr_ptr = halfposptr; } -template -inline constexpr void deque_allocate_on_empty_common_impl(dequecontroltype &controller, ::std::size_t align, ::std::size_t bytes) noexcept -{ - constexpr ::std::size_t initial_allocated_block_counts{3}; - ::fast_io::containers::details::deque_allocate_on_empty_common_with_n_impl(controller, align, bytes, initial_allocated_block_counts); -} - -// To remove -template -inline constexpr void deque_grow_back_common_old_impl( - dequecontroltype &controller, - std::size_t align, - std::size_t bytes) noexcept -{ - /** - * If the deque is empty, allocate the initial controller array - * and a single data block. This sets up the initial front/back - * block pointers and the sentinel. - */ - if (controller.controller_block.controller_start_ptr == nullptr) - { - ::fast_io::containers::details:: - deque_allocate_on_empty_common_impl(controller, align, bytes); - return; - } - - using replacetype = typename dequecontroltype::replacetype; - constexpr bool isvoidplaceholder = std::same_as; - using begin_ptrtype = - std::conditional_t; - - /** - * Compute how many controller slots remain between the current - * back block and controller_after_reserved_ptr. - * - * We require at least: - * - 1 slot for the new block pointer - * - 1 slot for the sentinel nullptr - */ - std::size_t diff_to_after_ptr = - static_cast( - controller.controller_block.controller_after_reserved_ptr - - controller.back_block.controller_ptr); - if (diff_to_after_ptr < 2) - { - /** - * If controller_after_reserved_ptr == controller_after_ptr, - * the controller array is physically full. We must rebalance - * or grow the controller array before inserting anything. - */ - if (controller.controller_block.controller_after_reserved_ptr == - controller.controller_block.controller_after_ptr) - { - ::fast_io::containers::details:: - deque_rebalance_or_grow_2x_after_blocks_impl(controller); - } - std::size_t diff_to_after_ptr2 = - static_cast( - controller.controller_block.controller_after_reserved_ptr - - controller.back_block.controller_ptr); - if (diff_to_after_ptr2 < 2) - { - begin_ptrtype new_block; - - /** - * Borrow a capacity block from the front if available. - * - * A capacity block exists at the front if - * controller_start_reserved_ptr != front_block.controller_ptr. - * - * Such a block contains no constructed elements and its memory - * can be reused directly as the new back block. - */ - if (controller.controller_block.controller_start_reserved_ptr != - controller.front_block.controller_ptr) - { - auto start_reserved_ptr = - controller.controller_block.controller_start_reserved_ptr; - - /* Reuse the block memory. */ - new_block = static_cast(*start_reserved_ptr); - - /* Consume one reserved block from the front. */ - ++controller.controller_block.controller_start_reserved_ptr; - } - else - { - /** - * No front capacity block is available. Allocate a new block. - */ - new_block = - static_cast(allocator::allocate_aligned(align, bytes)); - } - - /** - * Insert the new block pointer at controller_after_reserved_ptr, - * then advance controller_after_reserved_ptr and write the sentinel. - */ - auto pos{controller.controller_block.controller_after_reserved_ptr}; - ::std::construct_at(pos, new_block); - *(controller.controller_block.controller_after_reserved_ptr = pos + 1) = nullptr; - } - } - - if (controller.back_block.controller_ptr == controller.front_block.controller_ptr && controller.front_block.curr_ptr == controller.front_end_ptr) - { - auto front_block_controller_ptr{controller.front_block.controller_ptr + 1}; - controller.front_block.controller_ptr = front_block_controller_ptr; - auto front_begin_ptr = static_cast(*front_block_controller_ptr); - controller.front_block.curr_ptr = controller.front_block.begin_ptr = front_begin_ptr; - controller.front_end_ptr = front_begin_ptr + bytes; - } - - /** - * At this point, we have guaranteed controller capacity. - * Advance back_block.controller_ptr to the new block slot. - */ - ++controller.back_block.controller_ptr; - - /** - * Load the block pointer and initialize begin/curr/end pointers. - */ - auto begin_ptr = - static_cast(*controller.back_block.controller_ptr); - - controller.back_block.begin_ptr = begin_ptr; - controller.back_block.curr_ptr = begin_ptr; - controller.back_end_ptr = begin_ptr + bytes; - -#if 0 - ::fast_io::iomnp::debug_println(::std::source_location::current()); -#endif -} - -template -inline constexpr void deque_grow_front_common_old_impl( - dequecontroltype &controller, - std::size_t align, - std::size_t bytes) noexcept -{ - if (controller.controller_block.controller_start_ptr == nullptr) - { - ::fast_io::containers::details:: - deque_allocate_on_empty_common_impl(controller, align, bytes); - return; - } - - using replacetype = typename dequecontroltype::replacetype; - constexpr bool isvoidplaceholder = std::same_as; - using begin_ptrtype = - std::conditional_t; - if (controller.front_block.controller_ptr == - controller.controller_block.controller_start_reserved_ptr) - { - if (controller.controller_block.controller_start_reserved_ptr == - controller.controller_block.controller_start_ptr) - { - ::fast_io::containers::details:: - deque_rebalance_or_grow_2x_after_blocks_impl(controller); - } - if (controller.front_block.controller_ptr == - controller.controller_block.controller_start_reserved_ptr) - { - begin_ptrtype new_block; - auto after_reserved_ptr = - controller.controller_block.controller_after_reserved_ptr; - std::size_t diff_to_after_ptr = - static_cast( - after_reserved_ptr - - controller.back_block.controller_ptr); - if (1 < diff_to_after_ptr) - { - /* Reuse the block memory. */ - new_block = static_cast(*(--after_reserved_ptr)); - - /* Consume one reserved block from the back. */ - *(controller.controller_block.controller_after_reserved_ptr = after_reserved_ptr) = nullptr; - } - else - { - new_block = - static_cast(allocator::allocate_aligned(align, bytes)); - } - - auto pos{--controller.controller_block.controller_start_reserved_ptr}; - std::construct_at(pos, new_block); - } - } - --controller.front_block.controller_ptr; - - auto begin_ptr = - static_cast(*controller.front_block.controller_ptr); - controller.front_block.begin_ptr = begin_ptr; - controller.front_end_ptr = (controller.front_block.curr_ptr = (begin_ptr + bytes)); -} - template inline constexpr void deque_clear_common_impl(dequecontroltype &controller, ::std::size_t blockbytes) { @@ -1230,8 +1034,6 @@ deque_erase_common_trivial_impl(::fast_io::containers::details::deque_controller return first; } -#if 1 - template inline constexpr void deque_rebalance_or_grow_insertation_impl(dequecontroltype &controller, ::std::size_t extrablocks) noexcept { @@ -1421,19 +1223,7 @@ template (controller, align, blockbytes); - } - else - { - ::fast_io::containers::details::deque_grow_back_common_old_impl(controller, align, blockbytes); - } + ::fast_io::containers::details::deque_grow_back_common_impl(controller, align, blockbytes); } template @@ -1605,22 +1395,9 @@ inline constexpr void deque_grow_front_common(dequecontroltype &controller) noex { constexpr ::std::size_t blockbytes{sz * block_size}; - constexpr bool use_new_push_implementation{ -#ifdef FAST_IO_DEBUG_DEQUE_USE_NEW_PUSH_IMPLEMENTATION - true -#endif - }; - if constexpr (use_new_push_implementation) - { - ::fast_io::containers::details::deque_grow_front_common_impl(controller, align, blockbytes); - } - else - { - ::fast_io::containers::details::deque_grow_front_common_old_impl(controller, align, blockbytes); - } + ::fast_io::containers::details::deque_grow_front_common_impl(controller, align, blockbytes); } -#endif } // namespace details @@ -2394,19 +2171,13 @@ class deque FAST_IO_TRIVIALLY_RELOCATABLE_IF_ELIGIBLE requires ::std::constructible_from> inline constexpr insert_range_result insert_range_impl(size_type pos, R &&rg, size_type old_size) noexcept(::std::is_nothrow_constructible_v>) { - constexpr bool enable_size_insertation{ -#ifdef FAST_IO_DEBUG_ENABLE_SIZE_INSERTATION - true // we haven't yet finished this so we use a macro. will remove it later on -#endif - }; - if constexpr (::std::ranges::sized_range && enable_size_insertation) + if constexpr (::std::ranges::sized_range) { size_type const rgsize{::std::ranges::size(rg)}; if (!rgsize) { return {pos, this->begin() + pos}; } -#if 1 size_type const half_size{old_size >> 1u}; if (pos < half_size) { @@ -2424,7 +2195,6 @@ class deque FAST_IO_TRIVIALLY_RELOCATABLE_IF_ELIGIBLE return {pos, thisbgrgsizenew}; } else -#endif { ::fast_io::containers::details::deque_reserve_back_spaces(this->controller, rgsize); From eab427f3f10b981ebfd9e07410e79a4295fc2366 Mon Sep 17 00:00:00 2001 From: trcrsired Date: Fri, 30 Jan 2026 06:48:12 +0800 Subject: [PATCH 31/42] deque add insert benchmark. --- .../deque/0003.insert_range/fast_io.cc | 33 +++++++++++++++++++ .../deque/0003.insert_range/std.cc | 33 +++++++++++++++++++ 2 files changed, 66 insertions(+) create mode 100644 benchmark/0011.containers/deque/0003.insert_range/fast_io.cc create mode 100644 benchmark/0011.containers/deque/0003.insert_range/std.cc diff --git a/benchmark/0011.containers/deque/0003.insert_range/fast_io.cc b/benchmark/0011.containers/deque/0003.insert_range/fast_io.cc new file mode 100644 index 00000000..15d2f324 --- /dev/null +++ b/benchmark/0011.containers/deque/0003.insert_range/fast_io.cc @@ -0,0 +1,33 @@ +#include +#include +#include +#include + +int main() +{ + fast_io::timer tm(u8"fast_io::deque"); + fast_io::deque dq; + constexpr std::size_t n{50000}; + + { + fast_io::timer t(u8"insert_range_index"); + for (std::size_t i{}; i != n; ++i) + { + ::std::size_t dqsz{dq.size()}; + std::size_t pos = dqsz ? (i % dqsz) : 0; + std::size_t tmp[4]{i, i + 1, i + 2, i + 3}; + dq.insert_range_index(pos, tmp); + } + } + + std::size_t sum{}; + { + fast_io::timer t(u8"loop"); + for (auto const e : dq) + { + sum += e; + } + } + + fast_io::io::perrln("sum=", sum); +} diff --git a/benchmark/0011.containers/deque/0003.insert_range/std.cc b/benchmark/0011.containers/deque/0003.insert_range/std.cc new file mode 100644 index 00000000..29fd5d56 --- /dev/null +++ b/benchmark/0011.containers/deque/0003.insert_range/std.cc @@ -0,0 +1,33 @@ +#include +#include +#include +#include + +int main() +{ + fast_io::timer tm(u8"fast_io::deque"); + ::std::deque dq; + constexpr std::size_t n{50000}; + + { + fast_io::timer t(u8"insert_range"); + for (std::size_t i{}; i != n; ++i) + { + ::std::size_t dqsz{dq.size()}; + std::size_t pos = dqsz ? (i % dqsz) : 0; + std::size_t tmp[4]{i, i + 1, i + 2, i + 3}; + dq.insert_range(dq.cbegin() + pos, tmp); + } + } + + std::size_t sum{}; + { + fast_io::timer t(u8"loop"); + for (auto const e : dq) + { + sum += e; + } + } + + fast_io::io::perrln("sum=", sum); +} From 8428d072762f560e281406bfe603eb3cb943b742 Mon Sep 17 00:00:00 2001 From: trcrsired Date: Fri, 30 Jan 2026 07:03:22 +0800 Subject: [PATCH 32/42] [skip ci] std not fast_io in deque insert_range bench --- benchmark/0011.containers/deque/0003.insert_range/std.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/benchmark/0011.containers/deque/0003.insert_range/std.cc b/benchmark/0011.containers/deque/0003.insert_range/std.cc index 29fd5d56..5fb70b6a 100644 --- a/benchmark/0011.containers/deque/0003.insert_range/std.cc +++ b/benchmark/0011.containers/deque/0003.insert_range/std.cc @@ -5,7 +5,7 @@ int main() { - fast_io::timer tm(u8"fast_io::deque"); + fast_io::timer tm(u8"std::deque"); ::std::deque dq; constexpr std::size_t n{50000}; From 75c14e4ff3042c8becaa0057c67015711a6c8533 Mon Sep 17 00:00:00 2001 From: trcrsired Date: Fri, 30 Jan 2026 16:33:14 +0800 Subject: [PATCH 33/42] uninitialized algos add hooks --- include/fast_io_dsal/impl/freestanding.h | 36 ++++++++++++------------ 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/include/fast_io_dsal/impl/freestanding.h b/include/fast_io_dsal/impl/freestanding.h index 673f385b..cf17a9c4 100644 --- a/include/fast_io_dsal/impl/freestanding.h +++ b/include/fast_io_dsal/impl/freestanding.h @@ -2,24 +2,25 @@ namespace fast_io::operations::defines { -template -concept has_uninitialized_relocate_define = requires(T *ptr) { - { uninitialized_relocate_define(ptr, ptr, ptr) } -> ::std::same_as; + +template +concept has_uninitialized_relocate_define = ::std::sentinel_for && requires(Iter1 first, Snt last, Iter2 dest) { + { uninitialized_relocate_define(first, last, dest) } -> ::std::same_as; }; -template -concept has_uninitialized_relocate_backward_define = requires(T *ptr) { - { uninitialized_relocate_backward_define(ptr, ptr, ptr) } -> ::std::same_as; +template +concept has_uninitialized_relocate_backward_define = ::std::sentinel_for && requires(Iter1 first, Snt last, Iter2 dest) { + { uninitialized_relocate_backward_define(first, last, dest) } -> ::std::same_as; }; -template -concept has_uninitialized_move_define = requires(T *ptr) { - { uninitialized_move_define(ptr, ptr, ptr) } -> ::std::same_as; +template +concept has_uninitialized_move_define = ::std::sentinel_for && requires(Iter1 first, Snt last, Iter2 dest) { + { uninitialized_move_define(first, last, dest) } -> ::std::same_as; }; -template -concept has_uninitialized_move_backward_define = requires(T *ptr) { - { uninitialized_move_backward_define(ptr, ptr, ptr) } -> ::std::same_as; +template +concept has_uninitialized_move_backward_define = ::std::sentinel_for && requires(Iter1 first, Snt last, Iter2 dest) { + { uninitialized_move_backward_define(first, last, dest) } -> ::std::same_as; }; } // namespace fast_io::operations::defines @@ -70,7 +71,7 @@ inline constexpr Iter2 uninitialized_relocate(Iter1 first, Iter1 last, Iter2 des return reinterpret_cast(::fast_io::freestanding::bytes_copy(reinterpret_cast<::std::byte const *>(first), reinterpret_cast<::std::byte const *>(last), reinterpret_cast<::std::byte *>(dest))); } } - else if constexpr (::std::same_as && ::fast_io::operations::defines::has_uninitialized_relocate_define) + else if constexpr (::fast_io::operations::defines::has_uninitialized_relocate_define) { return uninitialized_relocate_define(first, last, dest); } @@ -163,10 +164,9 @@ inline constexpr Iter2 uninitialized_relocate_backward(Iter1 first, Iter1 last, } } // Custom relocate_backward hook for user-defined types - else if constexpr (::std::same_as && - ::fast_io::operations::defines::has_uninitialized_relocate_define) + else if constexpr (::fast_io::operations::defines::has_uninitialized_relocate_backward_define) { - return uninitialized_relocate_define_backward(first, last, dest); + return uninitialized_relocate_backward_define(first, last, dest); } // Generic slow path: @@ -236,7 +236,7 @@ inline constexpr Iter2 uninitialized_move(Iter1 first, Iter1 last, Iter2 dest) n return reinterpret_cast(::fast_io::freestanding::bytes_copy(reinterpret_cast<::std::byte const *>(first), reinterpret_cast<::std::byte const *>(last), reinterpret_cast<::std::byte *>(dest))); } } - else if constexpr (::std::same_as && ::fast_io::operations::defines::has_uninitialized_move_backward_define) + else if constexpr (::fast_io::operations::defines::has_uninitialized_move_define) { return uninitialized_move_define(first, last, dest); } @@ -294,7 +294,7 @@ inline constexpr Iter2 uninitialized_move_backward(Iter1 first, Iter1 last, Iter return d_start; } } - else if constexpr (::std::same_as && ::fast_io::operations::defines::has_uninitialized_move_backward_define) + else if constexpr (::fast_io::operations::defines::has_uninitialized_move_backward_define) { return uninitialized_move_backward_define(first, last, d_last); } From 1f36a6f2e649e0306103137fd7ae785949241e02 Mon Sep 17 00:00:00 2001 From: trcrsired Date: Fri, 30 Jan 2026 17:27:36 +0800 Subject: [PATCH 34/42] [skip ci] backup type code for algo since it may be useless --- include/fast_io_dsal/impl/freestanding.h | 25 ++++++++++++++++-------- 1 file changed, 17 insertions(+), 8 deletions(-) diff --git a/include/fast_io_dsal/impl/freestanding.h b/include/fast_io_dsal/impl/freestanding.h index cf17a9c4..e5270cf9 100644 --- a/include/fast_io_dsal/impl/freestanding.h +++ b/include/fast_io_dsal/impl/freestanding.h @@ -3,24 +3,33 @@ namespace fast_io::operations::defines { +template +struct memory_algorithm_define_type +{ + explicit constexpr memory_algorithm_define_type() noexcept = default; +}; + +template +inline constexpr memory_algorithm_define_type memory_algorithm_define{}; + template concept has_uninitialized_relocate_define = ::std::sentinel_for && requires(Iter1 first, Snt last, Iter2 dest) { - { uninitialized_relocate_define(first, last, dest) } -> ::std::same_as; + { uninitialized_relocate_define(::fast_io::operations::defines::memory_algorithm_define, first, last, dest) } -> ::std::same_as; }; template concept has_uninitialized_relocate_backward_define = ::std::sentinel_for && requires(Iter1 first, Snt last, Iter2 dest) { - { uninitialized_relocate_backward_define(first, last, dest) } -> ::std::same_as; + { uninitialized_relocate_backward_define(::fast_io::operations::defines::memory_algorithm_define, first, last, dest) } -> ::std::same_as; }; template concept has_uninitialized_move_define = ::std::sentinel_for && requires(Iter1 first, Snt last, Iter2 dest) { - { uninitialized_move_define(first, last, dest) } -> ::std::same_as; + { uninitialized_move_define(::fast_io::operations::defines::memory_algorithm_define, first, last, dest) } -> ::std::same_as; }; template concept has_uninitialized_move_backward_define = ::std::sentinel_for && requires(Iter1 first, Snt last, Iter2 dest) { - { uninitialized_move_backward_define(first, last, dest) } -> ::std::same_as; + { uninitialized_move_backward_define(::fast_io::operations::defines::memory_algorithm_define, first, last, dest) } -> ::std::same_as; }; } // namespace fast_io::operations::defines @@ -73,7 +82,7 @@ inline constexpr Iter2 uninitialized_relocate(Iter1 first, Iter1 last, Iter2 des } else if constexpr (::fast_io::operations::defines::has_uninitialized_relocate_define) { - return uninitialized_relocate_define(first, last, dest); + return uninitialized_relocate_define(::fast_io::operations::defines::memory_algorithm_define, first, last, dest); } // we do not allow move constructor to throw EH. while (first != last) @@ -166,7 +175,7 @@ inline constexpr Iter2 uninitialized_relocate_backward(Iter1 first, Iter1 last, // Custom relocate_backward hook for user-defined types else if constexpr (::fast_io::operations::defines::has_uninitialized_relocate_backward_define) { - return uninitialized_relocate_backward_define(first, last, dest); + return uninitialized_relocate_backward_define(::fast_io::operations::defines::memory_algorithm_define, first, last, dest); } // Generic slow path: @@ -238,7 +247,7 @@ inline constexpr Iter2 uninitialized_move(Iter1 first, Iter1 last, Iter2 dest) n } else if constexpr (::fast_io::operations::defines::has_uninitialized_move_define) { - return uninitialized_move_define(first, last, dest); + return uninitialized_move_define(::fast_io::operations::defines::memory_algorithm_define, first, last, dest); } // we do not allow move constructor to throw EH. while (first != last) @@ -296,7 +305,7 @@ inline constexpr Iter2 uninitialized_move_backward(Iter1 first, Iter1 last, Iter } else if constexpr (::fast_io::operations::defines::has_uninitialized_move_backward_define) { - return uninitialized_move_backward_define(first, last, d_last); + return uninitialized_move_backward_define(::fast_io::operations::defines::memory_algorithm_define, first, last, d_last); } while (first != last) { From 602df4b15301acfc02f0069b279b9e57b50e9ed8 Mon Sep 17 00:00:00 2001 From: trcrsired Date: Fri, 30 Jan 2026 21:17:45 +0800 Subject: [PATCH 35/42] [deque] add hooks to freestanding algos --- include/fast_io_dsal/impl/deque.h | 28 ++++++++++- include/fast_io_dsal/impl/freestanding.h | 61 +++++++++++++++++++----- 2 files changed, 76 insertions(+), 13 deletions(-) diff --git a/include/fast_io_dsal/impl/deque.h b/include/fast_io_dsal/impl/deque.h index b8b3cfcb..d217837d 100644 --- a/include/fast_io_dsal/impl/deque.h +++ b/include/fast_io_dsal/impl/deque.h @@ -426,7 +426,6 @@ inline constexpr auto operator<=>(::fast_io::containers::details::deque_iterator return block3way; } - template inline constexpr void deque_destroy_trivial_common_align(controllerblocktype &controller, ::std::size_t aligns, ::std::size_t totalsz) noexcept { @@ -1398,6 +1397,33 @@ inline constexpr void deque_grow_front_common(dequecontroltype &controller) noex ::fast_io::containers::details::deque_grow_front_common_impl(controller, align, blockbytes); } +template +struct is_fast_io_deque_iterator_impl : ::std::false_type +{}; + +template +struct is_fast_io_deque_iterator_impl< + ::fast_io::containers::details::deque_iterator> : ::std::true_type +{}; + +template +struct is_fast_io_deque_iterator_impl< + ::fast_io::containers::details::deque_iterator> : ::std::true_type +{}; + +template +concept is_fast_io_deque_iterator_v = + ::fast_io::containers::details::is_fast_io_deque_iterator_impl>::value; + +template + requires(::fast_io::containers::details::is_fast_io_deque_iterator_v || + ::fast_io::containers::details::is_fast_io_deque_iterator_v) +inline constexpr Iter2 uninitialized_relocate_define( + ::fast_io::operations::defines::memory_algorithm_define_type, + Iter1 first, Sentinel last, Iter2 dest) +{ + return ::fast_io::freestanding::uninitialized_relocate_ignore_define(first, last, dest); +} } // namespace details diff --git a/include/fast_io_dsal/impl/freestanding.h b/include/fast_io_dsal/impl/freestanding.h index e5270cf9..66d55630 100644 --- a/include/fast_io_dsal/impl/freestanding.h +++ b/include/fast_io_dsal/impl/freestanding.h @@ -40,23 +40,24 @@ namespace fast_io::freestanding /* uninitialized_relocate requires two range are not overlapped. */ -template <::std::input_or_output_iterator Iter1, ::std::input_or_output_iterator Iter2> -inline constexpr Iter2 uninitialized_relocate(Iter1 first, Iter1 last, Iter2 dest) noexcept + +template <::std::input_or_output_iterator Iter1, ::std::sentinel_for Sent, ::std::input_or_output_iterator Iter2> +inline constexpr Iter2 uninitialized_relocate_ignore_define(Iter1 first, Sent last, Iter2 dest) noexcept { if constexpr (::std::contiguous_iterator && !::std::is_pointer_v && ::std::contiguous_iterator && !::std::is_pointer_v) { - return uninitialized_relocate(::std::to_address(first), ::std::to_address(last), - ::std::to_address(dest)) - + return uninitialized_relocate_ignore_define(::std::to_address(first), ::std::to_address(last), + ::std::to_address(dest)) - ::std::to_address(dest) + dest; } else if constexpr (::std::contiguous_iterator && !::std::is_pointer_v) { - return uninitialized_relocate(::std::to_address(first), ::std::to_address(last), - dest); + return uninitialized_relocate_ignore_define(::std::to_address(first), ::std::to_address(last), + dest); } else if constexpr (::std::contiguous_iterator && !::std::is_pointer_v) { - return uninitialized_relocate(first, last, ::std::to_address(dest)) - + return uninitialized_relocate_ignore_define(first, last, ::std::to_address(dest)) - ::std::to_address(dest) + dest; } else @@ -80,10 +81,6 @@ inline constexpr Iter2 uninitialized_relocate(Iter1 first, Iter1 last, Iter2 des return reinterpret_cast(::fast_io::freestanding::bytes_copy(reinterpret_cast<::std::byte const *>(first), reinterpret_cast<::std::byte const *>(last), reinterpret_cast<::std::byte *>(dest))); } } - else if constexpr (::fast_io::operations::defines::has_uninitialized_relocate_define) - { - return uninitialized_relocate_define(::fast_io::operations::defines::memory_algorithm_define, first, last, dest); - } // we do not allow move constructor to throw EH. while (first != last) { @@ -107,6 +104,41 @@ inline constexpr Iter2 uninitialized_relocate(Iter1 first, Iter1 last, Iter2 des } } +template <::std::input_or_output_iterator Iter1, ::std::sentinel_for Snt, ::std::input_or_output_iterator Iter2> +inline constexpr Iter2 uninitialized_relocate(Iter1 first, Snt last, Iter2 dest) noexcept +{ + if constexpr ( + ::std::same_as && ::std::contiguous_iterator && !::std::is_pointer_v && ::std::contiguous_iterator && !::std::is_pointer_v) + { + return uninitialized_relocate(::std::to_address(first), ::std::to_address(last), + ::std::to_address(dest)) - + ::std::to_address(dest) + dest; + } + else if constexpr (::std::same_as && ::std::contiguous_iterator && !::std::is_pointer_v) + { + return uninitialized_relocate(::std::to_address(first), ::std::to_address(last), + dest); + } + else if constexpr (::std::same_as && ::std::contiguous_iterator && !::std::is_pointer_v) + { + return uninitialized_relocate(first, last, ::std::to_address(dest)) - + ::std::to_address(dest) + dest; + } + else + { + using iter1valuetype = ::std::iter_value_t; + using iter2valuetype = ::std::iter_value_t; + if constexpr (::fast_io::operations::defines::has_uninitialized_relocate_define) + { + return uninitialized_relocate_define(::fast_io::operations::defines::memory_algorithm_define, first, last, dest); + } + else + { + return ::fast_io::freestanding::uninitialized_relocate_ignore_define(first, last, dest); + } + } +} + template <::std::bidirectional_iterator Iter1, ::std::bidirectional_iterator Iter2> inline constexpr Iter2 uninitialized_relocate_backward(Iter1 first, Iter1 last, Iter2 dest) noexcept { @@ -173,11 +205,12 @@ inline constexpr Iter2 uninitialized_relocate_backward(Iter1 first, Iter1 last, } } // Custom relocate_backward hook for user-defined types +#if 0 else if constexpr (::fast_io::operations::defines::has_uninitialized_relocate_backward_define) { return uninitialized_relocate_backward_define(::fast_io::operations::defines::memory_algorithm_define, first, last, dest); } - +#endif // Generic slow path: // Move-construct elements in reverse order into uninitialized memory, // then destroy the original elements. @@ -245,10 +278,12 @@ inline constexpr Iter2 uninitialized_move(Iter1 first, Iter1 last, Iter2 dest) n return reinterpret_cast(::fast_io::freestanding::bytes_copy(reinterpret_cast<::std::byte const *>(first), reinterpret_cast<::std::byte const *>(last), reinterpret_cast<::std::byte *>(dest))); } } +#if 0 else if constexpr (::fast_io::operations::defines::has_uninitialized_move_define) { return uninitialized_move_define(::fast_io::operations::defines::memory_algorithm_define, first, last, dest); } +#endif // we do not allow move constructor to throw EH. while (first != last) { @@ -303,10 +338,12 @@ inline constexpr Iter2 uninitialized_move_backward(Iter1 first, Iter1 last, Iter return d_start; } } +#if 0 else if constexpr (::fast_io::operations::defines::has_uninitialized_move_backward_define) { return uninitialized_move_backward_define(::fast_io::operations::defines::memory_algorithm_define, first, last, d_last); } +#endif while (first != last) { ::std::construct_at(--d_last, std::move(*(--last))); From f2d302b5712db7feef7370c98a3da022f23507a9 Mon Sep 17 00:00:00 2001 From: trcrsired Date: Tue, 3 Feb 2026 07:25:21 +0800 Subject: [PATCH 36/42] [deque] use copy_backward and copy should work for deque overlapped_copy only works for trivially_copyable types --- include/fast_io_core_impl/freestanding/algorithm.h | 6 ++++-- include/fast_io_dsal/impl/deque.h | 7 ++++--- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/include/fast_io_core_impl/freestanding/algorithm.h b/include/fast_io_core_impl/freestanding/algorithm.h index 279d67d4..63be6f23 100644 --- a/include/fast_io_core_impl/freestanding/algorithm.h +++ b/include/fast_io_core_impl/freestanding/algorithm.h @@ -436,7 +436,8 @@ inline constexpr output_iter non_overlapped_copy(input_iter first, input_iter la } template <::std::contiguous_iterator input_iter, ::std::contiguous_iterator output_iter> - requires(::std::same_as<::std::iter_value_t, ::std::iter_value_t>) + requires(::std::same_as<::std::iter_value_t, ::std::iter_value_t> && + ::std::is_trivially_copyable_v<::std::iter_value_t>) inline constexpr output_iter overlapped_copy(input_iter first, input_iter last, output_iter result) { if (__builtin_is_constant_evaluated()) @@ -485,7 +486,8 @@ inline constexpr output_iter overlapped_copy(input_iter first, input_iter last, } template <::std::contiguous_iterator input_iter, ::std::contiguous_iterator output_iter> - requires(::std::same_as<::std::iter_value_t, ::std::iter_value_t>) + requires(::std::same_as<::std::iter_value_t, ::std::iter_value_t> && + ::std::is_trivially_copyable_v<::std::iter_value_t>) inline output_iter overlapped_copy_n(input_iter first, ::std::size_t count, output_iter result) { if (__builtin_is_constant_evaluated()) diff --git a/include/fast_io_dsal/impl/deque.h b/include/fast_io_dsal/impl/deque.h index d217837d..38277700 100644 --- a/include/fast_io_dsal/impl/deque.h +++ b/include/fast_io_dsal/impl/deque.h @@ -903,7 +903,7 @@ deque_copy_impl(Itercontent first, Itercontent last, { tocopy = dest_block_to_end; } - ::fast_io::freestanding::overlapped_copy_n(firstcurrptr, tocopy, destcurrptr); + ::fast_io::freestanding::copy_n(firstcurrptr, tocopy, destcurrptr); if (0 < cmp) { dest.curr_ptr = (dest.begin_ptr = (*++dest.controller_ptr)); @@ -965,8 +965,8 @@ deque_copy_backward_impl(Itercontent first, Itercontent last, { tocopy = dest_block_to_begin; } - ::fast_io::freestanding::overlapped_copy_n(lastcurrptr - tocopy, tocopy, - destcurrptr - tocopy); + ::fast_io::freestanding::copy_backward(lastcurrptr - tocopy, lastcurrptr, + destcurrptr); if (0 < cmp) { dest.curr_ptr = (dest.begin_ptr = (*--dest.controller_ptr)) + blocksize; @@ -1422,6 +1422,7 @@ inline constexpr Iter2 uninitialized_relocate_define( ::fast_io::operations::defines::memory_algorithm_define_type, Iter1 first, Sentinel last, Iter2 dest) { + return ::fast_io::freestanding::uninitialized_relocate_ignore_define(first, last, dest); } From db7e9a763d4efca7b9f74e88d887a20739f09f61 Mon Sep 17 00:00:00 2001 From: trcrsired Date: Tue, 3 Feb 2026 08:01:55 +0800 Subject: [PATCH 37/42] [deque] add hooks for uninitialized_relocate_backward implement deque iterator relocate and relocate_backward --- include/fast_io_dsal/impl/deque.h | 56 ++++++++++++++++-- include/fast_io_dsal/impl/freestanding.h | 75 ++++++++++++++++++------ 2 files changed, 108 insertions(+), 23 deletions(-) diff --git a/include/fast_io_dsal/impl/deque.h b/include/fast_io_dsal/impl/deque.h index 38277700..f5417f5b 100644 --- a/include/fast_io_dsal/impl/deque.h +++ b/include/fast_io_dsal/impl/deque.h @@ -31,6 +31,9 @@ inline constexpr ::std::size_t deque_block_size_common{static_cast<::std::size_t template <::std::size_t sz> inline constexpr ::std::size_t deque_block_size{sz <= (deque_block_size_common / 16u) ? ::std::bit_ceil(static_cast<::std::size_t>(deque_block_size_common / sz)) : static_cast<::std::size_t>(16u)}; +template <::std::size_t sz> +inline constexpr ::std::size_t deque_block_bytes{sz * ::fast_io::containers::details::deque_block_size}; + struct #if __has_cpp_attribute(__gnu__::__may_alias__) [[__gnu__::__may_alias__]] @@ -1415,14 +1418,57 @@ template concept is_fast_io_deque_iterator_v = ::fast_io::containers::details::is_fast_io_deque_iterator_impl>::value; -template - requires(::fast_io::containers::details::is_fast_io_deque_iterator_v || - ::fast_io::containers::details::is_fast_io_deque_iterator_v) +template + requires((::fast_io::containers::details::is_fast_io_deque_iterator_v || + ::fast_io::containers::details::is_fast_io_deque_iterator_v)) inline constexpr Iter2 uninitialized_relocate_define( - ::fast_io::operations::defines::memory_algorithm_define_type, - Iter1 first, Sentinel last, Iter2 dest) + ::fast_io::operations::defines::memory_algorithm_define_type, + Iter1 first, Iter1 last, Iter2 dest) { + using itvaltype1 = ::std::iter_value_t; + using itvaltype2 = ::std::iter_value_t; + if !consteval + { + if constexpr ( + ::std::same_as && + ::fast_io::freestanding::is_trivially_copyable_or_relocatable_v && + ::fast_io::freestanding::is_trivially_copyable_or_relocatable_v) + { + return ::std::bit_cast( + ::fast_io::containers::details::deque_copy_impl( + ::std::bit_cast<::fast_io::containers::details::deque_control_block_common>(first.itercontent), + ::std::bit_cast<::fast_io::containers::details::deque_control_block_common>(last.itercontent), + ::std::bit_cast<::fast_io::containers::details::deque_control_block_common>(dest.itercontent), + ::fast_io::containers::details::deque_block_bytes)); + } + } + return ::fast_io::freestanding::uninitialized_relocate_ignore_define(first, last, dest); +} +template + requires((::fast_io::containers::details::is_fast_io_deque_iterator_v || + ::fast_io::containers::details::is_fast_io_deque_iterator_v)) +inline constexpr Iter2 uninitialized_relocate_backward_define( + ::fast_io::operations::defines::memory_algorithm_define_type, + Iter1 first, Iter1 last, Iter2 dest) +{ + using itvaltype1 = ::std::iter_value_t; + using itvaltype2 = ::std::iter_value_t; + if !consteval + { + if constexpr ( + ::std::same_as && + ::fast_io::freestanding::is_trivially_copyable_or_relocatable_v && + ::fast_io::freestanding::is_trivially_copyable_or_relocatable_v) + { + return ::std::bit_cast( + ::fast_io::containers::details::deque_copy_backward_impl( + ::std::bit_cast<::fast_io::containers::details::deque_control_block_common>(first.itercontent), + ::std::bit_cast<::fast_io::containers::details::deque_control_block_common>(last.itercontent), + ::std::bit_cast<::fast_io::containers::details::deque_control_block_common>(dest.itercontent), + ::fast_io::containers::details::deque_block_bytes)); + } + } return ::fast_io::freestanding::uninitialized_relocate_ignore_define(first, last, dest); } diff --git a/include/fast_io_dsal/impl/freestanding.h b/include/fast_io_dsal/impl/freestanding.h index 66d55630..84dd3a1b 100644 --- a/include/fast_io_dsal/impl/freestanding.h +++ b/include/fast_io_dsal/impl/freestanding.h @@ -139,8 +139,8 @@ inline constexpr Iter2 uninitialized_relocate(Iter1 first, Snt last, Iter2 dest) } } -template <::std::bidirectional_iterator Iter1, ::std::bidirectional_iterator Iter2> -inline constexpr Iter2 uninitialized_relocate_backward(Iter1 first, Iter1 last, Iter2 dest) noexcept +template <::std::bidirectional_iterator Iter1, ::std::sentinel_for Snt, ::std::bidirectional_iterator Iter2> +inline constexpr Iter2 uninitialized_relocate_backward_ignore_define(Iter1 first, Snt last, Iter2 dest) noexcept { // Semantics: // Relocate the range [first, last) into the uninitialized memory ending at `dest`. @@ -151,22 +151,22 @@ inline constexpr Iter2 uninitialized_relocate_backward(Iter1 first, Iter1 last, if constexpr (::std::contiguous_iterator && !::std::is_pointer_v && ::std::contiguous_iterator && !::std::is_pointer_v) { - return uninitialized_relocate_backward(::std::to_address(first), - ::std::to_address(last), - ::std::to_address(dest)) - + return uninitialized_relocate_backward_ignore_define(::std::to_address(first), + ::std::to_address(last), + ::std::to_address(dest)) - ::std::to_address(dest) + dest; } else if constexpr (::std::contiguous_iterator && !::std::is_pointer_v) { - return uninitialized_relocate_backward(::std::to_address(first), - ::std::to_address(last), - dest); + return uninitialized_relocate_backward_ignore_define(::std::to_address(first), + ::std::to_address(last), + dest); } else if constexpr (::std::contiguous_iterator && !::std::is_pointer_v) { - return uninitialized_relocate_backward(first, - last, - ::std::to_address(dest)) - + return uninitialized_relocate_backward_ignore_define(first, + last, + ::std::to_address(dest)) - ::std::to_address(dest) + dest; } else @@ -204,13 +204,6 @@ inline constexpr Iter2 uninitialized_relocate_backward(Iter1 first, Iter1 last, return reinterpret_cast(destfirst); } } - // Custom relocate_backward hook for user-defined types -#if 0 - else if constexpr (::fast_io::operations::defines::has_uninitialized_relocate_backward_define) - { - return uninitialized_relocate_backward_define(::fast_io::operations::defines::memory_algorithm_define, first, last, dest); - } -#endif // Generic slow path: // Move-construct elements in reverse order into uninitialized memory, // then destroy the original elements. @@ -238,6 +231,52 @@ inline constexpr Iter2 uninitialized_relocate_backward(Iter1 first, Iter1 last, } } +template <::std::bidirectional_iterator Iter1, ::std::sentinel_for Snt, ::std::bidirectional_iterator Iter2> +inline constexpr Iter2 uninitialized_relocate_backward(Iter1 first, Snt last, Iter2 dest) noexcept +{ + // Semantics: + // Relocate the range [first, last) into the uninitialized memory ending at `dest`. + // `dest` is treated as the end iterator (one past the last element) of the destination range. + // The function returns the begin iterator of the destination range: + // dest - (last - first) + + if constexpr (::std::contiguous_iterator && !::std::is_pointer_v && + ::std::contiguous_iterator && !::std::is_pointer_v) + { + return uninitialized_relocate_backward(::std::to_address(first), + ::std::to_address(last), + ::std::to_address(dest)) - + ::std::to_address(dest) + dest; + } + else if constexpr (::std::contiguous_iterator && !::std::is_pointer_v) + { + return uninitialized_relocate_backward(::std::to_address(first), + ::std::to_address(last), + dest); + } + else if constexpr (::std::contiguous_iterator && !::std::is_pointer_v) + { + return uninitialized_relocate_backward(first, + last, + ::std::to_address(dest)) - + ::std::to_address(dest) + dest; + } + else + { + using iter1valuetype = ::std::iter_value_t; + using iter2valuetype = ::std::iter_value_t; + + if constexpr (::fast_io::operations::defines::has_uninitialized_relocate_backward_define) + { + return uninitialized_relocate_backward_define(::fast_io::operations::defines::memory_algorithm_define, first, last, dest); + } + else + { + return ::fast_io::freestanding::uninitialized_relocate_backward_ignore_define(first, last, dest); + } + } +} + template <::std::input_or_output_iterator Iter1, ::std::input_or_output_iterator Iter2> inline constexpr Iter2 uninitialized_move(Iter1 first, Iter1 last, Iter2 dest) noexcept { From cccb2827e81d9b85d771b0e602e1c83787eca072 Mon Sep 17 00:00:00 2001 From: trcrsired Date: Tue, 3 Feb 2026 08:16:36 +0800 Subject: [PATCH 38/42] [deque] implement relocate for all types --- include/fast_io_dsal/impl/deque.h | 185 ++++++++++++++++++++++++++---- 1 file changed, 164 insertions(+), 21 deletions(-) diff --git a/include/fast_io_dsal/impl/deque.h b/include/fast_io_dsal/impl/deque.h index f5417f5b..1bd2045e 100644 --- a/include/fast_io_dsal/impl/deque.h +++ b/include/fast_io_dsal/impl/deque.h @@ -1000,6 +1000,137 @@ deque_copy_backward_impl(Itercontent first, Itercontent last, return dest; } + +template +inline constexpr Itercontent +deque_relocate_impl(Itercontent first, Itercontent last, + Itercontent dest, ::std::size_t blocksize) +{ + if (first.curr_ptr == last.curr_ptr) + { + return dest; + } + for (;;) + { + decltype(first.begin_ptr) firstend; + if (first.controller_ptr == last.controller_ptr) + { + firstend = last.curr_ptr; + } + else + { + firstend = first.begin_ptr + blocksize; + } + auto firstcurrptr{first.curr_ptr}; + ::std::size_t const curr_block_to_end{ + static_cast<::std::size_t>(firstend - firstcurrptr)}; + auto destcurrptr{dest.curr_ptr}; + ::std::size_t const dest_block_to_end{ + static_cast<::std::size_t>(dest.begin_ptr + blocksize - destcurrptr)}; + auto cmp{curr_block_to_end <=> dest_block_to_end}; + ::std::size_t tocopy; + if (cmp < 0) + { + tocopy = curr_block_to_end; + } + else + { + tocopy = dest_block_to_end; + } + ::fast_io::freestanding::uninitialized_relocate_ignore_define(firstcurrptr, firstcurrptr + tocopy, destcurrptr); + if (0 < cmp) + { + dest.curr_ptr = (dest.begin_ptr = (*++dest.controller_ptr)); + first.curr_ptr += tocopy; + } + else + { + if (cmp < 0) + { + dest.curr_ptr += tocopy; + } + else if (cmp == 0) + { + dest.curr_ptr = (dest.begin_ptr = (*++dest.controller_ptr)); + } + if (first.controller_ptr == last.controller_ptr) + { + break; + } + first.curr_ptr = (first.begin_ptr = (*++first.controller_ptr)); + } + } + return dest; +} + +template +inline constexpr Itercontent +deque_relocate_backward_impl(Itercontent first, Itercontent last, + Itercontent dest, ::std::size_t blocksize) +{ + if (first.curr_ptr == last.curr_ptr) + { + return dest; + } + for (;;) + { + decltype(first.begin_ptr) lastbegin; + if (first.controller_ptr == last.controller_ptr) + { + lastbegin = first.curr_ptr; + } + else + { + lastbegin = last.begin_ptr; + } + auto lastcurrptr{last.curr_ptr}; + ::std::size_t const curr_block_to_begin{ + static_cast<::std::size_t>(lastcurrptr - lastbegin)}; + auto destcurrptr{dest.curr_ptr}; + ::std::size_t const dest_block_to_begin{ + static_cast<::std::size_t>(destcurrptr - dest.begin_ptr)}; + auto cmp{curr_block_to_begin <=> dest_block_to_begin}; + ::std::size_t tocopy; + if (cmp < 0) + { + tocopy = curr_block_to_begin; + } + else + { + tocopy = dest_block_to_begin; + } + ::fast_io::freestanding::uninitialized_relocate_backward_ignore_define(lastcurrptr - tocopy, lastcurrptr, + destcurrptr); + if (0 < cmp) + { + dest.curr_ptr = (dest.begin_ptr = (*--dest.controller_ptr)) + blocksize; + last.curr_ptr -= tocopy; + } + else + { + if (cmp == 0) + { + if (last.controller_ptr == first.controller_ptr) + { + dest.curr_ptr = dest.begin_ptr; + break; + } + dest.curr_ptr = (dest.begin_ptr = (*--dest.controller_ptr)) + blocksize; + } + else + { + dest.curr_ptr -= tocopy; + if (last.controller_ptr == first.controller_ptr) + { + break; + } + } + last.curr_ptr = (last.begin_ptr = (*--last.controller_ptr)) + blocksize; + } + } + return dest; +} + inline ::fast_io::containers::details::deque_control_block_common deque_erase_common_trivial_impl(::fast_io::containers::details::deque_controller_common &controller, ::fast_io::containers::details::deque_control_block_common first, @@ -1429,17 +1560,23 @@ inline constexpr Iter2 uninitialized_relocate_define( using itvaltype2 = ::std::iter_value_t; if !consteval { - if constexpr ( - ::std::same_as && - ::fast_io::freestanding::is_trivially_copyable_or_relocatable_v && - ::fast_io::freestanding::is_trivially_copyable_or_relocatable_v) + if constexpr (::std::same_as) { - return ::std::bit_cast( - ::fast_io::containers::details::deque_copy_impl( - ::std::bit_cast<::fast_io::containers::details::deque_control_block_common>(first.itercontent), - ::std::bit_cast<::fast_io::containers::details::deque_control_block_common>(last.itercontent), - ::std::bit_cast<::fast_io::containers::details::deque_control_block_common>(dest.itercontent), - ::fast_io::containers::details::deque_block_bytes)); + if constexpr (::fast_io::freestanding::is_trivially_copyable_or_relocatable_v) + { + return ::std::bit_cast( + ::fast_io::containers::details::deque_copy_impl( + ::std::bit_cast<::fast_io::containers::details::deque_control_block_common>(first.itercontent), + ::std::bit_cast<::fast_io::containers::details::deque_control_block_common>(last.itercontent), + ::std::bit_cast<::fast_io::containers::details::deque_control_block_common>(dest.itercontent), + ::fast_io::containers::details::deque_block_bytes)); + } + else + { + return ::std::bit_cast( + ::fast_io::containers::details::deque_relocate_impl(first.itercontent, last.itercontent, dest.itercontent, + ::fast_io::containers::details::deque_block_size)); + } } } return ::fast_io::freestanding::uninitialized_relocate_ignore_define(first, last, dest); @@ -1456,20 +1593,26 @@ inline constexpr Iter2 uninitialized_relocate_backward_define( using itvaltype2 = ::std::iter_value_t; if !consteval { - if constexpr ( - ::std::same_as && - ::fast_io::freestanding::is_trivially_copyable_or_relocatable_v && - ::fast_io::freestanding::is_trivially_copyable_or_relocatable_v) + if constexpr (::std::same_as) { - return ::std::bit_cast( - ::fast_io::containers::details::deque_copy_backward_impl( - ::std::bit_cast<::fast_io::containers::details::deque_control_block_common>(first.itercontent), - ::std::bit_cast<::fast_io::containers::details::deque_control_block_common>(last.itercontent), - ::std::bit_cast<::fast_io::containers::details::deque_control_block_common>(dest.itercontent), - ::fast_io::containers::details::deque_block_bytes)); + if constexpr (::fast_io::freestanding::is_trivially_copyable_or_relocatable_v) + { + return ::std::bit_cast( + ::fast_io::containers::details::deque_copy_backward_impl( + ::std::bit_cast<::fast_io::containers::details::deque_control_block_common>(first.itercontent), + ::std::bit_cast<::fast_io::containers::details::deque_control_block_common>(last.itercontent), + ::std::bit_cast<::fast_io::containers::details::deque_control_block_common>(dest.itercontent), + ::fast_io::containers::details::deque_block_bytes)); + } + else + { + return ::std::bit_cast( + ::fast_io::containers::details::deque_relocate_backward_impl(first.itercontent, last.itercontent, dest.itercontent, + ::fast_io::containers::details::deque_block_size)); + } } } - return ::fast_io::freestanding::uninitialized_relocate_ignore_define(first, last, dest); + return ::fast_io::freestanding::uninitialized_relocate_backward_ignore_define(first, last, dest); } } // namespace details From ec94df7613296cd2bac5b7e923aac8d6a4514973 Mon Sep 17 00:00:00 2001 From: trcrsired Date: Tue, 3 Feb 2026 08:31:15 +0800 Subject: [PATCH 39/42] avoid invoking ~ for uninitialized_copy_n since msvc would complain --- .../freestanding/algorithm.h | 7 +- include/fast_io_dsal/impl/deque.h | 86 ++++++++----------- include/fast_io_dsal/impl/freestanding.h | 5 -- 3 files changed, 39 insertions(+), 59 deletions(-) diff --git a/include/fast_io_core_impl/freestanding/algorithm.h b/include/fast_io_core_impl/freestanding/algorithm.h index 63be6f23..cd64e6e0 100644 --- a/include/fast_io_core_impl/freestanding/algorithm.h +++ b/include/fast_io_core_impl/freestanding/algorithm.h @@ -775,9 +775,12 @@ uninitialized_copy_n(InputIt first, ::std::size_t n, NoThrowForwardIt d_first) n NoThrowForwardIt current; inline constexpr ~destroyer() noexcept { - for (; d_first != current; ++d_first) + if constexpr (!::std::is_trivially_destructible_v) { - d_first->~T(); + for (; d_first != current; ++d_first) + { + d_first->~T(); + } } } }; diff --git a/include/fast_io_dsal/impl/deque.h b/include/fast_io_dsal/impl/deque.h index 1bd2045e..b9f113de 100644 --- a/include/fast_io_dsal/impl/deque.h +++ b/include/fast_io_dsal/impl/deque.h @@ -1549,70 +1549,52 @@ template concept is_fast_io_deque_iterator_v = ::fast_io::containers::details::is_fast_io_deque_iterator_impl>::value; -template - requires((::fast_io::containers::details::is_fast_io_deque_iterator_v || - ::fast_io::containers::details::is_fast_io_deque_iterator_v)) -inline constexpr Iter2 uninitialized_relocate_define( - ::fast_io::operations::defines::memory_algorithm_define_type, - Iter1 first, Iter1 last, Iter2 dest) +template + requires(::fast_io::containers::details::is_fast_io_deque_iterator_v) +inline constexpr Iter uninitialized_relocate_define( + ::fast_io::operations::defines::memory_algorithm_define_type, + Iter first, Iter last, Iter dest) { - using itvaltype1 = ::std::iter_value_t; - using itvaltype2 = ::std::iter_value_t; - if !consteval + using valtype = ::std::iter_value_t; + if constexpr (::fast_io::freestanding::is_trivially_copyable_or_relocatable_v) { - if constexpr (::std::same_as) + if !consteval { - if constexpr (::fast_io::freestanding::is_trivially_copyable_or_relocatable_v) - { - return ::std::bit_cast( - ::fast_io::containers::details::deque_copy_impl( - ::std::bit_cast<::fast_io::containers::details::deque_control_block_common>(first.itercontent), - ::std::bit_cast<::fast_io::containers::details::deque_control_block_common>(last.itercontent), - ::std::bit_cast<::fast_io::containers::details::deque_control_block_common>(dest.itercontent), - ::fast_io::containers::details::deque_block_bytes)); - } - else - { - return ::std::bit_cast( - ::fast_io::containers::details::deque_relocate_impl(first.itercontent, last.itercontent, dest.itercontent, - ::fast_io::containers::details::deque_block_size)); - } + return ::std::bit_cast( + ::fast_io::containers::details::deque_copy_impl( + ::std::bit_cast<::fast_io::containers::details::deque_control_block_common>(first.itercontent), + ::std::bit_cast<::fast_io::containers::details::deque_control_block_common>(last.itercontent), + ::std::bit_cast<::fast_io::containers::details::deque_control_block_common>(dest.itercontent), + ::fast_io::containers::details::deque_block_bytes)); } } - return ::fast_io::freestanding::uninitialized_relocate_ignore_define(first, last, dest); + return ::std::bit_cast( + ::fast_io::containers::details::deque_relocate_impl(first.itercontent, last.itercontent, dest.itercontent, + ::fast_io::containers::details::deque_block_size)); } -template - requires((::fast_io::containers::details::is_fast_io_deque_iterator_v || - ::fast_io::containers::details::is_fast_io_deque_iterator_v)) -inline constexpr Iter2 uninitialized_relocate_backward_define( - ::fast_io::operations::defines::memory_algorithm_define_type, - Iter1 first, Iter1 last, Iter2 dest) +template + requires(::fast_io::containers::details::is_fast_io_deque_iterator_v) +inline constexpr Iter uninitialized_relocate_backward_define( + ::fast_io::operations::defines::memory_algorithm_define_type, + Iter first, Iter last, Iter dest) { - using itvaltype1 = ::std::iter_value_t; - using itvaltype2 = ::std::iter_value_t; - if !consteval + using valtype = ::std::iter_value_t; + if constexpr (::fast_io::freestanding::is_trivially_copyable_or_relocatable_v) { - if constexpr (::std::same_as) + if !consteval { - if constexpr (::fast_io::freestanding::is_trivially_copyable_or_relocatable_v) - { - return ::std::bit_cast( - ::fast_io::containers::details::deque_copy_backward_impl( - ::std::bit_cast<::fast_io::containers::details::deque_control_block_common>(first.itercontent), - ::std::bit_cast<::fast_io::containers::details::deque_control_block_common>(last.itercontent), - ::std::bit_cast<::fast_io::containers::details::deque_control_block_common>(dest.itercontent), - ::fast_io::containers::details::deque_block_bytes)); - } - else - { - return ::std::bit_cast( - ::fast_io::containers::details::deque_relocate_backward_impl(first.itercontent, last.itercontent, dest.itercontent, - ::fast_io::containers::details::deque_block_size)); - } + return ::std::bit_cast( + ::fast_io::containers::details::deque_copy_backward_impl( + ::std::bit_cast<::fast_io::containers::details::deque_control_block_common>(first.itercontent), + ::std::bit_cast<::fast_io::containers::details::deque_control_block_common>(last.itercontent), + ::std::bit_cast<::fast_io::containers::details::deque_control_block_common>(dest.itercontent), + ::fast_io::containers::details::deque_block_bytes)); } } - return ::fast_io::freestanding::uninitialized_relocate_backward_ignore_define(first, last, dest); + return ::std::bit_cast( + ::fast_io::containers::details::deque_relocate_backward_impl(first.itercontent, last.itercontent, dest.itercontent, + ::fast_io::containers::details::deque_block_size)); } } // namespace details diff --git a/include/fast_io_dsal/impl/freestanding.h b/include/fast_io_dsal/impl/freestanding.h index 84dd3a1b..cbd9bd84 100644 --- a/include/fast_io_dsal/impl/freestanding.h +++ b/include/fast_io_dsal/impl/freestanding.h @@ -126,8 +126,6 @@ inline constexpr Iter2 uninitialized_relocate(Iter1 first, Snt last, Iter2 dest) } else { - using iter1valuetype = ::std::iter_value_t; - using iter2valuetype = ::std::iter_value_t; if constexpr (::fast_io::operations::defines::has_uninitialized_relocate_define) { return uninitialized_relocate_define(::fast_io::operations::defines::memory_algorithm_define, first, last, dest); @@ -263,9 +261,6 @@ inline constexpr Iter2 uninitialized_relocate_backward(Iter1 first, Snt last, It } else { - using iter1valuetype = ::std::iter_value_t; - using iter2valuetype = ::std::iter_value_t; - if constexpr (::fast_io::operations::defines::has_uninitialized_relocate_backward_define) { return uninitialized_relocate_backward_define(::fast_io::operations::defines::memory_algorithm_define, first, last, dest); From 6d003fe65dbe2e10dcc56c5e662aea4053ae8923 Mon Sep 17 00:00:00 2001 From: trcrsired Date: Tue, 3 Feb 2026 08:42:25 +0800 Subject: [PATCH 40/42] remove unused variable for startpos --- include/fast_io_dsal/impl/deque.h | 2 -- 1 file changed, 2 deletions(-) diff --git a/include/fast_io_dsal/impl/deque.h b/include/fast_io_dsal/impl/deque.h index b9f113de..1ced898e 100644 --- a/include/fast_io_dsal/impl/deque.h +++ b/include/fast_io_dsal/impl/deque.h @@ -1372,7 +1372,6 @@ inline constexpr void deque_reserve_back_spaces(dequecontroltype &controller, :: { return; } - ::std::size_t startpos{static_cast<::std::size_t>(back_curr_ptr - controller.back_block.begin_ptr)}; ::std::size_t nmblocksn{n - blocksn}; ::std::size_t back_more_blocks{nmblocksn / block_size}; ::std::size_t const back_more_blocks_mod{nmblocksn % block_size}; @@ -1483,7 +1482,6 @@ inline constexpr void deque_reserve_front_spaces(dequecontroltype &controller, : { return; } - ::std::size_t startpos{static_cast<::std::size_t>(controller.front_end_ptr - front_curr_ptr)}; ::std::size_t nmblocksn{n - blocksn}; ::std::size_t front_more_blocks{nmblocksn / block_size}; ::std::size_t const front_more_blocks_mod{nmblocksn % block_size}; From 8fbbc43d8fd87ce5d93b28383be01d11ceedc44a Mon Sep 17 00:00:00 2001 From: trcrsired Date: Tue, 3 Feb 2026 08:52:32 +0800 Subject: [PATCH 41/42] .test_prop --- benchmark/0011.containers/deque/.test_prop.toml | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 benchmark/0011.containers/deque/.test_prop.toml diff --git a/benchmark/0011.containers/deque/.test_prop.toml b/benchmark/0011.containers/deque/.test_prop.toml new file mode 100644 index 00000000..c19ff243 --- /dev/null +++ b/benchmark/0011.containers/deque/.test_prop.toml @@ -0,0 +1,2 @@ +["0003.insert_range"] +ignore = true From 84763e78f0b0b2820993e27bb7c237fc61309e26 Mon Sep 17 00:00:00 2001 From: trcrsired Date: Tue, 10 Feb 2026 00:02:52 +0800 Subject: [PATCH 42/42] update module to it compiles successfully on wasm remove threading junk --- share/fast_io/fast_io.cppm | 6 +++--- share/fast_io/fast_io_inc/hosted.inc | 21 +++++++------------ .../fast_io_inc/{host => hosted}/nt.inc | 0 .../fast_io_inc/{host => hosted}/posix.inc | 3 +-- .../fast_io_inc/{host => hosted}/win32.inc | 2 +- 5 files changed, 12 insertions(+), 20 deletions(-) rename share/fast_io/fast_io_inc/{host => hosted}/nt.inc (100%) rename share/fast_io/fast_io_inc/{host => hosted}/posix.inc (95%) rename share/fast_io/fast_io_inc/{host => hosted}/win32.inc (99%) diff --git a/share/fast_io/fast_io.cppm b/share/fast_io/fast_io.cppm index 594f9aa4..2f6dacb6 100644 --- a/share/fast_io/fast_io.cppm +++ b/share/fast_io/fast_io.cppm @@ -28,11 +28,11 @@ export module fast_io; #ifndef FAST_IO_FREESTANDING #include "fast_io_inc/hosted.inc" -#include "fast_io_inc/host/posix.inc" +#include "fast_io_inc/hosted/posix.inc" #if defined(_WIN32) || defined(__CYGWIN__) -#include "fast_io_inc/host/nt.inc" -#include "fast_io_inc/host/win32.inc" +#include "fast_io_inc/hosted/nt.inc" +#include "fast_io_inc/hosted/win32.inc" #endif #include "fast_io_inc/legacy/c.inc" diff --git a/share/fast_io/fast_io_inc/hosted.inc b/share/fast_io/fast_io_inc/hosted.inc index 2201e2d5..a40e2241 100644 --- a/share/fast_io/fast_io_inc/hosted.inc +++ b/share/fast_io/fast_io_inc/hosted.inc @@ -128,18 +128,6 @@ using ::fast_io::posix_clock_getres; using ::fast_io::native_mutex; -using ::fast_io::native_socklen_t; - -namespace this_thread -{ -#if ((defined(_WIN32) && !defined(__WINE__)) && !defined(__CYGWIN__)) || (defined(__MSDOS__) || defined(__DJGPP__)) || defined(__wasi__) || (!defined(__SINGLE_THREAD__) && !defined(__NEWLIB__) && !defined(__MSDOS__) && __has_include()) -using ::fast_io::this_thread::get_id; -using ::fast_io::this_thread::sleep_for; -using ::fast_io::this_thread::sleep_until; -using ::fast_io::this_thread::yield; -#endif -} // namespace this_thread - using ::fast_io::native_readlinkat; using ::fast_io::native_symlinkat; using ::fast_io::native_unlinkat; @@ -150,10 +138,13 @@ using ::fast_io::native_at_flags; using ::fast_io::native_utimensat; using ::fast_io::native_linkat; +#ifndef __wasm__ +using ::fast_io::native_socklen_t; using ::fast_io::posix_accept; using ::fast_io::posix_connect; using ::fast_io::posix_bind; using ::fast_io::posix_listen; +#endif using ::fast_io::begin; using ::fast_io::end; @@ -170,15 +161,17 @@ using ::fast_io::posix_file_status; using ::fast_io::truncate; using ::fast_io::native_white_hole; -using ::fast_io::native_socket_file; -using ::fast_io::native_socket_io_observer; using ::fast_io::ipv4; using ::fast_io::ipv6; +#ifndef __wasm__ +using ::fast_io::native_socket_file; +using ::fast_io::native_socket_io_observer; using ::fast_io::native_dns_file; using ::fast_io::to_ip; using ::fast_io::to_ip_address; +#endif using ::fast_io::io_kernel; diff --git a/share/fast_io/fast_io_inc/host/nt.inc b/share/fast_io/fast_io_inc/hosted/nt.inc similarity index 100% rename from share/fast_io/fast_io_inc/host/nt.inc rename to share/fast_io/fast_io_inc/hosted/nt.inc diff --git a/share/fast_io/fast_io_inc/host/posix.inc b/share/fast_io/fast_io_inc/hosted/posix.inc similarity index 95% rename from share/fast_io/fast_io_inc/host/posix.inc rename to share/fast_io/fast_io_inc/hosted/posix.inc index 0ab9324a..f7afad8f 100644 --- a/share/fast_io/fast_io_inc/host/posix.inc +++ b/share/fast_io/fast_io_inc/hosted/posix.inc @@ -6,7 +6,7 @@ export namespace fast_io using ::fast_io::posix_stderr_number; using ::fast_io::posix_domain_value; -#if ((!defined(_WIN32) || defined(__WINE__)) || defined(__CYGWIN__)) +#if ((!defined(_WIN32) || defined(__WINE__)) || defined(__CYGWIN__)) && !defined(__wasm__) namespace posix { using ::fast_io::posix::libc_ioctl; @@ -18,7 +18,6 @@ export namespace fast_io using ::fast_io::details::sys_mprotect; using ::fast_io::details::sys_munmap; using ::fast_io::details::sys_munmap_nothrow; - } using ::fast_io::posix_socklen_t; diff --git a/share/fast_io/fast_io_inc/host/win32.inc b/share/fast_io/fast_io_inc/hosted/win32.inc similarity index 99% rename from share/fast_io/fast_io_inc/host/win32.inc rename to share/fast_io/fast_io_inc/hosted/win32.inc index 1f08c09d..4972cd0e 100644 --- a/share/fast_io/fast_io_inc/host/win32.inc +++ b/share/fast_io/fast_io_inc/hosted/win32.inc @@ -61,4 +61,4 @@ export namespace fast_io using ::fast_io::data_sync_flags; using ::fast_io::data_sync; u using ::fast_io::flush; -} \ No newline at end of file +}