summaryrefslogtreecommitdiffhomepage
path: root/misc
diff options
context:
space:
mode:
Diffstat (limited to 'misc')
-rw-r--r--misc/benchmarks/external/ankerl/unordered_dense.h418
-rw-r--r--misc/benchmarks/external/emhash/hash_table7.hpp44
-rw-r--r--misc/benchmarks/plotbench/cdeq_benchmark.cpp2
-rw-r--r--misc/benchmarks/plotbench/cpque_benchmark.cpp2
-rw-r--r--misc/benchmarks/plotbench/cvec_benchmark.cpp2
-rw-r--r--misc/benchmarks/plotbench/plot.py4
-rw-r--r--misc/benchmarks/plotbench/run_clang.sh10
-rw-r--r--misc/benchmarks/plotbench/run_gcc.sh10
-rw-r--r--misc/benchmarks/shootout_hashmaps.cpp4
-rw-r--r--misc/benchmarks/various/csort_bench.c46
-rw-r--r--misc/benchmarks/various/cspan_bench.c34
-rw-r--r--misc/benchmarks/various/rust_cmap.c2
-rw-r--r--misc/benchmarks/various/sso_bench.cpp156
-rw-r--r--misc/benchmarks/various/string_bench_STC.cpp7
-rw-r--r--misc/benchmarks/various/string_bench_STD.cpp3
-rw-r--r--misc/examples/arc_containers.c17
-rw-r--r--misc/examples/arc_demo.c22
-rw-r--r--misc/examples/arcvec_erase.c12
-rw-r--r--misc/examples/astar.c7
-rw-r--r--misc/examples/birthday.c6
-rw-r--r--misc/examples/bits2.c2
-rw-r--r--misc/examples/books.c3
-rw-r--r--misc/examples/box.c9
-rw-r--r--misc/examples/box2.c14
-rw-r--r--misc/examples/cointerleave.c62
-rw-r--r--misc/examples/complex.c13
-rw-r--r--misc/examples/convert.c10
-rw-r--r--misc/examples/coread.c34
-rw-r--r--misc/examples/coroutines.c118
-rw-r--r--misc/examples/csmap_erase.c5
-rw-r--r--misc/examples/csmap_find.c20
-rw-r--r--misc/examples/csmap_insert.c19
-rw-r--r--misc/examples/csset_erase.c6
-rw-r--r--misc/examples/cstr_match.c3
-rw-r--r--misc/examples/demos.c26
-rw-r--r--misc/examples/dining_philosophers.c105
-rw-r--r--misc/examples/forfilter.c12
-rw-r--r--misc/examples/forloops.c8
-rw-r--r--misc/examples/functor.c39
-rw-r--r--misc/examples/gauss2.c7
-rw-r--r--misc/examples/generator.c48
-rw-r--r--misc/examples/hashmap.c1
-rw-r--r--misc/examples/inits.c16
-rw-r--r--misc/examples/intrusive.c7
-rw-r--r--misc/examples/list.c7
-rw-r--r--misc/examples/list_erase.c6
-rw-r--r--misc/examples/list_splice.c9
-rw-r--r--misc/examples/lower_bound.c11
-rwxr-xr-xmisc/examples/make.sh19
-rw-r--r--misc/examples/mapmap.c2
-rw-r--r--misc/examples/mmap.c5
-rw-r--r--misc/examples/multidim.c5
-rw-r--r--misc/examples/multimap.c5
-rw-r--r--misc/examples/music_arc.c17
-rw-r--r--misc/examples/new_list.c44
-rw-r--r--misc/examples/new_map.c15
-rw-r--r--misc/examples/new_pque.c8
-rw-r--r--misc/examples/new_queue.c8
-rw-r--r--misc/examples/new_smap.c9
-rw-r--r--misc/examples/new_sptr.c18
-rw-r--r--misc/examples/new_vec.c23
-rw-r--r--misc/examples/person_arc.c10
-rw-r--r--misc/examples/phonebook.c4
-rw-r--r--misc/examples/prime.c9
-rw-r--r--misc/examples/printspan.c33
-rw-r--r--misc/examples/priority.c4
-rw-r--r--misc/examples/queue.c2
-rw-r--r--misc/examples/random.c14
-rw-r--r--misc/examples/rawptr_elements.c6
-rw-r--r--misc/examples/read.c8
-rw-r--r--misc/examples/regex1.c2
-rw-r--r--misc/examples/regex2.c6
-rw-r--r--misc/examples/regex_match.c11
-rw-r--r--misc/examples/regex_replace.c6
-rw-r--r--misc/examples/replace.c3
-rw-r--r--misc/examples/scheduler.c74
-rw-r--r--misc/examples/shape.c16
-rw-r--r--misc/examples/sidebyside.cpp2
-rw-r--r--misc/examples/sorted_map.c4
-rw-r--r--misc/examples/splitstr.c5
-rw-r--r--misc/examples/sso_map.c3
-rw-r--r--misc/examples/sso_substr.c4
-rw-r--r--misc/examples/stack.c6
-rw-r--r--misc/examples/sview_split.c4
-rw-r--r--misc/examples/triples.c55
-rw-r--r--misc/examples/unordered_set.c3
-rw-r--r--misc/examples/utf8replace_c.c3
-rw-r--r--misc/examples/vikings.c13
-rw-r--r--misc/tests/cregex_test.c21
-rw-r--r--misc/tests/cspan_test.c31
90 files changed, 1322 insertions, 646 deletions
diff --git a/misc/benchmarks/external/ankerl/unordered_dense.h b/misc/benchmarks/external/ankerl/unordered_dense.h
index faad051d..b8cacea7 100644
--- a/misc/benchmarks/external/ankerl/unordered_dense.h
+++ b/misc/benchmarks/external/ankerl/unordered_dense.h
@@ -1,7 +1,7 @@
///////////////////////// ankerl::unordered_dense::{map, set} /////////////////////////
// A fast & densely stored hashmap and hashset based on robin-hood backward shift deletion.
-// Version 3.1.0
+// Version 4.0.1
// https://github.com/martinus/unordered_dense
//
// Licensed under the MIT License <http://opensource.org/licenses/MIT>.
@@ -30,12 +30,15 @@
#define ANKERL_UNORDERED_DENSE_H
// see https://semver.org/spec/v2.0.0.html
-#define ANKERL_UNORDERED_DENSE_VERSION_MAJOR 3 // NOLINT(cppcoreguidelines-macro-usage) incompatible API changes
-#define ANKERL_UNORDERED_DENSE_VERSION_MINOR 1 // NOLINT(cppcoreguidelines-macro-usage) backwards compatible functionality
-#define ANKERL_UNORDERED_DENSE_VERSION_PATCH 0 // NOLINT(cppcoreguidelines-macro-usage) backwards compatible bug fixes
+#define ANKERL_UNORDERED_DENSE_VERSION_MAJOR 4 // NOLINT(cppcoreguidelines-macro-usage) incompatible API changes
+#define ANKERL_UNORDERED_DENSE_VERSION_MINOR 0 // NOLINT(cppcoreguidelines-macro-usage) backwards compatible functionality
+#define ANKERL_UNORDERED_DENSE_VERSION_PATCH 1 // NOLINT(cppcoreguidelines-macro-usage) backwards compatible bug fixes
// API versioning with inline namespace, see https://www.foonathan.net/2018/11/inline-namespaces/
+
+// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
#define ANKERL_UNORDERED_DENSE_VERSION_CONCAT1(major, minor, patch) v##major##_##minor##_##patch
+// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
#define ANKERL_UNORDERED_DENSE_VERSION_CONCAT(major, minor, patch) ANKERL_UNORDERED_DENSE_VERSION_CONCAT1(major, minor, patch)
#define ANKERL_UNORDERED_DENSE_NAMESPACE \
ANKERL_UNORDERED_DENSE_VERSION_CONCAT( \
@@ -57,9 +60,9 @@
// exceptions
#if defined(__cpp_exceptions) || defined(__EXCEPTIONS) || defined(_CPPUNWIND)
-# define ANKERL_UNORDERED_DENSE_HAS_EXCEPTIONS() 1
+# define ANKERL_UNORDERED_DENSE_HAS_EXCEPTIONS() 1 // NOLINT(cppcoreguidelines-macro-usage)
#else
-# define ANKERL_UNORDERED_DENSE_HAS_EXCEPTIONS() 0
+# define ANKERL_UNORDERED_DENSE_HAS_EXCEPTIONS() 0 // NOLINT(cppcoreguidelines-macro-usage)
#endif
#ifdef _MSC_VER
# define ANKERL_UNORDERED_DENSE_NOINLINE __declspec(noinline)
@@ -89,20 +92,13 @@
# include <cstdlib> // for abort
# endif
-# define ANKERL_UNORDERED_DENSE_PMR 0 // NOLINT(cppcoreguidelines-macro-usage)
# if defined(__has_include)
# if __has_include(<memory_resource>)
-# undef ANKERL_UNORDERED_DENSE_PMR
-# define ANKERL_UNORDERED_DENSE_PMR 1 // NOLINT(cppcoreguidelines-macro-usage)
-# define ANKERL_UNORDERED_DENSE_PMR_ALLOCATOR \
- std::pmr::polymorphic_allocator // NOLINT(cppcoreguidelines-macro-usage)
-# include <memory_resource> // for polymorphic_allocator
+# define ANKERL_UNORDERED_DENSE_PMR std::pmr // NOLINT(cppcoreguidelines-macro-usage)
+# include <memory_resource> // for polymorphic_allocator
# elif __has_include(<experimental/memory_resource>)
-# undef ANKERL_UNORDERED_DENSE_PMR
-# define ANKERL_UNORDERED_DENSE_PMR 1 // NOLINT(cppcoreguidelines-macro-usage)
-# define ANKERL_UNORDERED_DENSE_PMR_ALLOCATOR \
- std::experimental::pmr::polymorphic_allocator // NOLINT(cppcoreguidelines-macro-usage)
-# include <experimental/memory_resource> // for polymorphic_allocator
+# define ANKERL_UNORDERED_DENSE_PMR std::experimental::pmr // NOLINT(cppcoreguidelines-macro-usage)
+# include <experimental/memory_resource> // for polymorphic_allocator
# endif
# endif
@@ -428,7 +424,7 @@ constexpr bool is_map_v = !std::is_void_v<Mapped>;
// clang-format off
template <typename Hash, typename KeyEqual>
-constexpr bool is_transparent_v = is_detected_v<detect_is_transparent, Hash>&& is_detected_v<detect_is_transparent, KeyEqual>;
+constexpr bool is_transparent_v = is_detected_v<detect_is_transparent, Hash> && is_detected_v<detect_is_transparent, KeyEqual>;
// clang-format on
template <typename From, typename To1, typename To2>
@@ -446,19 +442,320 @@ struct base_table_type_map {
// base type for set doesn't have mapped_type
struct base_table_type_set {};
+} // namespace detail
+
+// Very much like std::deque, but faster for indexing (in most cases). As of now this doesn't implement the full std::vector
+// API, but merely what's necessary to work as an underlying container for ankerl::unordered_dense::{map, set}.
+// It allocates blocks of equal size and puts them into the m_blocks vector. That means it can grow simply by adding a new
+// block to the back of m_blocks, and doesn't double its size like an std::vector. The disadvantage is that memory is not
+// linear and thus there is one more indirection necessary for indexing.
+template <typename T, typename Allocator = std::allocator<T>, size_t MaxSegmentSizeBytes = 4096>
+class segmented_vector {
+ template <bool IsConst>
+ class iter_t;
+
+public:
+ using allocator_type = Allocator;
+ using pointer = typename std::allocator_traits<allocator_type>::pointer;
+ using const_pointer = typename std::allocator_traits<allocator_type>::const_pointer;
+ using difference_type = typename std::allocator_traits<allocator_type>::difference_type;
+ using value_type = T;
+ using size_type = std::size_t;
+ using reference = T&;
+ using const_reference = T const&;
+ using iterator = iter_t<false>;
+ using const_iterator = iter_t<true>;
+
+private:
+ using vec_alloc = typename std::allocator_traits<Allocator>::template rebind_alloc<pointer>;
+ std::vector<pointer, vec_alloc> m_blocks{};
+ size_t m_size{};
+
+ // Calculates the maximum number for x in (s << x) <= max_val
+ static constexpr auto num_bits_closest(size_t max_val, size_t s) -> size_t {
+ auto f = size_t{0};
+ while (s << (f + 1) <= max_val) {
+ ++f;
+ }
+ return f;
+ }
+
+ using self_t = segmented_vector<T, Allocator, MaxSegmentSizeBytes>;
+ static constexpr auto num_bits = num_bits_closest(MaxSegmentSizeBytes, sizeof(T));
+ static constexpr auto num_elements_in_block = 1U << num_bits;
+ static constexpr auto mask = num_elements_in_block - 1U;
+
+ /**
+ * Iterator class doubles as const_iterator and iterator
+ */
+ template <bool IsConst>
+ class iter_t {
+ using ptr_t = typename std::conditional_t<IsConst, segmented_vector::const_pointer const*, segmented_vector::pointer*>;
+ ptr_t m_data{};
+ size_t m_idx{};
+
+ template <bool B>
+ friend class iter_t;
+
+ public:
+ using difference_type = segmented_vector::difference_type;
+ using value_type = T;
+ using reference = typename std::conditional_t<IsConst, value_type const&, value_type&>;
+ using pointer = typename std::conditional_t<IsConst, segmented_vector::const_pointer, segmented_vector::pointer>;
+ using iterator_category = std::forward_iterator_tag;
+
+ iter_t() noexcept = default;
+
+ template <bool OtherIsConst, typename = typename std::enable_if<IsConst && !OtherIsConst>::type>
+ // NOLINTNEXTLINE(google-explicit-constructor,hicpp-explicit-conversions)
+ constexpr iter_t(iter_t<OtherIsConst> const& other) noexcept
+ : m_data(other.m_data)
+ , m_idx(other.m_idx) {}
+
+ constexpr iter_t(ptr_t data, size_t idx) noexcept
+ : m_data(data)
+ , m_idx(idx) {}
+
+ template <bool OtherIsConst, typename = typename std::enable_if<IsConst && !OtherIsConst>::type>
+ constexpr auto operator=(iter_t<OtherIsConst> const& other) noexcept -> iter_t& {
+ m_data = other.m_data;
+ m_idx = other.m_idx;
+ return *this;
+ }
+
+ constexpr auto operator++() noexcept -> iter_t& {
+ ++m_idx;
+ return *this;
+ }
+
+ constexpr auto operator+(difference_type diff) noexcept -> iter_t {
+ return {m_data, static_cast<size_t>(static_cast<difference_type>(m_idx) + diff)};
+ }
+
+ template <bool OtherIsConst>
+ constexpr auto operator-(iter_t<OtherIsConst> const& other) noexcept -> difference_type {
+ return static_cast<difference_type>(m_idx) - static_cast<difference_type>(other.m_idx);
+ }
+
+ constexpr auto operator*() const noexcept -> reference {
+ return m_data[m_idx >> num_bits][m_idx & mask];
+ }
+
+ constexpr auto operator->() const noexcept -> pointer {
+ return &m_data[m_idx >> num_bits][m_idx & mask];
+ }
+
+ template <bool O>
+ constexpr auto operator==(iter_t<O> const& o) const noexcept -> bool {
+ return m_idx == o.m_idx;
+ }
+
+ template <bool O>
+ constexpr auto operator!=(iter_t<O> const& o) const noexcept -> bool {
+ return !(*this == o);
+ }
+ };
+
+ // slow path: need to allocate a new segment every once in a while
+ void increase_capacity() {
+ auto ba = Allocator(m_blocks.get_allocator());
+ pointer block = std::allocator_traits<Allocator>::allocate(ba, num_elements_in_block);
+ m_blocks.push_back(block);
+ }
+
+ // Moves everything from other
+ void append_everything_from(segmented_vector&& other) {
+ reserve(size() + other.size());
+ for (auto&& o : other) {
+ emplace_back(std::move(o));
+ }
+ }
+
+ // Copies everything from other
+ void append_everything_from(segmented_vector const& other) {
+ reserve(size() + other.size());
+ for (auto const& o : other) {
+ emplace_back(o);
+ }
+ }
+
+ void dealloc() {
+ auto ba = Allocator(m_blocks.get_allocator());
+ for (auto ptr : m_blocks) {
+ std::allocator_traits<Allocator>::deallocate(ba, ptr, num_elements_in_block);
+ }
+ }
+
+ [[nodiscard]] static constexpr auto calc_num_blocks_for_capacity(size_t capacity) {
+ return (capacity + num_elements_in_block - 1U) / num_elements_in_block;
+ }
+
+public:
+ segmented_vector() = default;
+
+ // NOLINTNEXTLINE(google-explicit-constructor,hicpp-explicit-conversions)
+ segmented_vector(Allocator alloc)
+ : m_blocks(vec_alloc(alloc)) {}
+
+ segmented_vector(segmented_vector&& other, Allocator alloc)
+ : m_blocks(vec_alloc(alloc)) {
+ if (other.get_allocator() == alloc) {
+ *this = std::move(other);
+ } else {
+ // Oh my, allocator is different so we need to copy everything.
+ append_everything_from(std::move(other));
+ }
+ }
+
+ segmented_vector(segmented_vector&& other) noexcept
+ : m_blocks(std::move(other.m_blocks))
+ , m_size(std::exchange(other.m_size, {})) {}
+
+ segmented_vector(segmented_vector const& other, Allocator alloc)
+ : m_blocks(vec_alloc(alloc)) {
+ append_everything_from(other);
+ }
+
+ segmented_vector(segmented_vector const& other) {
+ append_everything_from(other);
+ }
+
+ auto operator=(segmented_vector const& other) -> segmented_vector& {
+ if (this == &other) {
+ return *this;
+ }
+ clear();
+ append_everything_from(other);
+ return *this;
+ }
+
+ auto operator=(segmented_vector&& other) noexcept -> segmented_vector& {
+ clear();
+ dealloc();
+ m_blocks = std::move(other.m_blocks);
+ m_size = std::exchange(other.m_size, {});
+ return *this;
+ }
+
+ ~segmented_vector() {
+ clear();
+ dealloc();
+ }
+
+ [[nodiscard]] constexpr auto size() const -> size_t {
+ return m_size;
+ }
+
+ [[nodiscard]] constexpr auto capacity() const -> size_t {
+ return m_blocks.size() * num_elements_in_block;
+ }
+
+ // Indexing is highly performance critical
+ [[nodiscard]] constexpr auto operator[](size_t i) const noexcept -> T const& {
+ return m_blocks[i >> num_bits][i & mask];
+ }
+
+ [[nodiscard]] constexpr auto operator[](size_t i) noexcept -> T& {
+ return m_blocks[i >> num_bits][i & mask];
+ }
+
+ [[nodiscard]] constexpr auto begin() -> iterator {
+ return {m_blocks.data(), 0U};
+ }
+ [[nodiscard]] constexpr auto begin() const -> const_iterator {
+ return {m_blocks.data(), 0U};
+ }
+ [[nodiscard]] constexpr auto cbegin() const -> const_iterator {
+ return {m_blocks.data(), 0U};
+ }
+
+ [[nodiscard]] constexpr auto end() -> iterator {
+ return {m_blocks.data(), m_size};
+ }
+ [[nodiscard]] constexpr auto end() const -> const_iterator {
+ return {m_blocks.data(), m_size};
+ }
+ [[nodiscard]] constexpr auto cend() const -> const_iterator {
+ return {m_blocks.data(), m_size};
+ }
+
+ [[nodiscard]] constexpr auto back() -> reference {
+ return operator[](m_size - 1);
+ }
+ [[nodiscard]] constexpr auto back() const -> const_reference {
+ return operator[](m_size - 1);
+ }
+
+ void pop_back() {
+ back().~T();
+ --m_size;
+ }
+
+ [[nodiscard]] auto empty() const {
+ return 0 == m_size;
+ }
+
+ void reserve(size_t new_capacity) {
+ m_blocks.reserve(calc_num_blocks_for_capacity(new_capacity));
+ while (new_capacity > capacity()) {
+ increase_capacity();
+ }
+ }
+
+ [[nodiscard]] auto get_allocator() const -> allocator_type {
+ return allocator_type{m_blocks.get_allocator()};
+ }
+
+ template <class... Args>
+ auto emplace_back(Args&&... args) -> reference {
+ if (m_size == capacity()) {
+ increase_capacity();
+ }
+ auto* ptr = static_cast<void*>(&operator[](m_size));
+ auto& ref = *new (ptr) T(std::forward<Args>(args)...);
+ ++m_size;
+ return ref;
+ }
+
+ void clear() {
+ if constexpr (!std::is_trivially_destructible_v<T>) {
+ for (size_t i = 0, s = size(); i < s; ++i) {
+ operator[](i).~T();
+ }
+ }
+ m_size = 0;
+ }
+
+ void shrink_to_fit() {
+ auto ba = Allocator(m_blocks.get_allocator());
+ auto num_blocks_required = calc_num_blocks_for_capacity(m_size);
+ while (m_blocks.size() > num_blocks_required) {
+ std::allocator_traits<Allocator>::deallocate(ba, m_blocks.back(), num_elements_in_block);
+ m_blocks.pop_back();
+ }
+ m_blocks.shrink_to_fit();
+ }
+};
+
+namespace detail {
+
// This is it, the table. Doubles as map and set, and uses `void` for T when its used as a set.
template <class Key,
class T, // when void, treat it as a set.
class Hash,
class KeyEqual,
class AllocatorOrContainer,
- class Bucket>
+ class Bucket,
+ bool IsSegmented>
class table : public std::conditional_t<is_map_v<T>, base_table_type_map<T>, base_table_type_set> {
+ using underlying_value_type = typename std::conditional_t<is_map_v<T>, std::pair<Key, T>, Key>;
+ using underlying_container_type = std::conditional_t<IsSegmented,
+ segmented_vector<underlying_value_type, AllocatorOrContainer>,
+ std::vector<underlying_value_type, AllocatorOrContainer>>;
+
public:
- using value_container_type = std::conditional_t<
- is_detected_v<detect_iterator, AllocatorOrContainer>,
- AllocatorOrContainer,
- typename std::vector<typename std::conditional_t<is_map_v<T>, std::pair<Key, T>, Key>, AllocatorOrContainer>>;
+ using value_container_type = std::
+ conditional_t<is_detected_v<detect_iterator, AllocatorOrContainer>, AllocatorOrContainer, underlying_container_type>;
private:
using bucket_alloc =
@@ -492,7 +789,8 @@ private:
static_assert(std::is_trivially_copyable_v<Bucket>, "assert we can just memset / memcpy");
value_container_type m_values{}; // Contains all the key-value pairs in one densely stored container. No holes.
- typename std::allocator_traits<bucket_alloc>::pointer m_buckets{};
+ using bucket_pointer = typename std::allocator_traits<bucket_alloc>::pointer;
+ bucket_pointer m_buckets{};
size_t m_num_buckets = 0;
size_t m_max_bucket_capacity = 0;
float m_max_load_factor = default_max_load_factor;
@@ -507,8 +805,7 @@ private:
}
// Helper to access bucket through pointer types
- [[nodiscard]] static constexpr auto at(typename std::allocator_traits<bucket_alloc>::pointer bucket_ptr, size_t offset)
- -> Bucket& {
+ [[nodiscard]] static constexpr auto at(bucket_pointer bucket_ptr, size_t offset) -> Bucket& {
return *(bucket_ptr + static_cast<typename std::allocator_traits<bucket_alloc>::difference_type>(offset));
}
@@ -578,7 +875,7 @@ private:
}
[[nodiscard]] static constexpr auto calc_num_buckets(uint8_t shifts) -> size_t {
- return std::min(max_bucket_count(), size_t{1} << (64U - shifts));
+ return (std::min)(max_bucket_count(), size_t{1} << (64U - shifts));
}
[[nodiscard]] constexpr auto calc_shifts_for_size(size_t s) const -> uint8_t {
@@ -983,7 +1280,7 @@ public:
}
[[nodiscard]] static constexpr auto max_size() noexcept -> size_t {
- if constexpr (std::numeric_limits<value_idx_type>::max() == std::numeric_limits<size_t>::max()) {
+ if constexpr ((std::numeric_limits<value_idx_type>::max)() == (std::numeric_limits<size_t>::max)()) {
return size_t{1} << (sizeof(value_idx_type) * 8 - 1);
} else {
return size_t{1} << (sizeof(value_idx_type) * 8);
@@ -1272,7 +1569,7 @@ public:
auto const last_to_end = std::distance(last, cend());
// remove elements from left to right which moves elements from the end back
- auto const mid = idx_first + std::min(first_to_last, last_to_end);
+ auto const mid = idx_first + (std::min)(first_to_last, last_to_end);
auto idx = idx_first;
while (idx != mid) {
erase(begin() + idx);
@@ -1439,8 +1736,8 @@ public:
}
void rehash(size_t count) {
- count = std::min(count, max_size());
- auto shifts = calc_shifts_for_size(std::max(count, size()));
+ count = (std::min)(count, max_size());
+ auto shifts = calc_shifts_for_size((std::max)(count, size()));
if (shifts != m_shifts) {
m_shifts = shifts;
deallocate_buckets();
@@ -1451,12 +1748,12 @@ public:
}
void reserve(size_t capa) {
- capa = std::min(capa, max_size());
+ capa = (std::min)(capa, max_size());
if constexpr (has_reserve<value_container_type>) {
// std::deque doesn't have reserve(). Make sure we only call when available
m_values.reserve(capa);
}
- auto shifts = calc_shifts_for_size(std::max(capa, size()));
+ auto shifts = calc_shifts_for_size((std::max)(capa, size()));
if (0 == m_num_buckets || shifts < m_shifts) {
m_shifts = shifts;
deallocate_buckets();
@@ -1519,16 +1816,31 @@ template <class Key,
class KeyEqual = std::equal_to<Key>,
class AllocatorOrContainer = std::allocator<std::pair<Key, T>>,
class Bucket = bucket_type::standard>
-using map = detail::table<Key, T, Hash, KeyEqual, AllocatorOrContainer, Bucket>;
+using map = detail::table<Key, T, Hash, KeyEqual, AllocatorOrContainer, Bucket, false>;
+
+template <class Key,
+ class T,
+ class Hash = hash<Key>,
+ class KeyEqual = std::equal_to<Key>,
+ class AllocatorOrContainer = std::allocator<std::pair<Key, T>>,
+ class Bucket = bucket_type::standard>
+using segmented_map = detail::table<Key, T, Hash, KeyEqual, AllocatorOrContainer, Bucket, true>;
+
+template <class Key,
+ class Hash = hash<Key>,
+ class KeyEqual = std::equal_to<Key>,
+ class AllocatorOrContainer = std::allocator<Key>,
+ class Bucket = bucket_type::standard>
+using set = detail::table<Key, void, Hash, KeyEqual, AllocatorOrContainer, Bucket, false>;
template <class Key,
class Hash = hash<Key>,
class KeyEqual = std::equal_to<Key>,
class AllocatorOrContainer = std::allocator<Key>,
class Bucket = bucket_type::standard>
-using set = detail::table<Key, void, Hash, KeyEqual, AllocatorOrContainer, Bucket>;
+using segmented_set = detail::table<Key, void, Hash, KeyEqual, AllocatorOrContainer, Bucket, true>;
-# if ANKERL_UNORDERED_DENSE_PMR
+# if defined(ANKERL_UNORDERED_DENSE_PMR)
namespace pmr {
@@ -1537,10 +1849,23 @@ template <class Key,
class Hash = hash<Key>,
class KeyEqual = std::equal_to<Key>,
class Bucket = bucket_type::standard>
-using map = detail::table<Key, T, Hash, KeyEqual, ANKERL_UNORDERED_DENSE_PMR_ALLOCATOR<std::pair<Key, T>>, Bucket>;
+using map =
+ detail::table<Key, T, Hash, KeyEqual, ANKERL_UNORDERED_DENSE_PMR::polymorphic_allocator<std::pair<Key, T>>, Bucket, false>;
+
+template <class Key,
+ class T,
+ class Hash = hash<Key>,
+ class KeyEqual = std::equal_to<Key>,
+ class Bucket = bucket_type::standard>
+using segmented_map =
+ detail::table<Key, T, Hash, KeyEqual, ANKERL_UNORDERED_DENSE_PMR::polymorphic_allocator<std::pair<Key, T>>, Bucket, true>;
+
+template <class Key, class Hash = hash<Key>, class KeyEqual = std::equal_to<Key>, class Bucket = bucket_type::standard>
+using set = detail::table<Key, void, Hash, KeyEqual, ANKERL_UNORDERED_DENSE_PMR::polymorphic_allocator<Key>, Bucket, false>;
template <class Key, class Hash = hash<Key>, class KeyEqual = std::equal_to<Key>, class Bucket = bucket_type::standard>
-using set = detail::table<Key, void, Hash, KeyEqual, ANKERL_UNORDERED_DENSE_PMR_ALLOCATOR<Key>, Bucket>;
+using segmented_set =
+ detail::table<Key, void, Hash, KeyEqual, ANKERL_UNORDERED_DENSE_PMR::polymorphic_allocator<Key>, Bucket, true>;
} // namespace pmr
@@ -1558,11 +1883,18 @@ using set = detail::table<Key, void, Hash, KeyEqual, ANKERL_UNORDERED_DENSE_PMR_
namespace std { // NOLINT(cert-dcl58-cpp)
-template <class Key, class T, class Hash, class KeyEqual, class AllocatorOrContainer, class Bucket, class Pred>
+template <class Key,
+ class T,
+ class Hash,
+ class KeyEqual,
+ class AllocatorOrContainer,
+ class Bucket,
+ class Pred,
+ bool IsSegmented>
// NOLINTNEXTLINE(cert-dcl58-cpp)
-auto erase_if(ankerl::unordered_dense::detail::table<Key, T, Hash, KeyEqual, AllocatorOrContainer, Bucket>& map, Pred pred)
- -> size_t {
- using map_t = ankerl::unordered_dense::detail::table<Key, T, Hash, KeyEqual, AllocatorOrContainer, Bucket>;
+auto erase_if(ankerl::unordered_dense::detail::table<Key, T, Hash, KeyEqual, AllocatorOrContainer, Bucket, IsSegmented>& map,
+ Pred pred) -> size_t {
+ using map_t = ankerl::unordered_dense::detail::table<Key, T, Hash, KeyEqual, AllocatorOrContainer, Bucket, IsSegmented>;
// going back to front because erase() invalidates the end iterator
auto const old_size = map.size();
@@ -1575,7 +1907,7 @@ auto erase_if(ankerl::unordered_dense::detail::table<Key, T, Hash, KeyEqual, All
}
}
- return map.size() - old_size;
+ return old_size - map.size();
}
} // namespace std
diff --git a/misc/benchmarks/external/emhash/hash_table7.hpp b/misc/benchmarks/external/emhash/hash_table7.hpp
index 8f8982f9..41970d8c 100644
--- a/misc/benchmarks/external/emhash/hash_table7.hpp
+++ b/misc/benchmarks/external/emhash/hash_table7.hpp
@@ -92,7 +92,7 @@ of resizing granularity. Ignoring variance, the expected occurrences of list siz
#include "wyhash.h"
#endif
-#ifdef EMH_KEY
+#ifdef EMH_NEW
#undef EMH_KEY
#undef EMH_VAL
#undef EMH_PKV
@@ -547,10 +547,10 @@ public:
static PairT* alloc_bucket(size_type num_buckets)
{
-#if _WIN32
- auto* new_pairs = (PairT*)malloc(AllocSize(num_buckets));
-#else
+#ifdef EMH_ALLOC
auto* new_pairs = (PairT*)aligned_alloc(EMH_MALIGN, AllocSize(num_buckets));
+#else
+ auto* new_pairs = (PairT*)malloc(AllocSize(num_buckets));
#endif
return new_pairs;
}
@@ -1668,16 +1668,10 @@ private:
// key is not in this map. Find a place to put it.
size_type find_empty_bucket(const size_type bucket_from, const size_type main_bucket)
{
-#ifdef EMH_ALIGN64 // only works 64bit
- const auto boset = bucket_from % MASK_BIT;
- auto* const align = _bitmask + bucket_from / MASK_BIT;
- const auto bmask = ((size_t)align[1] << (MASK_BIT - boset)) | (align[0] >> boset);
- if (EMH_LIKELY(bmask != 0))
- return bucket_from + CTZ(bmask);
-#elif EMH_ITER_SAFE
+#if EMH_ITER_SAFE
const auto boset = bucket_from % 8;
- auto* const start = (uint8_t*)_bitmask + bucket_from / 8;
- size_t bmask; memcpy(&bmask, start + 0, sizeof(bmask)); bmask >>= boset;// bmask |= ((size_t)start[8] << (SIZE_BIT - boset));
+ auto* const align = (uint8_t*)_bitmask + bucket_from / 8;(void)main_bucket;
+ size_t bmask; memcpy(&bmask, align + 0, sizeof(bmask)); bmask >>= boset;// bmask |= ((size_t)align[8] << (SIZE_BIT - boset));
if (EMH_LIKELY(bmask != 0))
return bucket_from + CTZ(bmask);
#else
@@ -1715,21 +1709,15 @@ private:
}
// key is not in this map. Find a place to put it.
- size_type find_unique_empty(const size_type bucket_from, const size_t main_bucket)
- {
-#ifdef EMH_ALIGN64
- const auto boset = bucket_from % MASK_BIT;
- auto* const align = _bitmask + bucket_from / MASK_BIT;
- const auto bmask = ((size_t)align[1] << (MASK_BIT - boset)) | (align[0] >> boset);
- static_assert(sizeof(size_t) > 4);
-#elif EMH_ITER_SAFE
+ size_type find_unique_empty(const size_type bucket_from)
+ {
const auto boset = bucket_from % 8;
- auto* const start = (uint8_t*)_bitmask + bucket_from / 8;
- size_t bmask; memcpy(&bmask, start + 0, sizeof(bmask)); bmask >>= boset;
-#else
- const auto boset = bucket_from % 8; (void)main_bucket;
auto* const align = (uint8_t*)_bitmask + bucket_from / 8;
- const auto bmask = (*(size_t*)(align) >> boset); //maybe not aligned and warning
+
+#if EMH_ITER_SAFE
+ size_t bmask; memcpy(&bmask, align + 0, sizeof(bmask)); bmask >>= boset;
+#else
+ const auto bmask = (*(size_t*)(align) >> boset); //maybe not aligned and warning
#endif
if (EMH_LIKELY(bmask != 0))
return bucket_from + CTZ(bmask);
@@ -1789,12 +1777,12 @@ private:
next_bucket = find_last_bucket(next_bucket);
//find a new empty and link it to tail
- return EMH_BUCKET(_pairs, next_bucket) = find_unique_empty(next_bucket, bucket);
+ return EMH_BUCKET(_pairs, next_bucket) = find_empty_bucket(next_bucket, bucket);
}
#if EMH_INT_HASH
static constexpr uint64_t KC = UINT64_C(11400714819323198485);
- inline uint64_t hash64(uint64_t key)
+ inline static uint64_t hash64(uint64_t key)
{
#if __SIZEOF_INT128__ && EMH_INT_HASH == 1
__uint128_t r = key; r *= KC;
diff --git a/misc/benchmarks/plotbench/cdeq_benchmark.cpp b/misc/benchmarks/plotbench/cdeq_benchmark.cpp
index bb0e28c8..54d7305b 100644
--- a/misc/benchmarks/plotbench/cdeq_benchmark.cpp
+++ b/misc/benchmarks/plotbench/cdeq_benchmark.cpp
@@ -12,7 +12,7 @@ enum {INSERT, ERASE, FIND, ITER, DESTRUCT, N_TESTS};
const char* operations[] = {"insert", "erase", "find", "iter", "destruct"};
typedef struct { time_t t1, t2; uint64_t sum; float fac; } Range;
typedef struct { const char* name; Range test[N_TESTS]; } Sample;
-enum {SAMPLES = 2, N = 50000000, S = 0x3ffc, R = 4};
+enum {SAMPLES = 2, N = 60000000, S = 0x3ffc, R = 4};
uint64_t seed = 1, mask1 = 0xfffffff, mask2 = 0xffff;
static float secs(Range s) { return (float)(s.t2 - s.t1) / CLOCKS_PER_SEC; }
diff --git a/misc/benchmarks/plotbench/cpque_benchmark.cpp b/misc/benchmarks/plotbench/cpque_benchmark.cpp
index 2d4c7a28..6c62ae3e 100644
--- a/misc/benchmarks/plotbench/cpque_benchmark.cpp
+++ b/misc/benchmarks/plotbench/cpque_benchmark.cpp
@@ -58,7 +58,7 @@ void stc_test()
}
-int main()
+int main(void)
{
puts("STD P.QUEUE:");
std_test();
diff --git a/misc/benchmarks/plotbench/cvec_benchmark.cpp b/misc/benchmarks/plotbench/cvec_benchmark.cpp
index c488a01c..3b4c3d7d 100644
--- a/misc/benchmarks/plotbench/cvec_benchmark.cpp
+++ b/misc/benchmarks/plotbench/cvec_benchmark.cpp
@@ -12,7 +12,7 @@ enum {INSERT, ERASE, FIND, ITER, DESTRUCT, N_TESTS};
const char* operations[] = {"insert", "erase", "find", "iter", "destruct"};
typedef struct { time_t t1, t2; uint64_t sum; float fac; } Range;
typedef struct { const char* name; Range test[N_TESTS]; } Sample;
-enum {SAMPLES = 2, N = 80000000, S = 0x3ffc, R = 4};
+enum {SAMPLES = 2, N = 40000000, S = 0x3ffc, R = 4};
uint64_t seed = 1, mask1 = 0xfffffff, mask2 = 0xffff;
static float secs(Range s) { return (float)(s.t2 - s.t1) / CLOCKS_PER_SEC; }
diff --git a/misc/benchmarks/plotbench/plot.py b/misc/benchmarks/plotbench/plot.py
index 0ba92264..e65631b7 100644
--- a/misc/benchmarks/plotbench/plot.py
+++ b/misc/benchmarks/plotbench/plot.py
@@ -12,8 +12,8 @@ df = df[df.Method != 'total']
if n > 0:
df = df[df.Compiler == comp[n]]
-g = sns.catplot(data=df, x='Method', y='Seconds', hue='Library', col='C', kind='bar',
- ci=68, legend=False, col_wrap=2, sharex=False, aspect=1.4, height=3.1)
+g = sns.catplot(data=df, x='Method', y='Seconds', hue='Library', col='C', kind='bar', orient='v',
+ errorbar=('ci', 68), legend=False, col_wrap=2, sharex=False, aspect=1.4, height=3.1)
g.set_xlabels('')
g.add_legend(bbox_to_anchor=(0.75, 0.2), borderaxespad=0.)
diff --git a/misc/benchmarks/plotbench/run_clang.sh b/misc/benchmarks/plotbench/run_clang.sh
index 096e71be..59d577d9 100644
--- a/misc/benchmarks/plotbench/run_clang.sh
+++ b/misc/benchmarks/plotbench/run_clang.sh
@@ -1,10 +1,10 @@
exe=''
if [ "$OS" = "Windows_NT" ] ; then exe=".exe" ; fi
-clang++ -I../include -O3 -o cdeq_benchmark$exe cdeq_benchmark.cpp
-clang++ -I../include -O3 -o clist_benchmark$exe clist_benchmark.cpp
-clang++ -I../include -O3 -o cmap_benchmark$exe cmap_benchmark.cpp
-clang++ -I../include -O3 -o csmap_benchmark$exe csmap_benchmark.cpp
-clang++ -I../include -O3 -o cvec_benchmark$exe cvec_benchmark.cpp
+clang++ -DNDEBUG -I../../include -O3 -o cdeq_benchmark$exe cdeq_benchmark.cpp
+clang++ -DNDEBUG -I../../include -O3 -o clist_benchmark$exe clist_benchmark.cpp
+clang++ -DNDEBUG -I../../include -O3 -o cmap_benchmark$exe cmap_benchmark.cpp
+clang++ -DNDEBUG -I../../include -O3 -o csmap_benchmark$exe csmap_benchmark.cpp
+clang++ -DNDEBUG -I../../include -O3 -o cvec_benchmark$exe cvec_benchmark.cpp
c='Win-Clang-14.0.1'
./cdeq_benchmark$exe $c
diff --git a/misc/benchmarks/plotbench/run_gcc.sh b/misc/benchmarks/plotbench/run_gcc.sh
index 5249ed1e..73b979d3 100644
--- a/misc/benchmarks/plotbench/run_gcc.sh
+++ b/misc/benchmarks/plotbench/run_gcc.sh
@@ -1,8 +1,8 @@
-g++ -I../include -O3 -o cdeq_benchmark cdeq_benchmark.cpp
-g++ -I../include -O3 -o clist_benchmark clist_benchmark.cpp
-g++ -I../include -O3 -o cmap_benchmark cmap_benchmark.cpp
-g++ -I../include -O3 -o csmap_benchmark csmap_benchmark.cpp
-g++ -I../include -O3 -o cvec_benchmark cvec_benchmark.cpp
+g++ -DNDEBUG -I../../include -O3 -o cdeq_benchmark cdeq_benchmark.cpp
+g++ -DNDEBUG -I../../include -O3 -o clist_benchmark clist_benchmark.cpp
+g++ -DNDEBUG -I../../include -O3 -o cmap_benchmark cmap_benchmark.cpp
+g++ -DNDEBUG -I../../include -O3 -o csmap_benchmark csmap_benchmark.cpp
+g++ -DNDEBUG -I../../include -O3 -o cvec_benchmark cvec_benchmark.cpp
c='Mingw-g++-11.3.0'
./cdeq_benchmark $c
diff --git a/misc/benchmarks/shootout_hashmaps.cpp b/misc/benchmarks/shootout_hashmaps.cpp
index bae9a42b..c6a81777 100644
--- a/misc/benchmarks/shootout_hashmaps.cpp
+++ b/misc/benchmarks/shootout_hashmaps.cpp
@@ -2,7 +2,7 @@
#include <time.h>
#include <stc/crand.h>
-#define MAX_LOAD_FACTOR 85
+#define MAX_LOAD_FACTOR 80
#ifdef __cplusplus
#include <limits>
@@ -35,8 +35,8 @@ KHASH_MAP_INIT_INT64(ii, IValue)
// cmap template expansion
#define i_key IKey
#define i_val IValue
-#define i_ssize int32_t // enable 2^K buckets like the rest.
#define i_tag ii
+//#define i_expandby 1
#define i_max_load_factor MAX_LOAD_FACTOR / 100.0f
#include <stc/cmap.h>
diff --git a/misc/benchmarks/various/csort_bench.c b/misc/benchmarks/various/csort_bench.c
index d5d7fa7c..f6b7f1db 100644
--- a/misc/benchmarks/various/csort_bench.c
+++ b/misc/benchmarks/various/csort_bench.c
@@ -5,8 +5,12 @@
#ifdef __cplusplus
#include <algorithm>
#endif
-#define i_val int
-#include <stc/algo/csort.h>
+#define NDEBUG
+#define i_type Ints
+#define i_key int
+#define i_more
+#include <stc/cvec.h>
+#include <stc/algo/sort.h>
#define ROTL(d,bits) ((d<<(bits)) | (d>>(8*sizeof(d)-(bits))))
uint64_t romutrio(uint64_t s[3]) {
@@ -21,14 +25,14 @@ static int cmp_int(const void* a, const void* b) {
return c_default_cmp((const int*)a, (const int*)b);
}
-void testsort(int *a, int size, const char *desc) {
+void testsort(Ints *a, int size, const char *desc) {
clock_t t = clock();
#ifdef __cplusplus
- printf("std::sort: "); std::sort(a, a + size);
+ printf("std::sort: "); std::sort(a->data, a->data + size);
#elif defined QSORT
- printf("qsort: "); qsort(a, size, sizeof *a, cmp_int);
+ printf("qsort: "); qsort(a->data, size, sizeof *a->data, cmp_int);
#else
- printf("stc_sort: "); csort_int(a, size);
+ printf("STC sort_n: "); Ints_sort_n(a, size);
#endif
t = clock() - t;
@@ -41,27 +45,27 @@ int main(int argc, char *argv[]) {
size_t i, size = argc > 1 ? strtoull(argv[1], NULL, 0) : 10000000;
uint64_t s[3] = {123456789, 3456789123, 789123456};
- int32_t *a = (int32_t*)malloc(sizeof(*a) * size);
- if (!a) return -1;
+ Ints a = Ints_with_capacity(size);
for (i = 0; i < size; i++)
- a[i] = romutrio(s) & (1U << 30) - 1;
- testsort(a, size, "random");
+ *Ints_push(&a, romutrio(s) & (1U << 30) - 1);
+ testsort(&a, size, "random");
for (i = 0; i < 20; i++)
- printf(" %d", (int)a[i]);
+ printf(" %d", (int)*Ints_at(&a, i));
puts("");
for (i = 0; i < size; i++)
- a[i] = i;
- testsort(a, size, "sorted");
+ *Ints_at_mut(&a, i) = i;
+ testsort(&a, size, "sorted");
for (i = 0; i < size; i++)
- a[i] = size - i;
- testsort(a, size, "reverse sorted");
+ *Ints_at_mut(&a, i) = size - i;
+ testsort(&a, size, "reverse sorted");
for (i = 0; i < size; i++)
- a[i] = 126735;
- testsort(a, size, "constant");
+ *Ints_at_mut(&a, i) = 126735;
+ testsort(&a, size, "constant");
for (i = 0; i < size; i++)
- a[i] = i + 1;
- a[size - 1] = 0;
- testsort(a, size, "rotated");
- free(a);
+ *Ints_at_mut(&a, i) = i + 1;
+ *Ints_at_mut(&a, size - 1) = 0;
+ testsort(&a, size, "rotated");
+
+ Ints_drop(&a);
}
diff --git a/misc/benchmarks/various/cspan_bench.c b/misc/benchmarks/various/cspan_bench.c
index 589df13a..f4b067f8 100644
--- a/misc/benchmarks/various/cspan_bench.c
+++ b/misc/benchmarks/various/cspan_bench.c
@@ -1,4 +1,4 @@
-#define STC_NDEBUG
+#define NDEBUG
#include <stc/cspan.h>
#include <stdio.h>
#include <time.h>
@@ -12,8 +12,7 @@ enum {
nz = 64
};
int lx = 15, ly = 10, lz = 5;
-int hx = 20, hy = 15, hz = 15;
-intptr_t n = 1000000;
+int hx = 30, hy = 15, hz = 15;
// define the contents of two nx x ny x nz arrays in and out
double Vout[nx * ny * nz];
@@ -21,12 +20,12 @@ double Vin[nx * ny * nz]; //, 1.23;
// define some slice indices for each dimension
-static void MDRanges_setup(intptr_t state)
+static void MDRanges_setup(intptr_t n)
{
double sum = 0;
clock_t t = clock();
- for (intptr_t s = 0; s < state; ++s)
+ for (intptr_t s = 0; s < n; ++s)
{
MD3 r_in = cspan_md(Vin, nx, ny, nz);
MD3 r_out = cspan_md(Vout, nx, ny, nz);
@@ -41,18 +40,18 @@ static void MDRanges_setup(intptr_t state)
printf("setup: %.1f ms, %f\n", 1000.0f * t / CLOCKS_PER_SEC, sum);
}
-static void TraditionalForLoop(intptr_t state)
+static void TraditionalForLoop(intptr_t n)
{
clock_t t = clock();
double sum = 0;
- for (int s = 0; s < state; ++s) {
+ for (int s = 0; s < n; ++s) {
for (int x = lx; x < hx; ++x) {
for (int y = ly; y < hy; ++y) {
- for (int z = lz; z < hz; ++z)
- {
- double d = Vin[nz*(ny*x + y) + z];
- Vout[nz*(ny*x + y) + z] += d;
+ for (int z = lz; z < hz; ++z) {
+ int i = nz*(ny*x + y) + z;
+ double d = Vin[i];
+ Vout[i] += d;
sum += d;
}
}
@@ -62,18 +61,18 @@ static void TraditionalForLoop(intptr_t state)
printf("forloop: %.1f ms, %f\n", 1000.0f * t / CLOCKS_PER_SEC, sum);
}
-static void MDRanges_nested_loop(intptr_t state)
+static void MDRanges_nested_loop(intptr_t n)
{
+ clock_t t = clock();
MD3 r_in = cspan_md(Vin, nx, ny, nz);
MD3 r_out = cspan_md(Vout, nx, ny, nz);
r_in = cspan_slice(MD3, &r_in, {lx, hx}, {ly, hy}, {lz, hz});
r_out = cspan_slice(MD3, &r_out, {lx, hx}, {ly, hy}, {lz, hz});
// C++23: for (auto [o, i] : std::views::zip(flat(r_out), flat(r_in))) { o = i; }
- clock_t t = clock();
double sum = 0;
- for (intptr_t s = 0; s < state; ++s) {
+ for (intptr_t s = 0; s < n; ++s) {
for (int x = 0; x < r_in.shape[0]; ++x) {
for (int y = 0; y < r_in.shape[1]; ++y) {
for (int z = 0; z < r_in.shape[2]; ++z)
@@ -89,7 +88,7 @@ static void MDRanges_nested_loop(intptr_t state)
printf("nested: %.1f ms, %f\n", 1000.0f * t / CLOCKS_PER_SEC, sum);
}
-static void MDRanges_loop_over_joined(intptr_t state)
+static void MDRanges_loop_over_joined(intptr_t n)
{
MD3 r_in = cspan_md(Vin, nx, ny, nz);
MD3 r_out = cspan_md(Vout, nx, ny, nz);
@@ -100,7 +99,7 @@ static void MDRanges_loop_over_joined(intptr_t state)
double sum = 0;
clock_t t = clock();
- for (intptr_t s = 0; s < state; ++s) {
+ for (intptr_t s = 0; s < n; ++s) {
MD3_iter i = MD3_begin(&r_in);
MD3_iter o = MD3_begin(&r_out);
@@ -114,8 +113,9 @@ static void MDRanges_loop_over_joined(intptr_t state)
printf("joined: %.1f ms, %f\n", 1000.0f * t / CLOCKS_PER_SEC, sum);
}
-int main()
+int main(void)
{
+ intptr_t n = 100000;
for (int i = 0; i < nx * ny * nz; ++i)
Vin[i] = i + 1.23;
diff --git a/misc/benchmarks/various/rust_cmap.c b/misc/benchmarks/various/rust_cmap.c
index abdb42b0..97047e0b 100644
--- a/misc/benchmarks/various/rust_cmap.c
+++ b/misc/benchmarks/various/rust_cmap.c
@@ -22,7 +22,7 @@ uint64_t romu_trio(uint64_t s[3]) {
return xp;
}
-int main()
+int main(void)
{
cmap_u64 m = {0};
diff --git a/misc/benchmarks/various/sso_bench.cpp b/misc/benchmarks/various/sso_bench.cpp
index 993ff1bb..244c1291 100644
--- a/misc/benchmarks/various/sso_bench.cpp
+++ b/misc/benchmarks/various/sso_bench.cpp
@@ -3,65 +3,82 @@
#include <chrono>
#include <stc/crand.h>
+#define i_static
#include <stc/cstr.h>
#define i_type StcVec
#define i_val_str
#include <stc/cstack.h>
-#define i_type StcSet
-#define i_val_str
-#include <stc/csset.h>
-
#include <vector>
using StdVec = std::vector<std::string>;
-#include <set>
-using StdSet = std::set<std::string>;
-static const int BENCHMARK_SIZE = 2000000;
-static const int MAX_STRING_SIZE = 50;
+#include <unordered_set>
+#include "../external/ankerl/robin_hood.h"
+
+struct string_hash {
+ using is_transparent = void;
+ [[nodiscard]] size_t operator()(const char *txt) const {
+ return std::hash<std::string_view>{}(txt);
+ }
+ [[nodiscard]] size_t operator()(std::string_view txt) const {
+ return std::hash<std::string_view>{}(txt);
+ }
+ [[nodiscard]] size_t operator()(const std::string &txt) const {
+ return std::hash<std::string>{}(txt);
+ }
+};
+using StdSet = robin_hood::unordered_flat_set<std::string, string_hash, std::equal_to<>>;
+//using StdSet = std::unordered_set<std::string>;
+
+#define i_type StcSet
+#define i_val_str
+//#define i_hash(txtp) std::hash<std::string_view>{}(*txtp)
+#include <stc/cset.h>
+
+
+static const int BENCHMARK_SIZE = 250000;
+static const int MAX_STRING_SIZE = 100;
static const char CHARS[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz=+-";
using time_point = std::chrono::high_resolution_clock::time_point;
-static inline std::string randomString_STD(int strsize) {
- std::string s(strsize, 0);
- char* p = &s[0];
+static inline const char* randomString(int strsize) {
+ static char str[256];
union { uint64_t u8; uint8_t b[8]; } r;
for (int i = 0; i < strsize; ++i) {
if ((i & 7) == 0) r.u8 = crand() & 0x3f3f3f3f3f3f3f3f;
- p[i] = CHARS[r.b[i & 7]];
+ str[i] = CHARS[r.b[i & 7]];
}
- return s;
+ str[strsize] = 0;
+ return str;
}
-static inline cstr randomString_STC(int strsize) {
- cstr s = cstr_with_size(strsize, 0);
- char* p = cstr_data(&s);
- union { uint64_t u8; uint8_t b[8]; } r;
- for (int i = 0; i < strsize; ++i) {
- if ((i & 7) == 0) r.u8 = crand() & 0x3f3f3f3f3f3f3f3f;
- p[i] = CHARS[r.b[i & 7]];
- }
- return s;
+
+
+static inline void addRandomString(StdVec& vec, const char* str) {
+ vec.push_back(str);
}
+static inline void addRandomString(StcVec& vec, const char* str) {
+ StcVec_emplace(&vec, str);
+}
-void addRandomString(StdVec& vec, int strsize) {
- vec.push_back(std::move(randomString_STD(strsize)));
+static inline void addRandomString(StdSet& set, const char* str) {
+ set.insert(str);
}
-void addRandomString(StcVec& vec, int strsize) {
- StcVec_push(&vec, randomString_STC(strsize));
+static inline void addRandomString(StcSet& set, const char* str) {
+ StcSet_emplace(&set, str);
}
-void addRandomString(StdSet& set, int strsize) {
- set.insert(std::move(randomString_STD(strsize)));
+static inline bool getRandomString(const StdSet& set, const char* str) {
+ return set.find(str) != set.end();
}
-void addRandomString(StcSet& set, int strsize) {
- StcSet_insert(&set, randomString_STC(strsize));
+static inline bool getRandomString(const StcSet& set, const char* str) {
+ return StcSet_contains(&set, str);
}
@@ -70,7 +87,7 @@ int benchmark(C& container, const int n, const int strsize) {
time_point t1 = std::chrono::high_resolution_clock::now();
for (int i = 0; i < n; i++)
- addRandomString(container, strsize);
+ addRandomString(container, randomString(strsize));
time_point t2 = std::chrono::high_resolution_clock::now();
const auto duration = std::chrono::duration_cast<std::chrono::milliseconds>(t2 - t1).count();
@@ -78,9 +95,25 @@ int benchmark(C& container, const int n, const int strsize) {
return (int)duration;
}
+template <class C>
+int benchmark_lookup(C& container, const int n, const int strsize) {
+ for (int i = 0; i < n; i++)
+ addRandomString(container, randomString(strsize));
+
+ time_point t1 = std::chrono::high_resolution_clock::now();
+ int found = 0;
+ for (int i = 0; i < n; i++)
+ found += (int)getRandomString(container, randomString(strsize));
+
+ time_point t2 = std::chrono::high_resolution_clock::now();
+ const auto duration = std::chrono::duration_cast<std::chrono::milliseconds>(t2 - t1).count();
+ std::cerr << (strsize ? strsize : 32) << "\t" << duration << '\t' << found;
+ return (int)duration;
+}
-int main() {
- uint64_t seed = 4321;
+#include <time.h>
+int main(void) {
+ uint64_t seed = time(NULL); // 4321;
int sum, n;
// VECTOR WITH STRINGS
@@ -88,48 +121,75 @@ int main() {
csrand(seed);
sum = 0, n = 0;
std::cerr << "\nstrsize\tmsecs\tstd::vector<std::string>, size=" << BENCHMARK_SIZE << "\n";
- for (int strsize = 1; strsize <= MAX_STRING_SIZE; strsize += 2) {
+ for (int strsize = 1; strsize <= MAX_STRING_SIZE; strsize += 4) {
StdVec vec; vec.reserve(BENCHMARK_SIZE);
sum += benchmark(vec, BENCHMARK_SIZE, strsize), ++n;
std::cout << '\t' << vec.front() << '\n';
}
- std::cout << "Avg:\t" << sum/n << '\n';
+ std::cout << "Avg:\t" << sum/n << "ms\n";
csrand(seed);
sum = 0, n = 0;
std::cerr << "\nstrsize\tmsecs\tcvec<cstr>, size=" << BENCHMARK_SIZE << "\n";
- for (int strsize = 1; strsize <= MAX_STRING_SIZE; strsize += 2) {
+ for (int strsize = 1; strsize <= MAX_STRING_SIZE; strsize += 4) {
StcVec vec = StcVec_with_capacity(BENCHMARK_SIZE);
sum += benchmark(vec, BENCHMARK_SIZE, strsize), ++n;
std::cout << '\t' << cstr_str(&vec.data[0]) << '\n';
StcVec_drop(&vec);
}
- std::cout << "Avg:\t" << sum/n << '\n';
+ std::cout << "Avg:\t" << sum/n << "ms\n";
+
+ // INSERT: SORTED SET WITH STRINGS
+
+ csrand(seed);
+ sum = 0, n = 0;
+ std::cerr << "\nstrsize\tmsecs\tinsert: robin_hood::unordered_flat_set<std::string>, size=" << BENCHMARK_SIZE/2 << "\n";
+ for (int strsize = 1; strsize <= MAX_STRING_SIZE; strsize += 4) {
+ StdSet set; set.reserve(BENCHMARK_SIZE/2);
+ sum += benchmark(set, BENCHMARK_SIZE/2, strsize), ++n;
+ std::cout << '\t' << *set.begin() << '\n';
+ }
+ std::cout << "Avg:\t" << sum/n << "ms\n";
- // SORTED SET WITH STRINGS
csrand(seed);
sum = 0, n = 0;
- std::cerr << "\nstrsize\tmsecs\tstd::set<std::string>, size=" << BENCHMARK_SIZE/16 << "\n";
+ std::cerr << "\nstrsize\tmsecs\tinsert: cset<cstr>, size=" << BENCHMARK_SIZE/2 << "\n";
+ for (int strsize = 1; strsize <= MAX_STRING_SIZE; strsize += 4) {
+ StcSet set = StcSet_with_capacity(BENCHMARK_SIZE/2);
+ sum += benchmark(set, BENCHMARK_SIZE/2, strsize), ++n;
+ std::cout << '\t' << cstr_str(StcSet_begin(&set).ref) << '\n';
+ StcSet_drop(&set);
+ }
+ std::cout << "Avg:\t" << sum/n << "ms\n";
+
+ // LOOKUP: SORTED SET WITH STRINGS
+
+ csrand(seed);
+ sum = 0, n = 0;
+ std::cerr << "\nstrsize\tmsecs\tfind: robin_hood::unordered_flat_set<std::string>, size=" << BENCHMARK_SIZE/2 << "\n";
for (int strsize = 1; strsize <= MAX_STRING_SIZE; strsize += 2) {
- StdSet set;
- sum += benchmark(set, BENCHMARK_SIZE/16, strsize), ++n;
+ StdSet set; set.reserve(BENCHMARK_SIZE/2);
+ sum += benchmark_lookup(set, BENCHMARK_SIZE/2, strsize), ++n;
std::cout << '\t' << *set.begin() << '\n';
}
- std::cout << "Avg:\t" << sum/n << '\n';
+ std::cout << "Avg:\t" << sum/n << "ms\n";
csrand(seed);
sum = 0, n = 0;
- std::cerr << "\nstrsize\tmsecs\tcsset<cstr>, size=" << BENCHMARK_SIZE/16 << "\n";
+ std::cerr << "\nstrsize\tmsecs\tfind: cset<cstr>, size=" << BENCHMARK_SIZE/2 << "\n";
for (int strsize = 1; strsize <= MAX_STRING_SIZE; strsize += 2) {
- StcSet set = StcSet_with_capacity(BENCHMARK_SIZE/16);
- sum += benchmark(set, BENCHMARK_SIZE/16, strsize), ++n;
- std::cout << '\t' << cstr_str(StcSet_front(&set)) << '\n';
+ StcSet set = StcSet_with_capacity(BENCHMARK_SIZE/2);
+ sum += benchmark_lookup(set, BENCHMARK_SIZE/2, strsize), ++n;
+ std::cout << '\t' << cstr_str(StcSet_begin(&set).ref) << '\n';
StcSet_drop(&set);
}
- std::cout << "Avg:\t" << sum/n << '\n';
+ std::cout << "Avg:\t" << sum/n << "ms\n";
+
std::cerr << "sizeof(std::string) : " << sizeof(std::string) << std::endl
- << "sizeof(cstr) : " << sizeof(cstr) << std::endl;
+ << "sizeof(cstr) : " << sizeof(cstr) << std::endl
+ << "sizeof(StdSet) : " << sizeof(StdSet) << std::endl
+ << "sizeof(StcSet) : " << sizeof(StcSet) << std::endl;
return 0;
}
diff --git a/misc/benchmarks/various/string_bench_STC.cpp b/misc/benchmarks/various/string_bench_STC.cpp
index ae8e4c38..a5dfd901 100644
--- a/misc/benchmarks/various/string_bench_STC.cpp
+++ b/misc/benchmarks/various/string_bench_STC.cpp
@@ -4,10 +4,11 @@
#include <iostream>
#include <iomanip>
#include <chrono>
-#define i_static
+#define i_implement
#include <stc/cstr.h> // string
-#define i_static
+#define i_implement
#include <stc/csview.h> // string_view
+#include <stc/algo/raii.h>
#define i_key_str
#include <stc/cvec.h> // vec of cstr with const char* lookup
@@ -183,7 +184,7 @@ void benchmark(
//const size_t MAX_LOOP = 1000000;
const size_t MAX_LOOP = 2000;
-int main()
+int main(void)
{
c_auto (cvec_str, vec_string)
c_auto (cvec_sv, vec_stringview)
diff --git a/misc/benchmarks/various/string_bench_STD.cpp b/misc/benchmarks/various/string_bench_STD.cpp
index 8bb87937..153ac02f 100644
--- a/misc/benchmarks/various/string_bench_STD.cpp
+++ b/misc/benchmarks/various/string_bench_STD.cpp
@@ -12,6 +12,7 @@
#include <unordered_map>
#define i_static
#include <stc/cstr.h>
+#include <stc/algo/raii.h>
std::vector<std::string> read_file(const char* name)
{
@@ -193,7 +194,7 @@ void benchmark(
//const size_t MAX_LOOP = 1000000;
const size_t MAX_LOOP = 2000;
-int main()
+int main(void)
{
std::vector<std::string> vec_shortstr;
std::vector<std::string_view> vec_shortstrview;
diff --git a/misc/examples/arc_containers.c b/misc/examples/arc_containers.c
index 84ba8dda..2fb04c56 100644
--- a/misc/examples/arc_containers.c
+++ b/misc/examples/arc_containers.c
@@ -1,7 +1,8 @@
// Create a stack and a list of shared pointers to maps,
// and demonstrate sharing and cloning of maps.
-#define i_static
+#define i_implement
#include <stc/cstr.h>
+#include <stc/algo/raii.h>
#define i_type Map
#define i_key_str // strings
#define i_val int
@@ -9,23 +10,21 @@
#include <stc/csmap.h>
#define i_type Arc // (atomic) ref. counted type
-#define i_val Map
-#define i_valdrop(p) (printf("drop Arc:\n"), Map_drop(p))
+#define i_key Map
+#define i_keydrop(p) (printf("drop Arc:\n"), Map_drop(p))
// no need for atomic ref. count in single thread:
-#define i_opt c_no_atomic|c_no_cmp|c_no_clone
+#define i_opt c_no_atomic
#include <stc/carc.h>
#define i_type Stack
-#define i_valboxed Arc // define i_valboxed for carc/cbox value (not i_val)
-#define i_opt c_no_cmp
+#define i_keyboxed Arc // define i_keyboxed for carc/cbox value (not i_key)
#include <stc/cvec.h>
#define i_type List
-#define i_valboxed Arc // as above
-#define i_opt c_no_cmp
+#define i_keyboxed Arc // as above
#include <stc/clist.h>
-int main()
+int main(void)
{
Stack stack = {0};
List list = {0};
diff --git a/misc/examples/arc_demo.c b/misc/examples/arc_demo.c
index 2339adbb..87d64e67 100644
--- a/misc/examples/arc_demo.c
+++ b/misc/examples/arc_demo.c
@@ -6,27 +6,31 @@ void int_drop(int* x) {
}
// carc implements its own clone method using reference counting,
-// so 'i_valclone' is not required to be defined (ignored).
+// so 'i_keyclone' is not required to be defined (ignored).
#define i_type Arc // set type name to be defined (instead of 'carc_int')
-#define i_val int
-#define i_valdrop int_drop // optional, just to display the elements destroyed
-#define i_no_clone // required because of valdrop
+#define i_key int
+#define i_keydrop int_drop // optional, just to display the elements destroyed
+#define i_native_cmp // use int comparison (x < y, x == y).
#include <stc/carc.h> // Arc
-#define i_keyboxed Arc // note: use i_keyboxed instead of i_key for carc/cbox elements
+#define i_keyboxed Arc // note: use i_keyboxed instead of i_key for carc/cbox elements
#include <stc/csset.h> // csset_Arc (like: std::set<std::shared_ptr<int>>)
-#define i_valboxed Arc // note: as above.
+#define i_keyboxed Arc // note: as above.
#include <stc/cvec.h> // cvec_Arc (like: std::vector<std::shared_ptr<int>>)
-int main()
+int main(void)
{
const int years[] = {2021, 2012, 2022, 2015};
cvec_Arc vec = {0};
- c_forrange (i, c_arraylen(years))
- cvec_Arc_push(&vec, Arc_from(years[i]));
+ c_forrange (i, c_arraylen(years)) {
+ cvec_Arc_emplace(&vec, years[i]);
+ // cvec_Arc_push(&vec, Arc_from(years[i])); // alt.
+ }
+
+ cvec_Arc_sort(&vec);
printf("vec:");
c_foreach (i, cvec_Arc, vec)
diff --git a/misc/examples/arcvec_erase.c b/misc/examples/arcvec_erase.c
index 3bf41559..addef8b7 100644
--- a/misc/examples/arcvec_erase.c
+++ b/misc/examples/arcvec_erase.c
@@ -3,19 +3,19 @@
void show_drop(int* x) { printf("drop: %d\n", *x); }
#define i_type Arc
-#define i_val int
-#define i_valdrop show_drop
-#define i_no_clone // required because of valdrop
+#define i_key int
+#define i_keydrop show_drop
+#define i_native_cmp // enable sort/search for int type
#include <stc/carc.h> // Shared pointer to int
#define i_type Vec
-#define i_valboxed Arc
+#define i_keyboxed Arc
#include <stc/cvec.h> // Vec: cvec<Arc>
-int main()
+int main(void)
{
- Vec vec = c_make(Vec, {2012, 1990, 2012, 2019, 2015});
+ Vec vec = c_init(Vec, {2012, 1990, 2012, 2019, 2015});
// clone the second 2012 and push it back.
// note: cloning make sure that vec.data[2] has ref count 2.
diff --git a/misc/examples/astar.c b/misc/examples/astar.c
index 7dd12d50..590b7952 100644
--- a/misc/examples/astar.c
+++ b/misc/examples/astar.c
@@ -4,6 +4,7 @@
// This is a reimplementation of the CTL example to STC:
// https://github.com/glouw/ctl/blob/master/examples/astar.c
// https://www.redblobgames.com/pathfinding/a-star/introduction.html
+#define i_implement
#include <stc/cstr.h>
#include <stdio.h>
@@ -19,7 +20,7 @@ point;
point
point_init(int x, int y, int width)
{
- return (point) { x, y, 0, width };
+ return c_LITERAL(point){ x, y, 0, width };
}
int
@@ -55,11 +56,11 @@ point_key_cmp(const point* a, const point* b)
return (i == j) ? 0 : (i < j) ? -1 : 1;
}
-#define i_val point
+#define i_key point
#define i_cmp point_cmp_priority
#include <stc/cpque.h>
-#define i_val point
+#define i_key point
#define i_opt c_no_cmp
#include <stc/cdeq.h>
diff --git a/misc/examples/birthday.c b/misc/examples/birthday.c
index c301128a..4742cb45 100644
--- a/misc/examples/birthday.c
+++ b/misc/examples/birthday.c
@@ -13,8 +13,8 @@ static uint64_t seed = 12345;
static void test_repeats(void)
{
enum {BITS = 46, BITS_TEST = BITS/2 + 2};
- const static uint64_t N = 1ull << BITS_TEST;
- const static uint64_t mask = (1ull << BITS) - 1;
+ static const uint64_t N = 1ull << BITS_TEST;
+ static const uint64_t mask = (1ull << BITS) - 1;
printf("birthday paradox: value range: 2^%d, testing repeats of 2^%d values\n", BITS, BITS_TEST);
crand_t rng = crand_init(seed);
@@ -60,7 +60,7 @@ void test_distribution(void)
cmap_x_drop(&map);
}
-int main()
+int main(void)
{
seed = (uint64_t)time(NULL);
test_distribution();
diff --git a/misc/examples/bits2.c b/misc/examples/bits2.c
index 913bd185..de2f16f4 100644
--- a/misc/examples/bits2.c
+++ b/misc/examples/bits2.c
@@ -5,7 +5,7 @@
#define i_capacity 80 // enable fixed bitset on the stack
#include <stc/cbits.h>
-int main()
+int main(void)
{
Bits s1 = Bits_from("1110100110111");
diff --git a/misc/examples/books.c b/misc/examples/books.c
index a62769b0..1fd57f27 100644
--- a/misc/examples/books.c
+++ b/misc/examples/books.c
@@ -1,4 +1,5 @@
// https://doc.rust-lang.org/std/collections/struct.HashMap.html
+#define i_implement
#include <stc/cstr.h>
#define i_key_str
#define i_val_str
@@ -6,7 +7,7 @@
// Type inference lets us omit an explicit type signature (which
// would be `HashMap<String, String>` in this example).
-int main()
+int main(void)
{
cmap_str book_reviews = {0};
diff --git a/misc/examples/box.c b/misc/examples/box.c
index 9954883c..94d126c0 100644
--- a/misc/examples/box.c
+++ b/misc/examples/box.c
@@ -1,10 +1,11 @@
/* cbox: heap allocated boxed type */
+#define i_implement
#include <stc/cstr.h>
typedef struct { cstr name, last; } Person;
Person Person_make(const char* name, const char* last) {
- return (Person){.name = cstr_from(name), .last = cstr_from(last)};
+ return c_LITERAL(Person){.name = cstr_from(name), .last = cstr_from(last)};
}
uint64_t Person_hash(const Person* a) {
@@ -28,14 +29,14 @@ void Person_drop(Person* p) {
}
#define i_type PBox
-#define i_valclass Person // "class" binds _cmp, _clone, _drop functions.
+#define i_keyclass Person // "class" binds _cmp, _clone, _drop functions.
#include <stc/cbox.h>
#define i_type Persons
-#define i_valboxed PBox // "arcbox" informs that PBox is a smart pointer.
+#define i_keyboxed PBox // "arcbox" informs that PBox is a smart pointer.
#include <stc/csset.h>
-int main()
+int main(void)
{
Persons vec = {0};
PBox p = PBox_from(Person_make("Laura", "Palmer"));
diff --git a/misc/examples/box2.c b/misc/examples/box2.c
index cba255d2..eaab1c47 100644
--- a/misc/examples/box2.c
+++ b/misc/examples/box2.c
@@ -13,27 +13,25 @@ typedef struct {
Point bottom_right;
} Rectangle;
-#define i_val Point
-#define i_no_cmp
+#define i_key Point
#include <stc/cbox.h> // cbox_Point
-#define i_val Rectangle
-#define i_no_cmp
+#define i_key Rectangle
#include <stc/cbox.h> // cbox_Rectangle
// Box in box:
-#define i_valboxed cbox_Point // NB: use i_valboxed when value is a cbox or carc!
#define i_type BoxBoxPoint
+#define i_keyboxed cbox_Point // NB: use i_keyboxed when value is a cbox or carc!
#define i_no_cmp
#include <stc/cbox.h> // BoxBoxPoint
Point origin(void) {
- return (Point){ .x=1.0, .y=2.0 };
+ return c_LITERAL(Point){ .x=1.0, .y=2.0 };
}
cbox_Point boxed_origin(void) {
// Allocate this point on the heap, and return a pointer to it
- return cbox_Point_make((Point){ .x=1.0, .y=2.0 });
+ return cbox_Point_make(c_LITERAL(Point){ .x=1.0, .y=2.0 });
}
@@ -46,7 +44,7 @@ int main(void) {
};
// Heap allocated rectangle
- cbox_Rectangle boxed_rectangle = cbox_Rectangle_make((Rectangle){
+ cbox_Rectangle boxed_rectangle = cbox_Rectangle_make(c_LITERAL(Rectangle){
.top_left = origin(),
.bottom_right = { .x=3.0, .y=-4.0 }
});
diff --git a/misc/examples/cointerleave.c b/misc/examples/cointerleave.c
new file mode 100644
index 00000000..599ceaab
--- /dev/null
+++ b/misc/examples/cointerleave.c
@@ -0,0 +1,62 @@
+// https://www.youtube.com/watch?v=8sEe-4tig_A
+#include <stdio.h>
+#include <stc/calgo.h>
+#define i_type IVec
+#define i_key int
+#include <stc/cvec.h>
+
+struct GenValue {
+ IVec *v;
+ IVec_iter it;
+ int cco_state;
+};
+
+static int get_value(struct GenValue* g)
+{
+ cco_routine(g) {
+ for (g->it = IVec_begin(g->v); g->it.ref; IVec_next(&g->it))
+ cco_yield_v(*g->it.ref);
+ }
+ return -1;
+}
+
+struct Generator {
+ struct GenValue x, y;
+ int cco_state;
+ int value;
+};
+
+cco_result interleaved(struct Generator* g)
+{
+ cco_routine(g) {
+ while (!(cco_done(&g->x) & cco_done(&g->y))) {
+ g->value = get_value(&g->x);
+ if (!cco_done(&g->x))
+ cco_yield();
+
+ g->value = get_value(&g->y);
+ if (!cco_done(&g->y))
+ cco_yield();
+ }
+ }
+ return CCO_DONE;
+}
+
+void Use(void)
+{
+ IVec a = c_init(IVec, {2, 4, 6, 8, 10, 11});
+ IVec b = c_init(IVec, {3, 5, 7, 9});
+
+ struct Generator g = {{&a}, {&b}};
+
+ cco_block_on(interleaved(&g)) {
+ printf("%d ", g.value);
+ }
+ puts("");
+ c_drop(IVec, &a, &b);
+}
+
+int main(void)
+{
+ Use();
+}
diff --git a/misc/examples/complex.c b/misc/examples/complex.c
index 7dde981d..4eb1574b 100644
--- a/misc/examples/complex.c
+++ b/misc/examples/complex.c
@@ -5,17 +5,16 @@
// using StackList = std::stack<FloatStack>;
// using ListMap = std::unordered_map<int, std::forward_list<StackList>>;
// using MapMap = std::unordered_map<std::string, ListMap>;
-
+#define i_implement
#include <stc/cstr.h>
-
#define i_type FloatStack
-#define i_val float
+#define i_key float
#include <stc/cstack.h>
#define i_type StackList
-#define i_valclass FloatStack // "class" picks up _clone, _drop
-#define i_opt c_no_cmp // no FloatStack_cmp()
+#define i_keyclass FloatStack // "class" picks up _clone, _drop, _cmp
+#define i_opt c_no_cmp // exclude FloatStack_cmp(): not defined
#include <stc/clist.h>
#define i_type ListMap
@@ -29,7 +28,7 @@
#include <stc/cmap.h>
-int main()
+int main(void)
{
MapMap mmap = {0};
@@ -44,7 +43,7 @@ int main()
const ListMap* lmap_p = MapMap_at(&mmap, "first");
const StackList* list_p = ListMap_at(lmap_p, 42);
const FloatStack* stack_p = StackList_back(list_p);
- printf("value is: %f\n", *FloatStack_at(stack_p, 3)); // pi
+ printf("value is: %f\n", (double)*FloatStack_at(stack_p, 3)); // pi
MapMap_drop(&mmap);
}
diff --git a/misc/examples/convert.c b/misc/examples/convert.c
index 0f09e830..fa64560e 100644
--- a/misc/examples/convert.c
+++ b/misc/examples/convert.c
@@ -1,17 +1,17 @@
+#define i_implement
#include <stc/cstr.h>
#define i_key_str
#define i_val_str
#include <stc/cmap.h>
-#define i_val_str
+#define i_key_str
#include <stc/cvec.h>
-#define i_val_str
-#define i_extern // define _clist_mergesort() once
+#define i_key_str
#include <stc/clist.h>
-int main()
+int main(void)
{
cmap_str map, mclone;
cvec_str keys = {0}, values = {0};
@@ -24,7 +24,7 @@ int main()
cvec_str_drop(&values),
clist_str_drop(&list)
){
- map = c_make(cmap_str, {
+ map = c_init(cmap_str, {
{"green", "#00ff00"},
{"blue", "#0000ff"},
{"yellow", "#ffff00"},
diff --git a/misc/examples/coread.c b/misc/examples/coread.c
index 0a7f4816..a13f6be5 100644
--- a/misc/examples/coread.c
+++ b/misc/examples/coread.c
@@ -1,39 +1,41 @@
+#define i_implement
#include <stc/cstr.h>
#include <stc/algo/coroutine.h>
#include <errno.h>
// Read file line by line using coroutines:
-struct file_nextline {
+struct file_read {
const char* filename;
int cco_state;
FILE* fp;
cstr line;
};
-bool file_nextline(struct file_nextline* U)
+int file_read(struct file_read* g)
{
- cco_begin(U)
- U->fp = fopen(U->filename, "r");
- U->line = cstr_init();
+ cco_routine(g) {
+ g->fp = fopen(g->filename, "r");
+ if (!g->fp) cco_return;
+ g->line = cstr_init();
- while (cstr_getline(&U->line, U->fp))
- cco_yield(true);
+ cco_await(!cstr_getline(&g->line, g->fp));
- cco_final: // this label is required.
- printf("finish\n");
- cstr_drop(&U->line);
- fclose(U->fp);
- cco_end(false);
+ cco_cleanup:
+ printf("finish\n");
+ cstr_drop(&g->line);
+ if (g->fp) fclose(g->fp);
+ }
+ return 0;
}
int main(void)
{
- struct file_nextline it = {__FILE__};
+ struct file_read g = {__FILE__};
int n = 0;
- while (file_nextline(&it))
+ cco_block_on(file_read(&g))
{
- printf("%3d %s\n", ++n, cstr_str(&it.line));
- //if (n == 10) cco_stop(&it);
+ printf("%3d %s\n", ++n, cstr_str(&g.line));
+ //if (n == 10) cco_stop(&g);
}
}
diff --git a/misc/examples/coroutines.c b/misc/examples/coroutines.c
index b11b8532..b8dfaa13 100644
--- a/misc/examples/coroutines.c
+++ b/misc/examples/coroutines.c
@@ -5,38 +5,39 @@
// Demonstrate to call another coroutine from a coroutine:
// First create prime generator, then call fibonacci sequence:
-bool is_prime(int64_t i) {
- for (int64_t j=2; j*j <= i; ++j)
+bool is_prime(long long i) {
+ for (long long j=2; j*j <= i; ++j)
if (i % j == 0) return false;
return true;
}
struct prime {
int count, idx;
- int64_t result, pos;
+ long long result, pos;
int cco_state;
};
-bool prime(struct prime* U) {
- cco_begin(U);
- if (U->result < 2) U->result = 2;
- if (U->result == 2) {
- if (U->count-- == 0) cco_return;
- ++U->idx;
- cco_yield(true);
+int prime(struct prime* g) {
+ cco_routine(g) {
+ if (g->result < 2) g->result = 2;
+ if (g->result == 2) {
+ if (g->count-- == 0) cco_return;
+ ++g->idx;
+ cco_yield();
}
- U->result += !(U->result & 1);
- for (U->pos = U->result; U->count > 0; U->pos += 2) {
- if (is_prime(U->pos)) {
- --U->count;
- ++U->idx;
- U->result = U->pos;
- cco_yield(true);
+ g->result += !(g->result & 1);
+ for (g->pos = g->result; g->count > 0; g->pos += 2) {
+ if (is_prime(g->pos)) {
+ --g->count;
+ ++g->idx;
+ g->result = g->pos;
+ cco_yield();
}
}
- cco_final:
- printf("final prm\n");
- cco_end(false);
+ cco_cleanup:
+ printf("final prm\n");
+ }
+ return 0;
}
@@ -44,30 +45,33 @@ bool prime(struct prime* U) {
struct fibonacci {
int count, idx;
- int64_t result, b;
+ long long result, b;
int cco_state;
};
-bool fibonacci(struct fibonacci* F) {
- assert(F->count < 94);
+int fibonacci(struct fibonacci* g) {
+ assert(g->count < 94);
- cco_begin(F);
- F->idx = 0;
- F->result = 0;
- F->b = 1;
+ long long sum;
+ cco_routine(g) {
+ g->idx = 0;
+ g->result = 0;
+ g->b = 1;
for (;;) {
- if (F->count-- == 0)
+ if (g->count-- == 0)
cco_return;
- if (++F->idx > 1) {
- int64_t sum = F->result + F->b; // NB! locals only lasts until next cco_yield!
- F->result = F->b;
- F->b = sum;
+ if (++g->idx > 1) {
+ // NB! locals lasts only until next yield/await!
+ sum = g->result + g->b;
+ g->result = g->b;
+ g->b = sum;
}
- cco_yield(true);
+ cco_yield();
}
- cco_final:
- printf("final fib\n");
- cco_end(false);
+ cco_cleanup:
+ printf("final fib\n");
+ }
+ return 0;
}
// Combine
@@ -78,29 +82,31 @@ struct combined {
int cco_state;
};
-bool combined(struct combined* C) {
- cco_begin(C);
- cco_yield(prime(&C->prm), &C->prm, true);
- cco_yield(fibonacci(&C->fib), &C->fib, true);
+int combined(struct combined* g) {
+ cco_routine(g) {
+ cco_await_on(prime(&g->prm));
+ cco_await_on(fibonacci(&g->fib));
- // Reuse the C->prm context and extend the count:
- C->prm.count = 8; C->prm.result += 2;
- cco_reset(&C->prm);
- cco_yield(prime(&C->prm), &C->prm, true);
+ // Reuse the g->prm context and extend the count:
+ g->prm.count = 8, g->prm.result += 2;
+ cco_reset(&g->prm);
+ cco_await_on(prime(&g->prm));
- cco_final: puts("final comb");
- cco_end(false);
+ cco_cleanup:
+ puts("final combined");
+ }
+ return 0;
}
-int main(void) {
- struct combined comb = {.prm={.count=8}, .fib={14}};
- if (true)
- while (combined(&comb))
+int main(void)
+{
+ struct combined c = {.prm={.count=8}, .fib={14}};
+ int res;
+
+ cco_block_on(combined(&c), &res) {
+ if (res == CCO_YIELD)
printf("Prime(%d)=%lld, Fib(%d)=%lld\n",
- comb.prm.idx, (long long)comb.prm.result,
- comb.fib.idx, (long long)comb.fib.result);
- else
- while (prime(&comb.prm))
- printf("Prime(%d)=%lld\n",
- comb.prm.idx, (long long)comb.prm.result);
+ c.prm.idx, c.prm.result,
+ c.fib.idx, c.fib.result);
+ }
}
diff --git a/misc/examples/csmap_erase.c b/misc/examples/csmap_erase.c
index 697e6c09..8d4eeae3 100644
--- a/misc/examples/csmap_erase.c
+++ b/misc/examples/csmap_erase.c
@@ -1,5 +1,6 @@
// map_erase.c
// From C++ example: https://docs.microsoft.com/en-us/cpp/standard-library/map-class?view=msvc-160#example-16
+#define i_implement
#include <stc/cstr.h>
#include <stdio.h>
@@ -15,7 +16,7 @@ void printmap(mymap m)
printf("\nsize() == %" c_ZI "\n\n", mymap_size(&m));
}
-int main()
+int main(void)
{
mymap m1 = {0};
@@ -34,7 +35,7 @@ int main()
printmap(m1);
// Fill in some data to test with
- mymap m2 = c_make(mymap, {
+ mymap m2 = c_init(mymap, {
{10, "Bob"},
{11, "Rob"},
{12, "Robert"},
diff --git a/misc/examples/csmap_find.c b/misc/examples/csmap_find.c
index c417567a..c392338d 100644
--- a/misc/examples/csmap_find.c
+++ b/misc/examples/csmap_find.c
@@ -1,5 +1,6 @@
// This implements the c++ std::map::find example at:
// https://docs.microsoft.com/en-us/cpp/standard-library/map-class?view=msvc-160#example-17
+#define i_implement
#include <stc/cstr.h>
#define i_key int
@@ -7,8 +8,7 @@
#define i_tag istr
#include <stc/csmap.h>
-#define i_val csmap_istr_raw
-#define i_opt c_no_cmp
+#define i_key csmap_istr_raw
#define i_tag istr
#include <stc/cvec.h>
@@ -40,21 +40,21 @@ void findit(csmap_istr c, csmap_istr_key val)
}
}
-int main()
+int main(void)
{
- csmap_istr m1 = c_make(csmap_istr, {{40, "Zr"}, {45, "Rh"}});
+ csmap_istr m1 = c_init(csmap_istr, {{40, "Zr"}, {45, "Rh"}});
cvec_istr v = {0};
puts("The starting map m1 is (key, value):");
print_collection_csmap_istr(&m1);
typedef cvec_istr_value pair;
- cvec_istr_push(&v, (pair){43, "Tc"});
- cvec_istr_push(&v, (pair){41, "Nb"});
- cvec_istr_push(&v, (pair){46, "Pd"});
- cvec_istr_push(&v, (pair){42, "Mo"});
- cvec_istr_push(&v, (pair){44, "Ru"});
- cvec_istr_push(&v, (pair){44, "Ru"}); // attempt a duplicate
+ cvec_istr_push(&v, c_LITERAL(pair){43, "Tc"});
+ cvec_istr_push(&v, c_LITERAL(pair){41, "Nb"});
+ cvec_istr_push(&v, c_LITERAL(pair){46, "Pd"});
+ cvec_istr_push(&v, c_LITERAL(pair){42, "Mo"});
+ cvec_istr_push(&v, c_LITERAL(pair){44, "Ru"});
+ cvec_istr_push(&v, c_LITERAL(pair){44, "Ru"}); // attempt a duplicate
puts("Inserting the following vector data into m1:");
print_collection_cvec_istr(&v);
diff --git a/misc/examples/csmap_insert.c b/misc/examples/csmap_insert.c
index 3da245c7..c9f02891 100644
--- a/misc/examples/csmap_insert.c
+++ b/misc/examples/csmap_insert.c
@@ -5,13 +5,14 @@
#define i_tag ii // Map of int => int
#include <stc/csmap.h>
+#define i_implement
#include <stc/cstr.h>
#define i_key int
#define i_val_str
#define i_tag istr // Map of int => cstr
#include <stc/csmap.h>
-#define i_val csmap_ii_raw
+#define i_key csmap_ii_raw
#define i_opt c_no_cmp
#define i_tag ii
#include <stc/cvec.h>
@@ -28,12 +29,12 @@ void print_istr(csmap_istr map) {
puts("");
}
-int main()
+int main(void)
{
// insert single values
csmap_ii m1 = {0};
csmap_ii_insert(&m1, 1, 10);
- csmap_ii_push(&m1, (csmap_ii_value){2, 20});
+ csmap_ii_push(&m1, c_LITERAL(csmap_ii_value){2, 20});
puts("The original key and mapped values of m1 are:");
print_ii(m1);
@@ -60,11 +61,11 @@ int main()
csmap_ii m2 = {0};
cvec_ii v = {0};
typedef cvec_ii_value ipair;
- cvec_ii_push(&v, (ipair){43, 294});
- cvec_ii_push(&v, (ipair){41, 262});
- cvec_ii_push(&v, (ipair){45, 330});
- cvec_ii_push(&v, (ipair){42, 277});
- cvec_ii_push(&v, (ipair){44, 311});
+ cvec_ii_push(&v, c_LITERAL(ipair){43, 294});
+ cvec_ii_push(&v, c_LITERAL(ipair){41, 262});
+ cvec_ii_push(&v, c_LITERAL(ipair){45, 330});
+ cvec_ii_push(&v, c_LITERAL(ipair){42, 277});
+ cvec_ii_push(&v, c_LITERAL(ipair){44, 311});
puts("Inserting the following vector data into m2:");
c_foreach (e, cvec_ii, v)
@@ -96,7 +97,7 @@ int main()
csmap_ii m4 = {0};
// Insert the elements from an initializer_list
- m4 = c_make(csmap_ii, {{4, 44}, {2, 22}, {3, 33}, {1, 11}, {5, 55}});
+ m4 = c_init(csmap_ii, {{4, 44}, {2, 22}, {3, 33}, {1, 11}, {5, 55}});
puts("After initializer_list insertion, m4 contains:");
print_ii(m4);
puts("");
diff --git a/misc/examples/csset_erase.c b/misc/examples/csset_erase.c
index 9fa40682..9c7f5e1a 100644
--- a/misc/examples/csset_erase.c
+++ b/misc/examples/csset_erase.c
@@ -3,9 +3,9 @@
#define i_key int
#include <stc/csset.h>
-int main()
+int main(void)
{
- csset_int set = c_make(csset_int, {30, 20, 80, 40, 60, 90, 10, 70, 50});
+ csset_int set = c_init(csset_int, {30, 20, 80, 40, 60, 90, 10, 70, 50});
c_foreach (k, csset_int, set)
printf(" %d", *k.ref);
@@ -38,4 +38,4 @@ int main()
puts("");
csset_int_drop(&set);
-} \ No newline at end of file
+}
diff --git a/misc/examples/cstr_match.c b/misc/examples/cstr_match.c
index 58cf8884..be03e981 100644
--- a/misc/examples/cstr_match.c
+++ b/misc/examples/cstr_match.c
@@ -1,8 +1,9 @@
+#define i_implement
#include <stc/cstr.h>
#include <stc/csview.h>
#include <stdio.h>
-int main()
+int main(void)
{
cstr ss = cstr_lit("The quick brown fox jumps over the lazy dog.JPG");
diff --git a/misc/examples/demos.c b/misc/examples/demos.c
index de92e378..ecc89f2e 100644
--- a/misc/examples/demos.c
+++ b/misc/examples/demos.c
@@ -1,6 +1,7 @@
+#define i_implement
#include <stc/cstr.h>
-void stringdemo1()
+void stringdemo1(void)
{
cstr cs = cstr_lit("one-nine-three-seven-five");
printf("%s.\n", cstr_str(&cs));
@@ -27,11 +28,11 @@ void stringdemo1()
cstr_drop(&cs);
}
-#define i_val int64_t
+#define i_key int64_t
#define i_tag ix
#include <stc/cvec.h>
-void vectordemo1()
+void vectordemo1(void)
{
cvec_ix bignums = cvec_ix_with_capacity(100);
cvec_ix_reserve(&bignums, 100);
@@ -51,10 +52,10 @@ void vectordemo1()
cvec_ix_drop(&bignums);
}
-#define i_val_str
+#define i_key_str
#include <stc/cvec.h>
-void vectordemo2()
+void vectordemo2(void)
{
cvec_str names = {0};
cvec_str_emplace_back(&names, "Mary");
@@ -71,11 +72,12 @@ void vectordemo2()
cvec_str_drop(&names);
}
-#define i_val int
+#define i_key int
#define i_tag ix
+#define i_native_cmp
#include <stc/clist.h>
-void listdemo1()
+void listdemo1(void)
{
clist_ix nums = {0}, nums2 = {0};
for (int i = 0; i < 10; ++i)
@@ -107,7 +109,7 @@ void listdemo1()
#define i_tag i
#include <stc/cset.h>
-void setdemo1()
+void setdemo1(void)
{
cset_i nums = {0};
cset_i_insert(&nums, 8);
@@ -123,7 +125,7 @@ void setdemo1()
#define i_tag ii
#include <stc/cmap.h>
-void mapdemo1()
+void mapdemo1(void)
{
cmap_ii nums = {0};
cmap_ii_insert(&nums, 8, 64);
@@ -137,7 +139,7 @@ void mapdemo1()
#define i_tag si
#include <stc/cmap.h>
-void mapdemo2()
+void mapdemo2(void)
{
cmap_si nums = {0};
cmap_si_emplace_or_assign(&nums, "Hello", 64);
@@ -159,7 +161,7 @@ void mapdemo2()
#define i_val_str
#include <stc/cmap.h>
-void mapdemo3()
+void mapdemo3(void)
{
cmap_str table = {0};
cmap_str_emplace(&table, "Map", "test");
@@ -179,7 +181,7 @@ void mapdemo3()
cmap_str_drop(&table); // frees key and value cstrs, and hash table.
}
-int main()
+int main(void)
{
printf("\nSTRINGDEMO1\n"); stringdemo1();
printf("\nVECTORDEMO1\n"); vectordemo1();
diff --git a/misc/examples/dining_philosophers.c b/misc/examples/dining_philosophers.c
new file mode 100644
index 00000000..a5063a42
--- /dev/null
+++ b/misc/examples/dining_philosophers.c
@@ -0,0 +1,105 @@
+// https://en.wikipedia.org/wiki/Dining_philosophers_problem
+#include <stdio.h>
+#include <time.h>
+#include <stc/crand.h>
+#include <stc/algo/coroutine.h>
+
+// Define the number of philosophers and forks
+enum {
+ num_philosophers = 5,
+ num_forks = num_philosophers,
+};
+
+struct Philosopher {
+ int id;
+ cco_timer tm;
+ cco_sem* left_fork;
+ cco_sem* right_fork;
+ int cco_state; // required
+};
+
+struct Dining {
+ // Define semaphores for the forks
+ cco_sem forks[num_forks];
+ struct Philosopher ph[num_philosophers];
+ int cco_state; // required
+};
+
+
+// Philosopher coroutine
+int philosopher(struct Philosopher* p)
+{
+ double duration;
+ cco_routine(p) {
+ while (1) {
+ duration = 1.0 + crandf()*2.0;
+ printf("Philosopher %d is thinking for %.0f minutes...\n", p->id, duration*10);
+ cco_timer_await(&p->tm, duration);
+
+ printf("Philosopher %d is hungry...\n", p->id);
+ cco_sem_await(p->left_fork);
+ cco_sem_await(p->right_fork);
+
+ duration = 0.5 + crandf();
+ printf("Philosopher %d is eating for %.0f minutes...\n", p->id, duration*10);
+ cco_timer_await(&p->tm, duration);
+
+ cco_sem_release(p->left_fork);
+ cco_sem_release(p->right_fork);
+ }
+
+ cco_cleanup:
+ printf("Philosopher %d finished\n", p->id);
+ }
+ return 0;
+}
+
+
+// Dining coroutine
+int dining(struct Dining* d)
+{
+ cco_routine(d) {
+ for (int i = 0; i < num_forks; ++i)
+ cco_sem_set(&d->forks[i], 1); // all forks available
+ for (int i = 0; i < num_philosophers; ++i) {
+ cco_reset(&d->ph[i]);
+ d->ph[i].id = i + 1;
+ d->ph[i].left_fork = &d->forks[i];
+ d->ph[i].right_fork = &d->forks[(i + 1) % num_forks];
+ }
+
+ while (1) {
+ // per-"frame" logic resume each philosopher
+ for (int i = 0; i < num_philosophers; ++i) {
+ philosopher(&d->ph[i]);
+ }
+ cco_yield(); // suspend, return control back to main
+ }
+
+ cco_cleanup:
+ for (int i = 0; i < num_philosophers; ++i) {
+ cco_stop(&d->ph[i]);
+ philosopher(&d->ph[i]);
+ }
+ puts("Dining finished");
+ }
+ return 0;
+}
+
+int main(void)
+{
+ struct Dining dine;
+ cco_reset(&dine);
+ int n=0;
+ cco_timer tm = cco_timer_from(15.0); // seconds
+ csrand((uint64_t)time(NULL));
+
+ while (!cco_done(&dine)) {
+ if (cco_timer_expired(&tm))
+ cco_stop(&dine);
+ dining(&dine); // resume
+ cco_sleep(0.001);
+ ++n;
+ }
+ printf("n=%d\n", n);
+}
diff --git a/misc/examples/forfilter.c b/misc/examples/forfilter.c
index fbb7280f..f3c008b3 100644
--- a/misc/examples/forfilter.c
+++ b/misc/examples/forfilter.c
@@ -1,12 +1,13 @@
#include <stdio.h>
-#define i_extern
+#define i_import
#include <stc/cstr.h>
+#define i_implement
#include <stc/csview.h>
#include <stc/algo/filter.h>
#include <stc/algo/crange.h>
#define i_type IVec
-#define i_val int
+#define i_key int
#include <stc/cstack.h>
// filters and transforms:
@@ -17,7 +18,7 @@
void demo1(void)
{
- IVec vec = c_make(IVec, {0, 1, 2, 3, 4, 5, 80, 6, 7, 80, 8, 9, 80,
+ IVec vec = c_init(IVec, {0, 1, 2, 3, 4, 5, 80, 6, 7, 80, 8, 9, 80,
10, 11, 12, 13, 14, 15, 80, 16, 17});
c_forfilter (i, IVec, vec, flt_skipValue(i, 80))
@@ -54,7 +55,8 @@ fn main() {
void demo2(void)
{
IVec vector = {0};
- c_forfilter (x, crange, crange_obj(INT64_MAX),
+ crange r = crange_make(INT64_MAX);
+ c_forfilter (x, crange, r,
c_flt_skipwhile(x, *x.ref != 11) &&
(*x.ref % 2) != 0 &&
c_flt_take(x, 5)
@@ -81,7 +83,7 @@ fn main() {
}
*/
#define i_type SVec
-#define i_valclass csview
+#define i_keyclass csview
#include <stc/cstack.h>
void demo3(void)
diff --git a/misc/examples/forloops.c b/misc/examples/forloops.c
index 1fc00614..47cced8f 100644
--- a/misc/examples/forloops.c
+++ b/misc/examples/forloops.c
@@ -2,7 +2,7 @@
#include <stc/algo/filter.h>
#define i_type IVec
-#define i_val int
+#define i_key int
#include <stc/cstack.h>
#define i_type IMap
@@ -11,7 +11,7 @@
#include <stc/cmap.h>
-int main()
+int main(void)
{
puts("c_forrange:");
c_forrange (30) printf(" xx");
@@ -34,8 +34,8 @@ int main()
printf(" %s", *i.ref);
puts("");
- IVec vec = c_make(IVec, {12, 23, 453, 65, 113, 215, 676, 34, 67, 20, 27, 66, 189, 45, 280, 199});
- IMap map = c_make(IMap, {{12, 23}, {453, 65}, {676, 123}, {34, 67}});
+ IVec vec = c_init(IVec, {12, 23, 453, 65, 113, 215, 676, 34, 67, 20, 27, 66, 189, 45, 280, 199});
+ IMap map = c_init(IMap, {{12, 23}, {453, 65}, {676, 123}, {34, 67}});
puts("\n\nc_foreach:");
c_foreach (i, IVec, vec)
diff --git a/misc/examples/functor.c b/misc/examples/functor.c
index c0a4f8e8..e3bde1dd 100644
--- a/misc/examples/functor.c
+++ b/misc/examples/functor.c
@@ -1,22 +1,22 @@
// Implements c++ example: https://en.cppreference.com/w/cpp/container/priority_queue
// Example of per-instance less-function on a single priority queue type
//
-// Note: i_less: has self for cpque types only
-// i_cmp: has self for csmap and csset types only
-// i_hash/i_eq: has self for cmap and cset types only
#include <stdio.h>
#define i_type IPQue
-#define i_val int
-#define i_extend bool (*less)(const int*, const int*);
-#define i_less(x, y) c_getcon(self)->less(x, y)
-#define i_con cpque
+#define i_base cpque
+#define i_key int
+#define i_extend bool(*less)(const int*, const int*);
+#define i_less(x, y) c_extend()->less(x, y)
+// Note: i_less: c_extend() accessible for cpque types
+// i_cmp: c_extend() accessible for csmap and csset types
+// i_hash/i_eq: c_extend() accessible for cmap and cset types
#include <stc/extend.h>
void print_queue(const char* name, IPQue_ext q) {
// NB: make a clone because there is no way to traverse
- // priority_queue's content without erasing the queue.
+ // priority queue's content without erasing the queue.
IPQue_ext copy = {q.less, IPQue_clone(q.get)};
for (printf("%s: \t", name); !IPQue_empty(&copy.get); IPQue_pop(&copy.get))
@@ -30,28 +30,27 @@ static bool int_less(const int* x, const int* y) { return *x < *y; }
static bool int_greater(const int* x, const int* y) { return *x > *y; }
static bool int_lambda(const int* x, const int* y) { return (*x ^ 1) < (*y ^ 1); }
-int main()
+int main(void)
{
const int data[] = {1,8,5,6,3,4,0,9,7,2}, n = c_arraylen(data);
printf("data: \t");
- c_forrange (i, n)
- printf("%d ", data[i]);
+ c_forrange (i, n) printf("%d ", data[i]);
puts("");
- IPQue_ext q1 = {int_less}; // Max priority queue
- IPQue_ext minq1 = {int_greater}; // Min priority queue
- IPQue_ext q5 = {int_lambda}; // Using lambda to compare elements.
- c_forrange (i, n)
- IPQue_push(&q1.get, data[i]);
+ // Max priority queue
+ IPQue_ext q1 = {.less=int_less};
+ IPQue_put_n(&q1.get, data, n);
print_queue("q1", q1);
- c_forrange (i, n)
- IPQue_push(&minq1.get, data[i]);
+ // Min priority queue
+ IPQue_ext minq1 = {.less=int_greater};
+ IPQue_put_n(&minq1.get, data, n);
print_queue("minq1", minq1);
- c_forrange (i, n)
- IPQue_push(&q5.get, data[i]);
+ // Using lambda to compare elements.
+ IPQue_ext q5 = {.less=int_lambda};
+ IPQue_put_n(&q5.get, data, n);
print_queue("q5", q5);
c_drop(IPQue, &q1.get, &minq1.get, &q5.get);
diff --git a/misc/examples/gauss2.c b/misc/examples/gauss2.c
index df709d03..1ab8ade5 100644
--- a/misc/examples/gauss2.c
+++ b/misc/examples/gauss2.c
@@ -1,20 +1,21 @@
#include <stdio.h>
#include <time.h>
-#include <stc/crand.h>
+#define i_implement
#include <stc/cstr.h>
+#include <stc/crand.h>
// Declare int -> int sorted map.
#define i_key int
#define i_val int
#include <stc/csmap.h>
-int main()
+int main(void)
{
enum {N = 5000000};
uint64_t seed = (uint64_t)time(NULL);
crand_t rng = crand_init(seed);
- const double Mean = round(crand_f64(&rng)*98.f - 49.f), StdDev = crand_f64(&rng)*10.f + 1.f, Scale = 74.f;
+ const double Mean = round(crand_f64(&rng)*98.0 - 49.0), StdDev = crand_f64(&rng)*10.0 + 1.0, Scale = 74.0;
printf("Demo of gaussian / normal distribution of %d random samples\n", N);
printf("Mean %f, StdDev %f\n", Mean, StdDev);
diff --git a/misc/examples/generator.c b/misc/examples/generator.c
index 2bccc489..a15f9ba5 100644
--- a/misc/examples/generator.c
+++ b/misc/examples/generator.c
@@ -4,49 +4,51 @@
#include <stdio.h>
typedef struct {
- int n;
+ int size;
int a, b, c;
-} Triple_value, Triple;
+} Triple, Triple_value;
typedef struct {
Triple_value* ref;
+ int count;
int cco_state;
} Triple_iter;
-bool Triple_next(Triple_iter* it) {
- Triple_value* t = it->ref;
- cco_begin(it);
- for (t->c = 1;; ++t->c) {
- for (t->a = 1; t->a < t->c; ++t->a) {
- for (t->b = t->a; t->b < t->c; ++t->b) {
- if (t->a*t->a + t->b*t->b == t->c*t->c) {
- if (t->n-- == 0) cco_return;
- cco_yield(true);
+int Triple_next(Triple_iter* it) {
+ Triple_value* g = it->ref;
+ cco_routine(it)
+ {
+ for (g->c = 5; g->size; ++g->c) {
+ for (g->a = 1; g->a < g->c; ++g->a) {
+ for (g->b = g->a; g->b < g->c; ++g->b) {
+ if (g->a*g->a + g->b*g->b == g->c*g->c) {
+ if (it->count++ == g->size)
+ cco_return;
+ cco_yield();
}
}
}
}
- cco_final:
- it->ref = NULL;
- cco_end(false);
+ cco_cleanup:
+ it->ref = NULL;
+ }
+ return 0;
}
-Triple_iter Triple_begin(Triple* t) {
- Triple_iter it = {t};
- if (t->n > 0) Triple_next(&it);
- else it.ref = NULL;
+Triple_iter Triple_begin(Triple* g) {
+ Triple_iter it = {.ref=g};
+ Triple_next(&it);
return it;
}
-int main()
+int main(void)
{
puts("Pythagorean triples with c < 100:");
- Triple t = {INT32_MAX};
- c_foreach (i, Triple, t)
- {
+ Triple triple = {.size=30}; // max number of triples
+ c_foreach (i, Triple, triple) {
if (i.ref->c < 100)
- printf("%u: (%d, %d, %d)\n", INT32_MAX - i.ref->n + 1, i.ref->a, i.ref->b, i.ref->c);
+ printf("%u: (%d, %d, %d)\n", i.count, i.ref->a, i.ref->b, i.ref->c);
else
cco_stop(&i);
}
diff --git a/misc/examples/hashmap.c b/misc/examples/hashmap.c
index 47a3bcff..cf11b7f7 100644
--- a/misc/examples/hashmap.c
+++ b/misc/examples/hashmap.c
@@ -1,4 +1,5 @@
// https://doc.rust-lang.org/rust-by-example/std/hash.html
+#define i_implement
#include <stc/cstr.h>
#define i_key_str
#define i_val_str
diff --git a/misc/examples/inits.c b/misc/examples/inits.c
index 81bcdd3e..53a49f1f 100644
--- a/misc/examples/inits.c
+++ b/misc/examples/inits.c
@@ -1,3 +1,4 @@
+#define i_implement
#include <stc/cstr.h>
#define i_key int
@@ -17,18 +18,17 @@ inline static int ipair_cmp(const ipair_t* a, const ipair_t* b) {
}
-#define i_val ipair_t
+#define i_key ipair_t
#define i_cmp ipair_cmp
#define i_tag ip
#include <stc/cvec.h>
-#define i_val ipair_t
+#define i_key ipair_t
#define i_cmp ipair_cmp
#define i_tag ip
-#define i_extern // define _clist_mergesort() once
#include <stc/clist.h>
-#define i_val float
+#define i_key float
#define i_tag f
#include <stc/cpque.h>
@@ -45,7 +45,7 @@ int main(void)
puts("\npop and show high priorites first:");
while (! cpque_f_empty(&floats)) {
- printf("%.1f ", *cpque_f_top(&floats));
+ printf("%.1f ", (double)*cpque_f_top(&floats));
cpque_f_pop(&floats);
}
puts("\n");
@@ -66,7 +66,7 @@ int main(void)
// CMAP CNT
- cmap_cnt countries = c_make(cmap_cnt, {
+ cmap_cnt countries = c_init(cmap_cnt, {
{"Norway", 100},
{"Denmark", 50},
{"Iceland", 10},
@@ -88,7 +88,7 @@ int main(void)
// CVEC PAIR
- cvec_ip pairs1 = c_make(cvec_ip, {{5, 6}, {3, 4}, {1, 2}, {7, 8}});
+ cvec_ip pairs1 = c_init(cvec_ip, {{5, 6}, {3, 4}, {1, 2}, {7, 8}});
cvec_ip_sort(&pairs1);
c_foreach (i, cvec_ip, pairs1)
@@ -98,7 +98,7 @@ int main(void)
// CLIST PAIR
- clist_ip pairs2 = c_make(clist_ip, {{5, 6}, {3, 4}, {1, 2}, {7, 8}});
+ clist_ip pairs2 = c_init(clist_ip, {{5, 6}, {3, 4}, {1, 2}, {7, 8}});
clist_ip_sort(&pairs2);
c_foreach (i, clist_ip, pairs2)
diff --git a/misc/examples/intrusive.c b/misc/examples/intrusive.c
index 0f153589..80c1f63b 100644
--- a/misc/examples/intrusive.c
+++ b/misc/examples/intrusive.c
@@ -3,8 +3,9 @@
#include <stdio.h>
#define i_type List
-#define i_val int
-#include <stc/clist.h>
+#define i_key int
+#define i_native_cmp
+#include <stc/clist.h>
void printList(List list) {
printf("list:");
@@ -13,7 +14,7 @@ void printList(List list) {
puts("");
}
-int main() {
+int main(void) {
List list = {0};
c_forlist (i, int, {6, 9, 3, 1, 7, 4, 5, 2, 8})
List_push_back_node(&list, c_new(List_node, {.value=*i.ref}));
diff --git a/misc/examples/list.c b/misc/examples/list.c
index 363d7fec..fa33305a 100644
--- a/misc/examples/list.c
+++ b/misc/examples/list.c
@@ -4,10 +4,11 @@
#include <stc/crand.h>
#define i_type DList
-#define i_val double
+#define i_key double
+#define i_native_cmp
#include <stc/clist.h>
-int main() {
+int main(void) {
const int n = 3000000;
DList list = {0};
@@ -34,7 +35,7 @@ int main() {
puts("");
DList_drop(&list);
- list = c_make(DList, {10, 20, 30, 40, 30, 50});
+ list = c_init(DList, {10, 20, 30, 40, 30, 50});
const double* v = DList_get(&list, 30);
printf("found: %f\n", *v);
diff --git a/misc/examples/list_erase.c b/misc/examples/list_erase.c
index 0201c2d9..211c5a5d 100644
--- a/misc/examples/list_erase.c
+++ b/misc/examples/list_erase.c
@@ -2,12 +2,12 @@
#include <stdio.h>
#define i_type IList
-#define i_val int
+#define i_key int
#include <stc/clist.h>
-int main ()
+int main(void)
{
- IList L = c_make(IList, {10, 20, 30, 40, 50});
+ IList L = c_init(IList, {10, 20, 30, 40, 50});
c_foreach (x, IList, L)
printf("%d ", *x.ref);
diff --git a/misc/examples/list_splice.c b/misc/examples/list_splice.c
index baebca29..f1fd6e1f 100644
--- a/misc/examples/list_splice.c
+++ b/misc/examples/list_splice.c
@@ -1,8 +1,7 @@
#include <stdio.h>
-#define i_val int
+#define i_key int
#define i_tag i
-#define i_extern // define _clist_mergesort() once
#include <stc/clist.h>
void print_ilist(const char* s, clist_i list)
@@ -14,10 +13,10 @@ void print_ilist(const char* s, clist_i list)
puts("");
}
-int main ()
+int main(void)
{
- clist_i list1 = c_make(clist_i, {1, 2, 3, 4, 5});
- clist_i list2 = c_make(clist_i, {10, 20, 30, 40, 50});
+ clist_i list1 = c_init(clist_i, {1, 2, 3, 4, 5});
+ clist_i list2 = c_init(clist_i, {10, 20, 30, 40, 50});
print_ilist("list1:", list1);
print_ilist("list2:", list2);
diff --git a/misc/examples/lower_bound.c b/misc/examples/lower_bound.c
index 6ec7544c..e5d816e9 100644
--- a/misc/examples/lower_bound.c
+++ b/misc/examples/lower_bound.c
@@ -1,17 +1,18 @@
#include <stdio.h>
-#define i_val int
+#define i_key int
+#define i_native_cmp
#include <stc/cvec.h>
-#define i_val int
+#define i_key int
#include <stc/csset.h>
-int main()
+int main(void)
{
// TEST SORTED VECTOR
{
int key, *res;
- cvec_int vec = c_make(cvec_int, {40, 600, 1, 7000, 2, 500, 30});
+ cvec_int vec = c_init(cvec_int, {40, 600, 1, 7000, 2, 500, 30});
cvec_int_sort(&vec);
@@ -40,7 +41,7 @@ int main()
// TEST SORTED SET
{
int key, *res;
- csset_int set = c_make(csset_int, {40, 600, 1, 7000, 2, 500, 30});
+ csset_int set = c_init(csset_int, {40, 600, 1, 7000, 2, 500, 30});
key = 100;
res = csset_int_lower_bound(&set, key).ref;
diff --git a/misc/examples/make.sh b/misc/examples/make.sh
index b0c0bd52..cf224950 100755
--- a/misc/examples/make.sh
+++ b/misc/examples/make.sh
@@ -1,20 +1,19 @@
#!/bin/sh
if [ "$(uname)" = 'Linux' ]; then
- sanitize='-fsanitize=address'
+ sanitize='-fsanitize=address -fsanitize=undefined -fsanitize-trap'
clibs='-lm' # -pthread
oflag='-o '
fi
-cc=gcc; cflags="-s -O3 -std=c99 -Wconversion -Wpedantic -Wall -Wsign-compare -Wwrite-strings -Wno-maybe-uninitialized"
-#cc=gcc; cflags="-g -std=c99 -Werror -Wfatal-errors -Wpedantic -Wall $sanitize"
-#cc=tcc; cflags="-Wall -std=c99"
-#cc=clang; cflags="-s -O2 -std=c99 -Werror -Wfatal-errors -Wpedantic -Wall -Wno-unused-function -Wsign-compare -Wwrite-strings"
-#cc=gcc; cflags="-x c++ -s -O2 -Wall -std=c++20"
-#cc=g++; cflags="-x c++ -s -O2 -Wall"
-#cc=cl; cflags="-O2 -nologo -W3 -MD"
-#cc=cl; cflags="-nologo -TP"
-#cc=cl; cflags="-nologo -std:c11"
+cc=gcc; cflags="-std=c99 -s -O3 -Wall -Wextra -Wpedantic -Wconversion -Wwrite-strings -Wdouble-promotion -Wno-unused-parameter -Wno-maybe-uninitialized -Wno-implicit-fallthrough -Wno-missing-field-initializers"
+#cc=gcc; cflags="-std=c99 -g -Werror -Wfatal-errors -Wpedantic -Wall $sanitize"
+#cc=tcc; cflags="-std=c99 -Wall"
+#cc=clang; cflags="-std=c99 -s -O3 -Wall -Wextra -Wpedantic -Wconversion -Wwrite-strings -Wdouble-promotion -Wno-unused-parameter -Wno-unused-function -Wno-implicit-fallthrough -Wno-missing-field-initializers"
+#cc=gcc; cflags="-x c++ -std=c++20 -O2 -s -Wall"
+#cc=cl; cflags="-nologo -O2 -MD -W3 -wd4003"
+#cc=cl; cflags="-nologo -TP -std:c++20 -wd4003"
+#cc=cl; cflags="-nologo -std:c11 -wd4003"
if [ "$cc" = "cl" ]; then
oflag='/Fe:'
diff --git a/misc/examples/mapmap.c b/misc/examples/mapmap.c
index 668da5de..d3065659 100644
--- a/misc/examples/mapmap.c
+++ b/misc/examples/mapmap.c
@@ -1,5 +1,5 @@
// create a structure like: std::map<std::string, std::map<std::string, std::string>>:
-
+#define i_implement
#include <stc/cstr.h>
// People: std::map<std::string, std::string>
diff --git a/misc/examples/mmap.c b/misc/examples/mmap.c
index 0394a2df..04a605a7 100644
--- a/misc/examples/mmap.c
+++ b/misc/examples/mmap.c
@@ -2,8 +2,9 @@
// https://en.cppreference.com/w/cpp/container/multimap/insert
// Multimap entries
+#define i_implement
#include <stc/cstr.h>
-#define i_val_str
+#define i_key_str
#include <stc/clist.h>
// Map of int => clist_str.
@@ -29,7 +30,7 @@ void insert(Multimap* mmap, int key, const char* str)
clist_str_emplace_back(list, str);
}
-int main()
+int main(void)
{
Multimap mmap = {0};
diff --git a/misc/examples/multidim.c b/misc/examples/multidim.c
index 3980e6d8..798a1126 100644
--- a/misc/examples/multidim.c
+++ b/misc/examples/multidim.c
@@ -6,9 +6,9 @@
using_cspan3(ispan, int);
-int main()
+int main(void)
{
- cstack_int v = c_make(cstack_int, {1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24});
+ cstack_int v = c_init(cstack_int, {1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24});
// View data as contiguous memory representing 24 ints
ispan ms1 = cspan_from(&v);
@@ -28,7 +28,6 @@ int main()
}
puts("ss3 = ms3[:, 1:3, 1:3]");
ispan3 ss3 = ms3;
- //cspan_slice(&ss3, {c_ALL}, {1,3}, {1,3});
ss3 = cspan_slice(ispan3, &ms3, {c_ALL}, {1,3}, {1,3});
for (int i=0; i != ss3.shape[0]; i++) {
diff --git a/misc/examples/multimap.c b/misc/examples/multimap.c
index d8981a81..1068a5dc 100644
--- a/misc/examples/multimap.c
+++ b/misc/examples/multimap.c
@@ -1,3 +1,4 @@
+#define i_implement
#include <stc/cstr.h>
// Olympics multimap example
@@ -39,7 +40,7 @@ OlympicLoc OlympicLoc_clone(OlympicLoc loc);
void OlympicLoc_drop(OlympicLoc* self);
// Create a clist<OlympicLoc>, can be sorted by year.
-#define i_valclass OlympicLoc // binds _cmp, _clone and _drop.
+#define i_keyclass OlympicLoc // binds _cmp, _clone and _drop.
#define i_tag OL
#include <stc/clist.h>
@@ -65,7 +66,7 @@ void OlympicLoc_drop(OlympicLoc* self) {
}
-int main()
+int main(void)
{
// Define the multimap with destructor defered to when block is completed.
csmap_OL multimap = {0};
diff --git a/misc/examples/music_arc.c b/misc/examples/music_arc.c
index 3714e1d5..16111b0b 100644
--- a/misc/examples/music_arc.c
+++ b/misc/examples/music_arc.c
@@ -1,5 +1,6 @@
// shared_ptr-examples.cpp
// based on https://docs.microsoft.com/en-us/cpp/cpp/how-to-create-and-use-shared-ptr-instances?view=msvc-160
+#define i_implement
#include <stc/cstr.h>
typedef struct
@@ -12,7 +13,7 @@ int Song_cmp(const Song* x, const Song* y)
{ return cstr_cmp(&x->title, &y->title); }
Song Song_make(const char* artist, const char* title)
- { return (Song){cstr_from(artist), cstr_from(title)}; }
+ { return c_LITERAL(Song){cstr_from(artist), cstr_from(title)}; }
void Song_drop(Song* s) {
printf("drop: %s\n", cstr_str(&s->title));
@@ -21,18 +22,18 @@ void Song_drop(Song* s) {
// Define the shared pointer:
#define i_type SongArc
-#define i_valclass Song
-#define i_opt c_no_hash // arc require hash fn, disable as we don't need it.
+#define i_keyclass Song
+#define i_no_hash // no hash fn for Song, fallback hash pointer to Song.
#include <stc/carc.h>
// ... and a vector of them
#define i_type SongVec
-#define i_valboxed SongArc // use i_valboxed on carc / cbox instead of i_val
-#include <stc/cstack.h>
+#define i_keyboxed SongArc // use i_keyboxed on carc / cbox (instead of i_key)
+#include <stc/cvec.h>
-void example3()
+void example3(void)
{
- SongVec vec1 = c_make(SongVec, {
+ SongVec vec1 = c_init(SongVec, {
Song_make("Bob Dylan", "The Times They Are A Changing"),
Song_make("Aretha Franklin", "Bridge Over Troubled Water"),
Song_make("Thalia", "Entre El Mar y Una Estrella")
@@ -60,7 +61,7 @@ void example3()
c_drop(SongVec, &vec1, &vec2);
}
-int main()
+int main(void)
{
example3();
}
diff --git a/misc/examples/new_list.c b/misc/examples/new_list.c
index 8b291d34..9676e7b4 100644
--- a/misc/examples/new_list.c
+++ b/misc/examples/new_list.c
@@ -5,11 +5,11 @@ forward_clist(clist_i32, int);
forward_clist(clist_pnt, struct Point);
typedef struct {
- clist_i32 intlst;
- clist_pnt pntlst;
+ clist_i32 intlist;
+ clist_pnt pntlist;
} MyStruct;
-#define i_val int
+#define i_key int
#define i_tag i32
#define i_is_forward
#include <stc/clist.h>
@@ -20,49 +20,51 @@ int point_cmp(const Point* a, const Point* b) {
return c ? c : a->y - b->y;
}
-#define i_val Point
+#define i_key Point
#define i_cmp point_cmp
#define i_is_forward
#define i_tag pnt
#include <stc/clist.h>
-#define i_val float
+#define i_key float
+#define i_native_cmp // use < and == operators for comparison
#include <stc/clist.h>
void MyStruct_drop(MyStruct* s);
#define i_type MyList
-#define i_valclass MyStruct // i_valclass uses MyStruct_drop
-#define i_opt c_no_clone|c_no_cmp
+#define i_key MyStruct
+#define i_keydrop MyStruct_drop // define drop function
+#define i_no_clone // must explicitely exclude or define cloning support because of drop.
#include <stc/clist.h>
void MyStruct_drop(MyStruct* s) {
- clist_i32_drop(&s->intlst);
- clist_pnt_drop(&s->pntlst);
+ clist_i32_drop(&s->intlist);
+ clist_pnt_drop(&s->pntlist);
}
-int main()
+int main(void)
{
MyStruct my = {0};
- clist_i32_push_back(&my.intlst, 123);
- clist_pnt_push_back(&my.pntlst, (Point){123, 456});
+ clist_i32_push_back(&my.intlist, 123);
+ clist_pnt_push_back(&my.pntlist, c_LITERAL(Point){123, 456});
MyStruct_drop(&my);
- clist_pnt plst = c_make(clist_pnt, {{42, 14}, {32, 94}, {62, 81}});
- clist_pnt_sort(&plst);
+ clist_pnt plist = c_init(clist_pnt, {{42, 14}, {32, 94}, {62, 81}});
+ clist_pnt_sort(&plist);
- c_foreach (i, clist_pnt, plst)
+ c_foreach (i, clist_pnt, plist)
printf(" (%d %d)", i.ref->x, i.ref->y);
puts("");
- clist_pnt_drop(&plst);
+ clist_pnt_drop(&plist);
- clist_float flst = c_make(clist_float, {123.3f, 321.2f, -32.2f, 78.2f});
- clist_float_sort(&flst);
+ clist_float flist = c_init(clist_float, {123.3f, 321.2f, -32.2f, 78.2f});
+ clist_float_sort(&flist);
- c_foreach (i, clist_float, flst)
- printf(" %g", *i.ref);
+ c_foreach (i, clist_float, flist)
+ printf(" %g", (double)*i.ref);
puts("");
- clist_float_drop(&flst);
+ clist_float_drop(&flist);
}
diff --git a/misc/examples/new_map.c b/misc/examples/new_map.c
index 3a4f934d..de990040 100644
--- a/misc/examples/new_map.c
+++ b/misc/examples/new_map.c
@@ -1,12 +1,13 @@
+#define i_implement
#include <stc/cstr.h>
#include <stc/forward.h>
forward_cmap(cmap_pnt, struct Point, int);
-struct MyStruct {
+typedef struct MyStruct {
cmap_pnt pntmap;
cstr name;
-} typedef MyStruct;
+} MyStruct;
// int => int map
#define i_key int
@@ -14,7 +15,7 @@ struct MyStruct {
#include <stc/cmap.h>
// Point => int map
-struct Point { int x, y; } typedef Point;
+typedef struct Point { int x, y; } Point;
int point_cmp(const Point* a, const Point* b) {
int c = a->x - b->x;
@@ -40,20 +41,20 @@ int point_cmp(const Point* a, const Point* b) {
#include <stc/cset.h>
-int main()
+int main(void)
{
- cmap_pnt pmap = c_make(cmap_pnt, {{{42, 14}, 1}, {{32, 94}, 2}, {{62, 81}, 3}});
+ cmap_pnt pmap = c_init(cmap_pnt, {{{42, 14}, 1}, {{32, 94}, 2}, {{62, 81}, 3}});
c_foreach (i, cmap_pnt, pmap)
printf(" (%d, %d: %d)", i.ref->first.x, i.ref->first.y, i.ref->second);
puts("");
- cmap_str smap = c_make(cmap_str, {
+ cmap_str smap = c_init(cmap_str, {
{"Hello, friend", "long time no see"},
{"So long", "see you around"},
});
- cset_str sset = c_make(cset_str, {
+ cset_str sset = c_init(cset_str, {
"Hello, friend",
"Nice to see you again",
"So long",
diff --git a/misc/examples/new_pque.c b/misc/examples/new_pque.c
index 9147e3f2..16823bb6 100644
--- a/misc/examples/new_pque.c
+++ b/misc/examples/new_pque.c
@@ -1,16 +1,16 @@
#include <stdio.h>
-struct Point { int x, y; } typedef Point;
+typedef struct Point { int x, y; } Point;
#define i_type PointQ
-#define i_val Point
+#define i_key Point
#define i_less(a, b) a->x < b->x || (a->x == b->x && a->y < b->y)
#include <stc/cpque.h>
-int main()
+int main(void)
{
- PointQ pque = c_make(PointQ, {{23, 80}, {12, 32}, {54, 74}, {12, 62}});
+ PointQ pque = c_init(PointQ, {{23, 80}, {12, 32}, {54, 74}, {12, 62}});
// print
for (; !PointQ_empty(&pque); PointQ_pop(&pque))
{
diff --git a/misc/examples/new_queue.c b/misc/examples/new_queue.c
index 916f4dbc..f3592df6 100644
--- a/misc/examples/new_queue.c
+++ b/misc/examples/new_queue.c
@@ -5,22 +5,22 @@
forward_cqueue(cqueue_pnt, struct Point);
-struct Point { int x, y; } typedef Point;
+typedef struct Point { int x, y; } Point;
int point_cmp(const Point* a, const Point* b) {
int c = c_default_cmp(&a->x, &b->x);
return c ? c : c_default_cmp(&a->y, &b->y);
}
-#define i_val Point
+#define i_key Point
#define i_cmp point_cmp
#define i_is_forward
#define i_tag pnt
#include <stc/cqueue.h>
#define i_type IQ
-#define i_val int
+#define i_key int
#include <stc/cqueue.h>
-int main() {
+int main(void) {
int n = 50000000;
crand_t rng = crand_init((uint64_t)time(NULL));
crand_unif_t dist = crand_unif_init(0, n);
diff --git a/misc/examples/new_smap.c b/misc/examples/new_smap.c
index d8245b8b..ee946c9a 100644
--- a/misc/examples/new_smap.c
+++ b/misc/examples/new_smap.c
@@ -1,3 +1,4 @@
+#define i_implement
#include <stc/cstr.h>
#include <stc/forward.h>
@@ -10,7 +11,7 @@ typedef struct {
} MyStruct;
// Point => int map
-struct Point { int x, y; } typedef Point;
+typedef struct Point { int x, y; } Point;
int point_cmp(const Point* a, const Point* b) {
int c = a->x - b->x;
return c ? c : a->y - b->y;
@@ -35,14 +36,14 @@ int point_cmp(const Point* a, const Point* b) {
#include <stc/csset.h>
-int main()
+int main(void)
{
- PMap pmap = c_make(PMap, {
+ PMap pmap = c_init(PMap, {
{{42, 14}, 1},
{{32, 94}, 2},
{{62, 81}, 3},
});
- SMap smap = c_make(SMap, {
+ SMap smap = c_init(SMap, {
{"Hello, friend", "this is the mapped value"},
{"The brown fox", "jumped"},
{"This is the time", "for all good things"},
diff --git a/misc/examples/new_sptr.c b/misc/examples/new_sptr.c
index 1b72e4f5..7fef5d1f 100644
--- a/misc/examples/new_sptr.c
+++ b/misc/examples/new_sptr.c
@@ -1,3 +1,4 @@
+#define i_implement
#include <stc/cstr.h>
typedef struct { cstr name, last; } Person;
@@ -8,28 +9,27 @@ int Person_cmp(const Person* a, const Person* b);
uint64_t Person_hash(const Person* p);
#define i_type PersonArc
-#define i_valclass Person // "class" ensure Person_drop will be called
-#define i_cmp Person_cmp // enable carc object comparisons (not ptr to obj)
-#define i_hash Person_hash // enable carc object hash (not ptr to obj)
+#define i_keyclass Person // "class" assume _clone, _drop, _cmp, _hash is defined.
#include <stc/carc.h>
#define i_type IPtr
-#define i_val int
-#define i_valdrop(x) printf("drop: %d\n", *x)
-#define i_no_clone
+#define i_key int
+#define i_keydrop(x) printf("drop: %d\n", *x)
+#define i_native_cmp
#include <stc/carc.h>
#define i_type IPStack
-#define i_valboxed IPtr
+#define i_keyboxed IPtr
#include <stc/cstack.h>
#define i_type PASet
-#define i_valboxed PersonArc
+#define i_keyboxed PersonArc
#include <stc/cset.h>
Person Person_make(const char* name, const char* last) {
- return (Person){.name = cstr_from(name), .last = cstr_from(last)};
+ Person p = {.name = cstr_from(name), .last = cstr_from(last)};
+ return p;
}
int Person_cmp(const Person* a, const Person* b) {
diff --git a/misc/examples/new_vec.c b/misc/examples/new_vec.c
index df443b7f..88efd55a 100644
--- a/misc/examples/new_vec.c
+++ b/misc/examples/new_vec.c
@@ -4,32 +4,33 @@
forward_cvec(cvec_i32, int);
forward_cvec(cvec_pnt, struct Point);
-struct MyStruct {
+typedef struct MyStruct {
cvec_i32 intvec;
cvec_pnt pntvec;
-} typedef MyStruct;
+} MyStruct;
-#define i_val int
-#define i_is_forward
+#define i_key int
#define i_tag i32
+#define i_is_forward
#include <stc/cvec.h>
typedef struct Point { int x, y; } Point;
-#define i_val Point
+#define i_key Point
+#define i_tag pnt
#define i_less(a, b) a->x < b->x || (a->x == b->x && a->y < b->y)
+#define i_eq(a, b) a->x == b->x && a->y == b->y
#define i_is_forward
-#define i_tag pnt
#include <stc/cvec.h>
-int main()
+int main(void)
{
MyStruct my = {0};
- cvec_pnt_push(&my.pntvec, (Point){42, 14});
- cvec_pnt_push(&my.pntvec, (Point){32, 94});
- cvec_pnt_push(&my.pntvec, (Point){62, 81});
- cvec_pnt_push(&my.pntvec, (Point){32, 91});
+ cvec_pnt_push(&my.pntvec, c_LITERAL(Point){42, 14});
+ cvec_pnt_push(&my.pntvec, c_LITERAL(Point){32, 94});
+ cvec_pnt_push(&my.pntvec, c_LITERAL(Point){62, 81});
+ cvec_pnt_push(&my.pntvec, c_LITERAL(Point){32, 91});
cvec_pnt_sort(&my.pntvec);
diff --git a/misc/examples/person_arc.c b/misc/examples/person_arc.c
index 620d311f..38c883a7 100644
--- a/misc/examples/person_arc.c
+++ b/misc/examples/person_arc.c
@@ -1,10 +1,12 @@
/* cbox: heap allocated boxed type */
+#define i_implement
#include <stc/cstr.h>
typedef struct { cstr name, last; } Person;
Person Person_make(const char* name, const char* last) {
- return (Person){.name = cstr_from(name), .last = cstr_from(last)};
+ Person p = {.name = cstr_from(name), .last = cstr_from(last)};
+ return p;
}
int Person_cmp(const Person* a, const Person* b) {
@@ -28,16 +30,16 @@ void Person_drop(Person* p) {
}
#define i_type PSPtr
-#define i_valclass Person // ensure Person_drop
+#define i_keyclass Person // ensure Person_drop
#define i_cmp Person_cmp // specify object cmp, instead of ptr cmp for arc.
#include <stc/carc.h>
#define i_type Persons
-#define i_valboxed PSPtr // binds PSPtr_cmp, PSPtr_drop...
+#define i_keyboxed PSPtr // binds PSPtr_cmp, PSPtr_drop...
#include <stc/cvec.h>
-int main()
+int main(void)
{
PSPtr p = PSPtr_from(Person_make("Laura", "Palmer"));
PSPtr q = PSPtr_from(Person_clone(*p.get)); // deep copy
diff --git a/misc/examples/phonebook.c b/misc/examples/phonebook.c
index c0007cb7..faf7566e 100644
--- a/misc/examples/phonebook.c
+++ b/misc/examples/phonebook.c
@@ -20,7 +20,7 @@
// IN THE SOFTWARE.
// Program to emulates the phone book.
-
+#define i_implement
#include <stc/cstr.h>
#define i_key_str
@@ -38,7 +38,7 @@ void print_phone_book(cmap_str phone_book)
int main(int argc, char **argv)
{
- cmap_str phone_book = c_make(cmap_str, {
+ cmap_str phone_book = c_init(cmap_str, {
{"Lilia Friedman", "(892) 670-4739"},
{"Tariq Beltran", "(489) 600-7575"},
{"Laiba Juarez", "(303) 885-5692"},
diff --git a/misc/examples/prime.c b/misc/examples/prime.c
index c3a0663c..c3db707d 100644
--- a/misc/examples/prime.c
+++ b/misc/examples/prime.c
@@ -28,15 +28,18 @@ cbits sieveOfEratosthenes(llong n)
int main(void)
{
+
llong n = 100000000;
printf("Computing prime numbers up to %lld\n", n);
- clock_t t1 = clock();
+ clock_t t = clock();
cbits primes = sieveOfEratosthenes(n + 1);
+
llong np = cbits_count(&primes);
clock_t t2 = clock();
printf("Number of primes: %lld, time: %f\n\n", np, (float)(t2 - t1) / (float)CLOCKS_PER_SEC);
+
puts("Show all the primes in the range [2, 1000):");
printf("2");
c_forrange (i, 3, 1000, 2)
@@ -44,7 +47,9 @@ int main(void)
puts("\n");
puts("Show the last 50 primes using a temporary crange generator:");
- c_forfilter (i, crange, crange_obj(n - 1, 0, -2),
+ crange range = crange_make(n - 1, 0, -2);
+
+ c_forfilter (i, crange, range,
cbits_test(&primes, *i.ref/2) &&
c_flt_take(i, 50)
){
diff --git a/misc/examples/printspan.c b/misc/examples/printspan.c
index 7459ac77..cd3c5f4f 100644
--- a/misc/examples/printspan.c
+++ b/misc/examples/printspan.c
@@ -1,17 +1,16 @@
// printspan.c
#include <stdio.h>
+#define i_implement
#include <stc/cstr.h>
-#define i_val int
+#define i_key int
#include <stc/cvec.h>
-#define i_val int
+#define i_key int
#include <stc/cstack.h>
-#define i_val int
-#include <stc/cdeq.h>
-#define i_val_str
+#define i_key_str
#include <stc/csset.h>
-#include <stc/cspan.h>
+#include <stc/cspan.h>
using_cspan(intspan, int, 1);
void printMe(intspan container) {
@@ -21,29 +20,26 @@ void printMe(intspan container) {
puts("");
}
-int main()
+int main(void)
{
- intspan sp1 = cspan_make(intspan, {1, 2});
+ intspan sp1 = cspan_init(intspan, {1, 2});
printMe( sp1 );
- printMe( c_make(intspan, {1, 2, 3}) );
+ printMe( c_init(intspan, {1, 2, 3}) );
int arr[] = {1, 2, 3, 4, 5, 6};
intspan sp2 = cspan_from_array(arr);
- printMe( (intspan)cspan_subspan(&sp2, 1, 4) );
+ printMe( c_LITERAL(intspan)cspan_subspan(&sp2, 1, 4) );
- cvec_int vec = c_make(cvec_int, {1, 2, 3, 4, 5});
- printMe( (intspan)cspan_from(&vec) );
+ cvec_int vec = c_init(cvec_int, {1, 2, 3, 4, 5});
+ printMe( c_LITERAL(intspan)cspan_from(&vec) );
printMe( sp2 );
- cstack_int stk = c_make(cstack_int, {1, 2, 3, 4, 5, 6, 7});
- printMe( (intspan)cspan_from(&stk) );
-
- cdeq_int deq = c_make(cdeq_int, {1, 2, 3, 4, 5, 6, 7, 8});
- printMe( (intspan)cspan_from(&deq) );
+ cstack_int stk = c_init(cstack_int, {1, 2, 3, 4, 5, 6, 7});
+ printMe( c_LITERAL(intspan)cspan_from(&stk) );
- csset_str set = c_make(csset_str, {"5", "7", "4", "3", "8", "2", "1", "9", "6"});
+ csset_str set = c_init(csset_str, {"5", "7", "4", "3", "8", "2", "1", "9", "6"});
printf("%d:", (int)csset_str_size(&set));
c_foreach (e, csset_str, set)
printf(" %s", cstr_str(e.ref));
@@ -52,6 +48,5 @@ int main()
// cleanup
cvec_int_drop(&vec);
cstack_int_drop(&stk);
- cdeq_int_drop(&deq);
csset_str_drop(&set);
}
diff --git a/misc/examples/priority.c b/misc/examples/priority.c
index 95dd3183..bf2e188a 100644
--- a/misc/examples/priority.c
+++ b/misc/examples/priority.c
@@ -3,12 +3,12 @@
#include <time.h>
#include <stc/crand.h>
-#define i_val int64_t
+#define i_key int64_t
#define i_cmp -c_default_cmp // min-heap (increasing values)
#define i_tag i
#include <stc/cpque.h>
-int main() {
+int main(void) {
intptr_t N = 10000000;
crand_t rng = crand_init((uint64_t)time(NULL));
crand_unif_t dist = crand_unif_init(0, N * 10);
diff --git a/misc/examples/queue.c b/misc/examples/queue.c
index 90c800aa..867a6c7b 100644
--- a/misc/examples/queue.c
+++ b/misc/examples/queue.c
@@ -1,7 +1,7 @@
#include <stc/crand.h>
#include <stdio.h>
-#define i_val int
+#define i_key int
#define i_tag i
#include <stc/cqueue.h>
diff --git a/misc/examples/random.c b/misc/examples/random.c
index b4b437cf..63c5a306 100644
--- a/misc/examples/random.c
+++ b/misc/examples/random.c
@@ -2,7 +2,7 @@
#include <time.h>
#include <stc/crand.h>
-int main()
+int main(void)
{
const size_t N = 10000000;
const uint64_t seed = (uint64_t)time(NULL), range = 1000000;
@@ -18,8 +18,8 @@ int main()
sum += (uint32_t)crand_u64(&rng);
}
diff = clock() - before;
- printf("full range\t\t: %f secs, %" c_ZI ", avg: %f\n",
- (float)diff / CLOCKS_PER_SEC, N, (float)sum / (float)N);
+ printf("full range\t\t: %f secs, %d, avg: %f\n",
+ (double)diff/CLOCKS_PER_SEC, N, (double)sum/N);
crand_unif_t dist1 = crand_unif_init(0, range);
rng = crand_init(seed);
@@ -29,8 +29,8 @@ int main()
sum += crand_unif(&rng, &dist1); // unbiased
}
diff = clock() - before;
- printf("unbiased 0-%" PRIu64 "\t: %f secs, %" c_ZI ", avg: %f\n",
- range, (float)diff/CLOCKS_PER_SEC, N, (float)sum / (float)N);
+ printf("unbiased 0-%" PRIu64 "\t: %f secs, %d, avg: %f\n",
+ range, (double)diff/CLOCKS_PER_SEC, N, (double)sum/N);
sum = 0;
rng = crand_init(seed);
@@ -39,7 +39,7 @@ int main()
sum += (int64_t)(crand_u64(&rng) % (range + 1)); // biased
}
diff = clock() - before;
- printf("biased 0-%" PRIu64 " \t: %f secs, %" c_ZI ", avg: %f\n",
- range, (float)diff / CLOCKS_PER_SEC, N, (float)sum / (float)N);
+ printf("biased 0-%" PRIu64 " \t: %f secs, %d, avg: %f\n",
+ range, (double)diff/CLOCKS_PER_SEC, N, (double)sum/N);
}
diff --git a/misc/examples/rawptr_elements.c b/misc/examples/rawptr_elements.c
index 01bcdc44..694ce12e 100644
--- a/misc/examples/rawptr_elements.c
+++ b/misc/examples/rawptr_elements.c
@@ -1,6 +1,6 @@
#include <stc/ccommon.h>
#include <stdio.h>
-
+#define i_implement
#include <stc/cstr.h>
// Create cmap of cstr => long*
@@ -16,7 +16,7 @@
// Alternatively, using cbox:
#define i_type IBox
-#define i_val long
+#define i_key long
#include <stc/cbox.h> // unique_ptr<long> alike.
// cmap of cstr => IBox
@@ -25,7 +25,7 @@
#define i_valboxed IBox // i_valboxed: use properties from IBox automatically
#include <stc/cmap.h>
-int main()
+int main(void)
{
// These have the same behaviour, except IBox has a get member:
SIPtrMap map1 = {0};
diff --git a/misc/examples/read.c b/misc/examples/read.c
index 4efdcfeb..b12f7409 100644
--- a/misc/examples/read.c
+++ b/misc/examples/read.c
@@ -1,5 +1,7 @@
+#define i_implement
#include <stc/cstr.h>
-#define i_val_str
+#include <stc/algo/raii.h>
+#define i_key_str
#include <stc/cvec.h>
#include <errno.h>
@@ -7,13 +9,13 @@ cvec_str read_file(const char* name)
{
cvec_str vec = cvec_str_init();
c_with (FILE* f = fopen(name, "r"), fclose(f))
- c_with (cstr line = cstr_NULL, cstr_drop(&line))
+ c_with (cstr line = cstr_null, cstr_drop(&line))
while (cstr_getline(&line, f))
cvec_str_push(&vec, cstr_clone(line));
return vec;
}
-int main()
+int main(void)
{
int n = 0;
c_with (cvec_str vec = read_file(__FILE__), cvec_str_drop(&vec))
diff --git a/misc/examples/regex1.c b/misc/examples/regex1.c
index 4a56b8ac..d8032358 100644
--- a/misc/examples/regex1.c
+++ b/misc/examples/regex1.c
@@ -1,4 +1,4 @@
-#define i_extern
+#define i_import
#include <stc/cregex.h>
int main(int argc, char* argv[])
diff --git a/misc/examples/regex2.c b/misc/examples/regex2.c
index 3133f7c2..a798b1a1 100644
--- a/misc/examples/regex2.c
+++ b/misc/examples/regex2.c
@@ -1,7 +1,7 @@
-#define i_extern
+#define i_import
#include <stc/cregex.h>
-int main()
+int main(void)
{
struct { const char *pattern, *input; } s[] = {
{"(\\d\\d\\d\\d)[-_](1[0-2]|0[1-9])[-_](3[01]|[12][0-9]|0[1-9])",
@@ -26,7 +26,7 @@ int main()
printf("\ninput: %s\n", s[i].input);
c_formatch (j, &re, s[i].input) {
- c_forrange (k, cregex_captures(&re))
+ c_forrange (k, cregex_captures(&re) + 1)
printf(" submatch %lld: %.*s\n", k, c_SV(j.match[k]));
}
}
diff --git a/misc/examples/regex_match.c b/misc/examples/regex_match.c
index def0ae7a..11426d2d 100644
--- a/misc/examples/regex_match.c
+++ b/misc/examples/regex_match.c
@@ -1,11 +1,12 @@
-#define i_extern
+#define i_import
#include <stc/cregex.h>
+#define i_implement
#include <stc/csview.h>
-#define i_val float
+#define i_key float
#include <stc/cstack.h>
-int main()
+int main(void)
{
// Lets find the first sequence of digits in a string
const char *str = "Hello numeric world, there are 24 hours in a day, 3600 seconds in an hour."
@@ -24,10 +25,10 @@ int main()
cstack_float_push(&vec, (float)atof(i.match[0].str));
c_foreach (i, cstack_float, vec)
- printf(" %g\n", *i.ref);
+ printf(" %g\n", (double)*i.ref);
// extracts the numbers only to a comma separated string.
- cstr nums = cregex_replace_sv(&re, csview_from(str), " $0,", 0, NULL, CREG_R_STRIP);
+ cstr nums = cregex_replace_sv(&re, csview_from(str), " $0,", 0, NULL, CREG_STRIP);
printf("\n%s\n", cstr_str(&nums));
cstr_drop(&nums);
diff --git a/misc/examples/regex_replace.c b/misc/examples/regex_replace.c
index d3952f50..f1ea2711 100644
--- a/misc/examples/regex_replace.c
+++ b/misc/examples/regex_replace.c
@@ -1,4 +1,4 @@
-#define i_extern
+#define i_import
#include <stc/cregex.h>
#include <stc/csview.h>
@@ -12,7 +12,7 @@ bool add_10_years(int i, csview match, cstr* out) {
return false;
}
-int main()
+int main(void)
{
const char* pattern = "\\b(\\d\\d\\d\\d)-(1[0-2]|0[1-9])-(3[01]|[12][0-9]|0[1-9])\\b";
const char* input = "start date: 2015-12-31, end date: 2022-02-28";
@@ -47,7 +47,7 @@ int main()
printf("euros: %s\n", cstr_str(&str));
/* Strip out everything but the matches */
- cstr_take(&str, cregex_replace_sv(&re, csview_from(input), "$3.$2.$1;", 0, NULL, CREG_R_STRIP));
+ cstr_take(&str, cregex_replace_sv(&re, csview_from(input), "$3.$2.$1;", 0, NULL, CREG_STRIP));
printf("strip: %s\n", cstr_str(&str));
/* Wrap all words in ${} */
diff --git a/misc/examples/replace.c b/misc/examples/replace.c
index cf5b45cb..59a56bf7 100644
--- a/misc/examples/replace.c
+++ b/misc/examples/replace.c
@@ -1,6 +1,7 @@
+#define i_implement
#include <stc/cstr.h>
-int main ()
+int main(void)
{
const char *base = "this is a test string.";
const char *s2 = "n example";
diff --git a/misc/examples/scheduler.c b/misc/examples/scheduler.c
new file mode 100644
index 00000000..38defd0f
--- /dev/null
+++ b/misc/examples/scheduler.c
@@ -0,0 +1,74 @@
+// https://www.youtube.com/watch?v=8sEe-4tig_A
+#include <stdio.h>
+#include <stc/calgo.h>
+
+struct Task {
+ int (*fn)(struct Task*);
+ int cco_state;
+ struct Scheduler* sched;
+};
+
+#define i_type Scheduler
+#define i_key struct Task
+#include <stc/cqueue.h>
+
+static bool schedule(Scheduler* sched)
+{
+ struct Task task = *Scheduler_front(sched);
+ Scheduler_pop(sched);
+
+ if (!cco_done(&task))
+ task.fn(&task);
+
+ return !Scheduler_empty(sched);
+}
+
+static int push_task(const struct Task* task)
+{
+ Scheduler_push(task->sched, *task);
+ return CCO_YIELD;
+}
+
+
+static int taskA(struct Task* task)
+{
+ cco_routine(task) {
+ puts("Hello, from task A");
+ cco_yield_v(push_task(task));
+ puts("A is back doing work");
+ cco_yield_v(push_task(task));
+ puts("A is back doing more work");
+ cco_yield_v(push_task(task));
+ puts("A is back doing even more work");
+ }
+ return 0;
+}
+
+static int taskB(struct Task* task)
+{
+ cco_routine(task) {
+ puts("Hello, from task B");
+ cco_yield_v(push_task(task));
+ puts("B is back doing work");
+ cco_yield_v(push_task(task));
+ puts("B is back doing more work");
+ }
+ return 0;
+}
+
+void Use(void)
+{
+ Scheduler scheduler = c_init(Scheduler, {
+ {.fn=taskA, .sched=&scheduler},
+ {.fn=taskB, .sched=&scheduler},
+ });
+
+ while (schedule(&scheduler)) {}
+
+ Scheduler_drop(&scheduler);
+}
+
+int main(void)
+{
+ Use();
+}
diff --git a/misc/examples/shape.c b/misc/examples/shape.c
index d7116039..bd4bdd5a 100644
--- a/misc/examples/shape.c
+++ b/misc/examples/shape.c
@@ -62,9 +62,9 @@ static void Triangle_draw(const Shape* shape)
{
const Triangle* self = DYN_CAST(Triangle, shape);
printf("Triangle : (%g,%g), (%g,%g), (%g,%g)\n",
- self->p[0].x, self->p[0].y,
- self->p[1].x, self->p[1].y,
- self->p[2].x, self->p[2].y);
+ (double)self->p[0].x, (double)self->p[0].y,
+ (double)self->p[1].x, (double)self->p[1].y,
+ (double)self->p[2].x, (double)self->p[2].y);
}
struct ShapeAPI Triangle_api = {
@@ -76,7 +76,7 @@ struct ShapeAPI Triangle_api = {
// ============================================================
#define i_type PointVec
-#define i_val Point
+#define i_key Point
#include <stc/cstack.h>
typedef struct {
@@ -109,7 +109,7 @@ static void Polygon_draw(const Shape* shape)
const Polygon* self = DYN_CAST(Polygon, shape);
printf("Polygon :");
c_foreach (i, PointVec, self->points)
- printf(" (%g,%g)", i.ref->x, i.ref->y);
+ printf(" (%g,%g)", (double)i.ref->x, (double)i.ref->y);
puts("");
}
@@ -122,8 +122,8 @@ struct ShapeAPI Polygon_api = {
// ============================================================
#define i_type Shapes
-#define i_val Shape*
-#define i_valdrop(x) Shape_delete(*x)
+#define i_key Shape*
+#define i_keydrop(x) Shape_delete(*x)
#define i_no_clone
#include <stc/cstack.h>
@@ -137,7 +137,7 @@ int main(void)
{
Shapes shapes = {0};
- Triangle* tri1 = c_new(Triangle, Triangle_from((Point){5, 7}, (Point){12, 7}, (Point){12, 20}));
+ Triangle* tri1 = c_new(Triangle, Triangle_from(c_LITERAL(Point){5, 7}, c_LITERAL(Point){12, 7}, c_LITERAL(Point){12, 20}));
Polygon* pol1 = c_new(Polygon, Polygon_init());
Polygon* pol2 = c_new(Polygon, Polygon_init());
diff --git a/misc/examples/sidebyside.cpp b/misc/examples/sidebyside.cpp
index a7c1008c..9414b691 100644
--- a/misc/examples/sidebyside.cpp
+++ b/misc/examples/sidebyside.cpp
@@ -13,7 +13,7 @@
#define i_val int
#include <stc/cmap.h>
-int main() {
+int main(void) {
{
std::map<int, int> hist;
hist.emplace(12, 100).first->second += 1;
diff --git a/misc/examples/sorted_map.c b/misc/examples/sorted_map.c
index ae9b45a4..89381554 100644
--- a/misc/examples/sorted_map.c
+++ b/misc/examples/sorted_map.c
@@ -1,11 +1,11 @@
// https://iq.opengenus.org/containers-cpp-stl/
+#include <stdio.h>
#define i_key int
#define i_val int
#include <stc/csmap.h>
-#include <stdio.h>
-int main()
+int main(void)
{
// empty map containers
diff --git a/misc/examples/splitstr.c b/misc/examples/splitstr.c
index 2bc6fc07..ef7ed174 100644
--- a/misc/examples/splitstr.c
+++ b/misc/examples/splitstr.c
@@ -1,9 +1,10 @@
#include <stdio.h>
-#define i_extern // cstr + utf8 functions
+#define i_import // cstr + utf8 functions
#include <stc/cregex.h>
+#define i_implement
#include <stc/csview.h>
-int main()
+int main(void)
{
puts("Split with c_fortoken (csview):");
diff --git a/misc/examples/sso_map.c b/misc/examples/sso_map.c
index 70450e21..4f84b651 100644
--- a/misc/examples/sso_map.c
+++ b/misc/examples/sso_map.c
@@ -1,9 +1,10 @@
+#define i_implement
#include <stc/cstr.h>
#define i_key_str
#define i_val_str
#include <stc/cmap.h>
-int main()
+int main(void)
{
cmap_str m = {0};
cmap_str_emplace(&m, "Test short", "This is a short string");
diff --git a/misc/examples/sso_substr.c b/misc/examples/sso_substr.c
index 4b2dbcc8..687658df 100644
--- a/misc/examples/sso_substr.c
+++ b/misc/examples/sso_substr.c
@@ -1,7 +1,9 @@
+#define i_implement
#include <stc/cstr.h>
+#define i_implement
#include <stc/csview.h>
-int main ()
+int main(void)
{
cstr str = cstr_lit("We think in generalities, but we live in details.");
csview sv1 = cstr_substr_ex(&str, 3, 5); // "think"
diff --git a/misc/examples/stack.c b/misc/examples/stack.c
index c817e1ae..6297fb6f 100644
--- a/misc/examples/stack.c
+++ b/misc/examples/stack.c
@@ -3,14 +3,14 @@
#define i_tag i
#define i_capacity 100
-#define i_val int
+#define i_key int
#include <stc/cstack.h>
#define i_tag c
-#define i_val char
+#define i_key char
#include <stc/cstack.h>
-int main() {
+int main(void) {
cstack_i stack = {0};
cstack_c chars = {0};
diff --git a/misc/examples/sview_split.c b/misc/examples/sview_split.c
index 31a28e51..ac275da0 100644
--- a/misc/examples/sview_split.c
+++ b/misc/examples/sview_split.c
@@ -1,7 +1,9 @@
+#define i_implement
#include <stc/cstr.h>
+#define i_implement
#include <stc/csview.h>
-int main()
+int main(void)
{
// No memory allocations or string length calculations!
const csview date = c_sv("2021/03/12");
diff --git a/misc/examples/triples.c b/misc/examples/triples.c
index 520bf012..9f2fcc1e 100644
--- a/misc/examples/triples.c
+++ b/misc/examples/triples.c
@@ -3,12 +3,21 @@
#include <stc/algo/coroutine.h>
#include <stdio.h>
+int gcd(int a, int b) {
+ while (b) {
+ int t = a % b;
+ a = b;
+ b = t;
+ }
+ return a;
+}
+
void triples_vanilla(int n) {
- for (int c = 5; n; ++c) {
+ for (int c = 5, i = 0; n; ++c) {
for (int a = 1; a < c; ++a) {
for (int b = a + 1; b < c; ++b) {
- if ((int64_t)a*a + (int64_t)b*b == (int64_t)c*c) {
- printf("{%d, %d, %d}\n", a, b, c);
+ if ((int64_t)a*a + (int64_t)b*b == (int64_t)c*c && gcd(a, b) == 1) {
+ printf("%d: {%d, %d, %d}\n", ++i, a, b, c);
if (--n == 0) goto done;
}
}
@@ -18,47 +27,41 @@ void triples_vanilla(int n) {
}
struct triples {
- int n;
+ int size, count;
int a, b, c;
int cco_state;
};
-bool triples_next(struct triples* I) {
- cco_begin(I);
- for (I->c = 5; I->n; ++I->c) {
- for (I->a = 1; I->a < I->c; ++I->a) {
- for (I->b = I->a + 1; I->b < I->c; ++I->b) {
- if ((int64_t)I->a*I->a + (int64_t)I->b*I->b == (int64_t)I->c*I->c) {
- cco_yield(true);
- if (--I->n == 0) cco_return;
+int triples_coro(struct triples* t) {
+ cco_routine(t) {
+ t->count = 0;
+ for (t->c = 5; t->size; ++t->c) {
+ for (t->a = 1; t->a < t->c; ++t->a) {
+ for (t->b = t->a + 1; t->b < t->c; ++t->b) {
+ if ((int64_t)t->a*t->a + (int64_t)t->b*t->b == (int64_t)t->c*t->c) {
+ if (t->count++ == t->size)
+ cco_return;
+ cco_yield();
}
}
}
}
- cco_final:
+ cco_cleanup:
puts("done");
- cco_end(false);
-}
-
-int gcd(int a, int b) {
- while (b) {
- int t = a % b;
- a = b;
- b = t;
}
- return a;
+ return 0;
}
-int main()
+int main(void)
{
puts("Vanilla triples:");
- triples_vanilla(6);
+ triples_vanilla(5);
puts("\nCoroutine triples:");
- struct triples t = {INT32_MAX};
+ struct triples t = {.size=INT32_MAX};
int n = 0;
- while (triples_next(&t)) {
+ while (triples_coro(&t)) {
if (gcd(t.a, t.b) > 1)
continue;
if (t.c < 100)
diff --git a/misc/examples/unordered_set.c b/misc/examples/unordered_set.c
index 61f9cc1f..dd899d78 100644
--- a/misc/examples/unordered_set.c
+++ b/misc/examples/unordered_set.c
@@ -1,10 +1,11 @@
// https://iq.opengenus.org/containers-cpp-stl/
// C program to demonstrate various function of stc cset
+#define i_implement
#include <stc/cstr.h>
#define i_key_str
#include <stc/cset.h>
-int main()
+int main(void)
{
// declaring set for storing string data-type
cset_str stringSet = {0};
diff --git a/misc/examples/utf8replace_c.c b/misc/examples/utf8replace_c.c
index 3cde8701..1d54486f 100644
--- a/misc/examples/utf8replace_c.c
+++ b/misc/examples/utf8replace_c.c
@@ -1,6 +1,7 @@
+#define i_implement
#include <stc/cstr.h>
-int main()
+int main(void)
{
cstr hello = cstr_lit("hell😀 w😀rld");
printf("%s\n", cstr_str(&hello));
diff --git a/misc/examples/vikings.c b/misc/examples/vikings.c
index abb909c3..d6125854 100644
--- a/misc/examples/vikings.c
+++ b/misc/examples/vikings.c
@@ -1,3 +1,4 @@
+#define i_implement
#include <stc/cstr.h>
typedef struct Viking {
@@ -40,15 +41,15 @@ static inline RViking Viking_toraw(const Viking* vp) {
#define i_val int // mapped type
#include <stc/cmap.h>
-int main()
+int main(void)
{
Vikings vikings = {0};
- Vikings_emplace(&vikings, (RViking){"Einar", "Norway"}, 20);
- Vikings_emplace(&vikings, (RViking){"Olaf", "Denmark"}, 24);
- Vikings_emplace(&vikings, (RViking){"Harald", "Iceland"}, 12);
- Vikings_emplace(&vikings, (RViking){"Björn", "Sweden"}, 10);
+ Vikings_emplace(&vikings, c_LITERAL(RViking){"Einar", "Norway"}, 20);
+ Vikings_emplace(&vikings, c_LITERAL(RViking){"Olaf", "Denmark"}, 24);
+ Vikings_emplace(&vikings, c_LITERAL(RViking){"Harald", "Iceland"}, 12);
+ Vikings_emplace(&vikings, c_LITERAL(RViking){"Björn", "Sweden"}, 10);
- Vikings_value* v = Vikings_get_mut(&vikings, (RViking){"Einar", "Norway"});
+ Vikings_value* v = Vikings_get_mut(&vikings, c_LITERAL(RViking){"Einar", "Norway"});
v->second += 3; // add 3 hp points to Einar
c_forpair (vk, hp, Vikings, vikings) {
diff --git a/misc/tests/cregex_test.c b/misc/tests/cregex_test.c
index aa4b2a65..4e192de6 100644
--- a/misc/tests/cregex_test.c
+++ b/misc/tests/cregex_test.c
@@ -1,6 +1,7 @@
-#define i_extern
+#define i_import
#include <stc/cregex.h>
#include <stc/csview.h>
+#include <stc/algo/raii.h>
#include "ctest.h"
#define M_START(m) ((m).str - inp)
@@ -14,7 +15,7 @@ CTEST(cregex, compile_match_char)
ASSERT_EQ(re.error, 0);
csview match;
- ASSERT_EQ(cregex_find(&re, inp="äsdf", &match, CREG_M_FULLMATCH), CREG_OK);
+ ASSERT_EQ(cregex_find(&re, inp="äsdf", &match, CREG_FULLMATCH), CREG_OK);
ASSERT_EQ(M_START(match), 0);
ASSERT_EQ(M_END(match), 5); // ä is two bytes wide
@@ -192,14 +193,14 @@ CTEST(cregex, search_all)
int res;
ASSERT_EQ(re.error, CREG_OK);
inp="ab,ab,ab";
- res = cregex_find(&re, inp, &m, CREG_M_NEXT);
+ res = cregex_find(&re, inp, &m, CREG_NEXT);
ASSERT_EQ(M_START(m), 0);
- res = cregex_find(&re, inp, &m, CREG_M_NEXT);
+ res = cregex_find(&re, inp, &m, CREG_NEXT);
ASSERT_EQ(res, CREG_OK);
ASSERT_EQ(M_START(m), 3);
- res = cregex_find(&re, inp, &m, CREG_M_NEXT);
+ res = cregex_find(&re, inp, &m, CREG_NEXT);
ASSERT_EQ(M_START(m), 6);
- res = cregex_find(&re, inp, &m, CREG_M_NEXT);
+ res = cregex_find(&re, inp, &m, CREG_NEXT);
ASSERT_NE(res, CREG_OK);
}
}
@@ -208,7 +209,7 @@ CTEST(cregex, captures_len)
{
c_auto (cregex, re) {
re = cregex_from("(ab(cd))(ef)");
- ASSERT_EQ(cregex_captures(&re), 4);
+ ASSERT_EQ(cregex_captures(&re), 3);
}
}
@@ -217,7 +218,7 @@ CTEST(cregex, captures_cap)
const char* inp;
c_auto (cregex, re) {
re = cregex_from("(ab)((cd)+)");
- ASSERT_EQ(cregex_captures(&re), 4);
+ ASSERT_EQ(cregex_captures(&re), 3);
csview cap[5];
ASSERT_EQ(cregex_find(&re, inp="xxabcdcde", cap), CREG_OK);
@@ -272,14 +273,14 @@ CTEST(cregex, replace)
// Compile RE separately
re = cregex_from(pattern);
- ASSERT_EQ(cregex_captures(&re), 4);
+ ASSERT_EQ(cregex_captures(&re), 3);
// European date format.
cstr_take(&str, cregex_replace(&re, input, "$3.$2.$1"));
ASSERT_STREQ(cstr_str(&str), "start date: 31.12.2015, end date: 28.02.2022");
// Strip out everything but the matches
- cstr_take(&str, cregex_replace_sv(&re, csview_from(input), "$3.$2.$1;", 0, NULL, CREG_R_STRIP));
+ cstr_take(&str, cregex_replace_sv(&re, csview_from(input), "$3.$2.$1;", 0, NULL, CREG_STRIP));
ASSERT_STREQ(cstr_str(&str), "31.12.2015;28.02.2022;");
}
}
diff --git a/misc/tests/cspan_test.c b/misc/tests/cspan_test.c
index 83ac762b..d7ca9b64 100644
--- a/misc/tests/cspan_test.c
+++ b/misc/tests/cspan_test.c
@@ -1,5 +1,6 @@
#include <stdio.h>
#include <stc/cspan.h>
+#include <stc/algo/raii.h>
#include "ctest.h"
using_cspan3(intspan, int);
@@ -9,11 +10,11 @@ CTEST(cspan, subdim) {
int array[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12};
intspan3 m = cspan_md(array, 2, 2, 3);
- for (size_t i = 0; i < m.shape[0]; ++i) {
+ for (int i = 0; i < m.shape[0]; ++i) {
intspan2 sub_i = cspan_submd3(&m, i);
- for (size_t j = 0; j < m.shape[1]; ++j) {
+ for (int j = 0; j < m.shape[1]; ++j) {
intspan sub_i_j = cspan_submd2(&sub_i, j);
- for (size_t k = 0; k < m.shape[2]; ++k) {
+ for (int k = 0; k < m.shape[2]; ++k) {
ASSERT_EQ(*cspan_at(&sub_i_j, k), *cspan_at(&m, i, j, k));
}
}
@@ -24,18 +25,18 @@ CTEST(cspan, slice) {
int array[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12};
intspan2 m1 = cspan_md(array, 3, 4);
- size_t sum1 = 0;
- for (size_t i = 0; i < m1.shape[0]; ++i) {
- for (size_t j = 0; j < m1.shape[1]; ++j) {
+ int sum1 = 0;
+ for (int i = 0; i < m1.shape[0]; ++i) {
+ for (int j = 0; j < m1.shape[1]; ++j) {
sum1 += *cspan_at(&m1, i, j);
}
}
intspan2 m2 = cspan_slice(intspan2, &m1, {c_ALL}, {2,4});
- size_t sum2 = 0;
- for (size_t i = 0; i < m2.shape[0]; ++i) {
- for (size_t j = 0; j < m2.shape[1]; ++j) {
+ int sum2 = 0;
+ for (int i = 0; i < m2.shape[0]; ++i) {
+ for (int j = 0; j < m2.shape[1]; ++j) {
sum2 += *cspan_at(&m2, i, j);
}
}
@@ -43,7 +44,7 @@ CTEST(cspan, slice) {
ASSERT_EQ(45, sum2);
}
-#define i_val int
+#define i_key int
#include <stc/cstack.h>
CTEST(cspan, slice2) {
@@ -55,10 +56,10 @@ CTEST(cspan, slice2) {
intspan3 ms3 = cspan_md(stack.data, 10, 20, 30);
ms3 = cspan_slice(intspan3, &ms3, {1,4}, {3,7}, {20,24});
- size_t sum = 0;
- for (size_t i = 0; i < ms3.shape[0]; ++i) {
- for (size_t j = 0; j < ms3.shape[1]; ++j) {
- for (size_t k = 0; k < ms3.shape[2]; ++k) {
+ int sum = 0;
+ for (int i = 0; i < ms3.shape[0]; ++i) {
+ for (int j = 0; j < ms3.shape[1]; ++j) {
+ for (int k = 0; k < ms3.shape[2]; ++k) {
sum += *cspan_at(&ms3, i, j, k);
}
}
@@ -74,7 +75,7 @@ CTEST(cspan, slice2) {
#define i_type Tiles
-#define i_val intspan3
+#define i_key intspan3
#include <stc/cstack.h>
CTEST_FIXTURE(cspan_cube) {