diff options
| author | Tyge Løvset <[email protected]> | 2023-07-18 02:36:04 +0200 |
|---|---|---|
| committer | GitHub <[email protected]> | 2023-07-18 02:36:04 +0200 |
| commit | da70303c149b37dbf442e41038a00836132562ee (patch) | |
| tree | 06d795c66d6759e06de5f2d166215b461ac40d1d /misc | |
| parent | 071b41c0fe95cb3f9a72bbe0417d856e7989ca08 (diff) | |
| parent | 23eeedb3fc298602732f394adba6a43c876ca7d8 (diff) | |
| download | STC-modified-da70303c149b37dbf442e41038a00836132562ee.tar.gz STC-modified-da70303c149b37dbf442e41038a00836132562ee.zip | |
Merge branch 'dev43' into master
Diffstat (limited to 'misc')
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(©.get); IPQue_pop(©.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) { |
