Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion benchmark/0011.containers/deque/0001.push_back/fast_io.cc
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ int main()
for (auto const e : deq)
{
sum += e;
}
}
}
::fast_io::io::perrln("sum=",sum);
}
26 changes: 26 additions & 0 deletions benchmark/0011.containers/deque/0001.push_back/fast_io_reverse.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
#include <fast_io.h>
#include <fast_io_driver/timer.h>
#include <fast_io_dsal/deque.h>

int main()
{
fast_io::timer tm(u8"fast_io::deque reverse");
fast_io::deque<std::size_t> 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"loop reverse");
for (auto const e : ::std::ranges::reverse_view(deq))
{
sum += e;
}
}
::fast_io::io::perrln("sum=",sum);
}
153 changes: 153 additions & 0 deletions fuzzing/0007.containers/deque/fuzz_deque_erase.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,153 @@
// deque_erase_fuzz.cc
#include <cstddef>
#include <cstdint>
#include <deque>
#include <vector>

#include <source_location>
#include <fast_io.h>
#include <fast_io_dsal/deque.h>

using T = std::size_t;

// Check equality between fast_io::deque and std::deque
static void check_equal(::fast_io::deque<T> const &dq,
::std::deque<T> const &ref)
{
if (dq.size() != ref.size())
{
__builtin_trap(); // mismatch: size
}

for (std::size_t i{}; i != dq.size(); ++i)
{
if (dq[i] != ref[i])
{
__builtin_trap(); // mismatch: value
}
}
}

// Map a byte to an operation kind
enum class OpKind : uint8_t
{
PushBack = 0,
PushFront = 1,
EraseIndex = 2,
EraseRangeIter = 3,
// you can add more later
};

extern "C" int LLVMFuzzerTestOneInput(uint8_t const *data, std::size_t size)
{
::fast_io::deque<T> dq;
::std::deque<T> ref;

// We interpret the input as a stream of small commands.
// Each command may consume 1~3 bytes depending on the op.
std::size_t i = 0;
while (i < size)
{
uint8_t op_raw = data[i++] % 4; // we currently have 4 ops
OpKind op = static_cast<OpKind>(op_raw);

switch (op)
{
case OpKind::PushBack:
{
if (i >= size)
{
break;
}
// use the next byte as low bits of the value
T v = static_cast<T>(data[i++]);
dq.push_back(v);
ref.push_back(v);
break;
}
case OpKind::PushFront:
{
if (i >= size)
{
break;
}
T v = static_cast<T>(data[i++]);
dq.push_front(v);
ref.push_front(v);
break;
}
case OpKind::EraseIndex:
{
if (dq.empty())
{
break;
}

if (i >= size)
{
break;
}
std::size_t pos = static_cast<std::size_t>(data[i++]);
if (!dq.empty())
{
pos %= dq.size();
dq.erase_index(pos);
ref.erase(ref.begin() + static_cast<std::ptrdiff_t>(pos));
}
break;
}
case OpKind::EraseRangeIter:
{
if (dq.empty())
{
break;
}

if (i + 1 > size) // need at least 1 byte
{
break;
}

std::size_t n = dq.size();
if (n == 0)
{
break;
}

// choose two indices from bytes
std::size_t a = static_cast<std::size_t>(data[i++]) % n;
std::size_t b = static_cast<std::size_t>(data[i++ % size]) % (n + 1);

std::size_t first_idx = (a < b ? a : b);
std::size_t last_idx = (a < b ? b : a);

if (last_idx > n)
{
last_idx = n;
}
if (first_idx > last_idx)
{
first_idx = last_idx;
}
if (first_idx == last_idx)
{
break; // empty range, skip
}

auto dq_first = dq.begin() + static_cast<std::ptrdiff_t>(first_idx);
auto dq_last = dq.begin() + static_cast<std::ptrdiff_t>(last_idx);
auto ref_first = ref.begin() + static_cast<std::ptrdiff_t>(first_idx);
auto ref_last = ref.begin() + static_cast<std::ptrdiff_t>(last_idx);

dq.erase(dq_first, dq_last);
ref.erase(ref_first, ref_last);
break;
}
}

// After each operation, verify dq == ref
check_equal(dq, ref);
}

return 0;
}
9 changes: 9 additions & 0 deletions include/fast_io_core_impl/integers/impl.h
Original file line number Diff line number Diff line change
Expand Up @@ -617,6 +617,15 @@ inline constexpr auto pointervw(scalar_type t) noexcept
::fast_io::details::base_mani_flags_cache<16, uppercase, true, true, false>>(t);
}

template <bool uppercase = false, typename scalar_type>
requires((::std::is_pointer_v<scalar_type> || ::std::contiguous_iterator<scalar_type>) &&
(!::std::is_function_v<::std::remove_cvref_t<scalar_type>>))
inline constexpr auto itervw(scalar_type t) noexcept
{
return ::fast_io::details::scalar_flags_int_cache<
::fast_io::details::base_mani_flags_cache<16, uppercase, true, true, false>>(t);
}

template <bool uppercase = false, typename scalar_type>
requires(::std::is_function_v<scalar_type>)
inline constexpr auto funcvw(scalar_type *t) noexcept
Expand Down
Loading