diff --git a/CMakeLists.txt b/CMakeLists.txt index e2c07fc8..3c77a7ec 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -18,23 +18,23 @@ option(WJR_DISABLE_EXCEPTIONS "Disable exceptions" ON) option(WJR_DISABLE_CXX_20 "Disable C++ 20 even if it's supported." ON) if (DEFINED WJR_DEBUG_LEVEL AND (NOT DEFINED WJR_DEBUG_LEVEL_DEBUG)) - set(WJR_DEBUG_LEVEL_DEBUG_TMP ${WJR_DEBUG_LEVEL}) + set(WJR_DEBUG_LEVEL_DEBUG ${WJR_DEBUG_LEVEL}) endif() if (DEFINED WJR_DEBUG_LEVEL AND (NOT DEFINED WJR_DEBUG_LEVEL_RELEASE)) - set(WJR_DEBUG_LEVEL_RELEASE_TMP ${WJR_DEBUG_LEVEL}) + set(WJR_DEBUG_LEVEL_RELEASE ${WJR_DEBUG_LEVEL}) endif() if (NOT DEFINED WJR_DEBUG_LEVEL_DEBUG) - set(WJR_DEBUG_LEVEL_DEBUG_TMP 3) + set(WJR_DEBUG_LEVEL_DEBUG 3) else() - set(WJR_DEBUG_LEVEL_DEBUG_TMP ${WJR_DEBUG_LEVEL_DEBUG}) + set(WJR_DEBUG_LEVEL_DEBUG ${WJR_DEBUG_LEVEL_DEBUG}) endif() if (NOT DEFINED WJR_DEBUG_LEVEL_RELEASE) - set(WJR_DEBUG_LEVEL_RELEASE_TMP 0) + set(WJR_DEBUG_LEVEL_RELEASE 0) else() - set(WJR_DEBUG_LEVEL_RELEASE_TMP ${WJR_DEBUG_LEVEL_RELEASE}) + set(WJR_DEBUG_LEVEL_RELEASE ${WJR_DEBUG_LEVEL_RELEASE}) endif() set(WJR_INCLUDE_DIR ${PROJECT_SOURCE_DIR}/include) @@ -111,8 +111,8 @@ if(MSVC) list(APPEND WJR_CXX_FLAGS /W3 /Zc:preprocessor /Zc:lambda /EHsc) - list(APPEND WJR_CXX_FLAGS_DEBUG /DWJR_DEBUG_LEVEL=${WJR_DEBUG_LEVEL_DEBUG_TMP}) - list(APPEND WJR_CXX_FLAGS_RELEASE /DWJR_DEBUG_LEVEL=${WJR_DEBUG_LEVEL_RELEASE_TMP}) + list(APPEND WJR_CXX_FLAGS_DEBUG /DWJR_DEBUG_LEVEL=${WJR_DEBUG_LEVEL_DEBUG}) + list(APPEND WJR_CXX_FLAGS_RELEASE /DWJR_DEBUG_LEVEL=${WJR_DEBUG_LEVEL_RELEASE}) if (WIN32) list(APPEND WJR_CXX_LINKER_FLAGS /lsynchronization) @@ -124,8 +124,8 @@ else() list(APPEND WJR_CXX_FLAGS -march=native -Wall -Wextra -Wshadow -Wformat=2 -Wunused) - list(APPEND WJR_CXX_FLAGS_DEBUG -DWJR_DEBUG_LEVEL=${WJR_DEBUG_LEVEL_DEBUG_TMP}) - list(APPEND WJR_CXX_FLAGS_RELEASE -DWJR_DEBUG_LEVEL=${WJR_DEBUG_LEVEL_RELEASE_TMP}) + list(APPEND WJR_CXX_FLAGS_DEBUG -DWJR_DEBUG_LEVEL=${WJR_DEBUG_LEVEL_DEBUG}) + list(APPEND WJR_CXX_FLAGS_RELEASE -DWJR_DEBUG_LEVEL=${WJR_DEBUG_LEVEL_RELEASE}) if (WIN32) list(APPEND WJR_CXX_LINKER_FLAGS -lsynchronization) @@ -165,6 +165,12 @@ if(WJR_DISABLE_EXCEPTIONS) ) endif() +if(WJR_LIGHT_ASSERT) + target_compile_definitions(wjr + PUBLIC $<$: -DWJR_LIGHT_ASSERT > + ) +endif() + if (WJR_USE_CXX_20) set(WJR_ATOMIC_LIBS) else() @@ -189,5 +195,5 @@ target_link_libraries(wjr ${WJR_ATOMIC_LIBS} ) -set(WJR_PCH PUBLIC ${WJR_INCLUDE_DIR}/wjr/assert.hpp ${WJR_INCLUDE_DIR}/wjr/biginteger.hpp) +set(WJR_PCH PUBLIC ${WJR_INCLUDE_DIR}/wjr/type_traits.hpp ${WJR_INCLUDE_DIR}/wjr/assert.hpp) target_precompile_headers(wjr PUBLIC ${WJR_PCH}) \ No newline at end of file diff --git a/include/wjr/biginteger/biginteger.hpp b/include/wjr/biginteger/biginteger.hpp index 48809e0c..7e2bfc2e 100644 --- a/include/wjr/biginteger/biginteger.hpp +++ b/include/wjr/biginteger/biginteger.hpp @@ -262,35 +262,35 @@ namespace biginteger_detail { /// @private template -bool __equal_pointer(const basic_biginteger *lhs, - const basic_biginteger *rhs) noexcept { +WJR_CONST bool __equal_pointer(const basic_biginteger *lhs, + const basic_biginteger *rhs) noexcept { return lhs == rhs; } /// @private template -bool __equal_pointer(const basic_biginteger *, - const basic_biginteger *) noexcept { +WJR_CONST bool __equal_pointer(const basic_biginteger *, + const basic_biginteger *) noexcept { return false; } /// @private template -bool __equal_pointer(const basic_biginteger *lhs, - const biginteger_data *rhs) noexcept { +WJR_PURE bool __equal_pointer(const basic_biginteger *lhs, + const biginteger_data *rhs) noexcept { return lhs->__get_data() == rhs; } /// @private template -bool __equal_pointer(const biginteger_data *lhs, - const basic_biginteger *rhs) noexcept { +WJR_PURE bool __equal_pointer(const biginteger_data *lhs, + const basic_biginteger *rhs) noexcept { return lhs == rhs->__get_data(); } /// @private -inline bool __equal_pointer(const biginteger_data *lhs, - const biginteger_data *rhs) noexcept { +WJR_CONST inline bool __equal_pointer(const biginteger_data *lhs, + const biginteger_data *rhs) noexcept { return lhs == rhs; } diff --git a/include/wjr/concurrency/rcu.hpp b/include/wjr/concurrency/lkf_ring_buffer.hpp similarity index 100% rename from include/wjr/concurrency/rcu.hpp rename to include/wjr/concurrency/lkf_ring_buffer.hpp diff --git a/include/wjr/concurrency/mutex-config.hpp b/include/wjr/concurrency/mutex-config.hpp deleted file mode 100644 index 323ca496..00000000 --- a/include/wjr/concurrency/mutex-config.hpp +++ /dev/null @@ -1,6 +0,0 @@ -#ifndef WJR_CONCURRENCY_MUTEX_CONFIG_HPP__ -#define WJR_CONCURRENCY_MUTEX_CONFIG_HPP__ - -#include - -#endif // WJR_CONCURRENCY_MUTEX_CONFIG_HPP__ \ No newline at end of file diff --git a/include/wjr/concurrency/scheduler.hpp b/include/wjr/concurrency/scheduler.hpp deleted file mode 100644 index 395ff690..00000000 --- a/include/wjr/concurrency/scheduler.hpp +++ /dev/null @@ -1,4 +0,0 @@ -#ifndef WJR_CONCURRENCY_SCHEDULER_HPP__ -#define WJR_CONCURRENCY_SCHEDULER_HPP__ - -#endif // WJR_CONCURRENCY_SCHEDULER_HPP__ \ No newline at end of file diff --git a/include/wjr/container/constant_map.hpp b/include/wjr/container/constant_map.hpp index f0751cf4..ca0fba79 100644 --- a/include/wjr/container/constant_map.hpp +++ b/include/wjr/container/constant_map.hpp @@ -4,7 +4,7 @@ #include #include -#include +#include namespace wjr { @@ -15,12 +15,17 @@ class string_map { public: using key_type = std::string_view; - constexpr string_map(const key_type (&keys)[KeySize]) noexcept : m_keys(keys) {} + constexpr string_map(const key_type (&keys)[KeySize]) noexcept : m_keys(keys) { + constant::sort(m_keys.begin(), m_keys.end()); + } private: std::array m_keys; }; +template +string_map(const std::string_view (&keys)[KeySize]) -> string_map; + } // namespace constant } // namespace wjr diff --git a/include/wjr/container/container_fn.hpp b/include/wjr/container/container_fn.hpp index 6b015e89..907b0fcf 100644 --- a/include/wjr/container/container_fn.hpp +++ b/include/wjr/container/container_fn.hpp @@ -8,7 +8,6 @@ namespace wjr { - /** * @class container_fn * @brief The same characteristics and behavior of all allocator containers diff --git a/include/wjr/format/encoding/huffman.hpp b/include/wjr/format/encoding/huffman.hpp index a1cc6cf6..50f6b691 100644 --- a/include/wjr/format/encoding/huffman.hpp +++ b/include/wjr/format/encoding/huffman.hpp @@ -8,17 +8,20 @@ namespace wjr { +template class huffman_node { public: huffman_node() = default; huffman_node(const huffman_node &) = delete; huffman_node &operator=(const huffman_node &) = delete; + huffman_node *left() noexcept { return m_left; } + const huffman_node *left() const noexcept { return m_left; } + huffman_node *right() noexcept { return m_right; } + const huffman_node *right() const noexcept { return m_right; } + void set_left(huffman_node *left) noexcept { m_left = left; } void set_right(huffman_node *right) noexcept { m_right = right; } - huffman_node *get_left() noexcept { return m_left; } - const huffman_node *get_left() const noexcept { return m_left; } - huffman_node *get_right() noexcept { return m_right; } bool is_leaf() const noexcept { return m_left == nullptr; } bool is_inner() const noexcept { return m_left != nullptr; } @@ -29,14 +32,14 @@ class huffman_node { }; template -class huffman_leaf_node : public huffman_node { +class huffman_leaf_node : public huffman_node { public: - huffman_leaf_node() noexcept : huffman_node(), m_value() {} + huffman_leaf_node() noexcept : huffman_node(), m_value() {} template )> huffman_leaf_node(Args &&...args) noexcept( std::is_nothrow_constructible_v) - : m_value(std::forward(args)...) {} + : huffman_node(), m_value(std::forward(args)...) {} huffman_leaf_node(const huffman_leaf_node &) = delete; huffman_leaf_node &operator=(const huffman_leaf_node &) = delete; @@ -52,50 +55,162 @@ class huffman_leaf_node : public huffman_node { }; template -constexpr huffman_leaf_node *get_leaf(huffman_node *node) { +constexpr huffman_leaf_node *get_leaf(huffman_node *node) { WJR_ASSERT(node->is_leaf()); return static_cast *>(node); } /// @todo Allocator. -template +template class huffman_tree { public: - using vector_type = fixed_vector; - using size_type = typename vector_type::size_type; + using node_type = huffman_node; + + huffman_tree(size_t n) : m_buffer(new char[n]) {} + + huffman_tree(const huffman_tree &) = delete; + huffman_tree(huffman_tree &&) = default; + huffman_tree &operator=(const huffman_tree &) = delete; + huffman_tree &operator=(huffman_tree &&) = default; + + node_type *root() noexcept { return reinterpret_cast(m_buffer.get()); } + const node_type *root() const noexcept { + return reinterpret_cast(m_buffer.get()); + } private: - fixed_vector m_vec; + std::unique_ptr m_buffer; +}; + +namespace huffman { + +template +struct __trivial_pair { + size_t first; + T second; }; +/// @brief Iter doesn't necessarily need to be an iterator. template -struct huffman_encode_node { - using size_type = typename Getter::size_type; +decltype(auto) build_tree(size_t n, Getter getter) noexcept { using value_type = typename Getter::value_type; + static_assert(std::is_trivial_v); + using tree_type = huffman_tree; + using pair_type = __trivial_pair; + using inner_type = huffman_node; + using leaf_type = huffman_leaf_node; + + std::unique_ptr buffer( + new char[sizeof(size_t) * (n - 1) + sizeof(pair_type) * n]); + + auto *size_first = reinterpret_cast(buffer.get()) + (n - 1); + auto *size_last = size_first; + auto *pair_first = reinterpret_cast(size_first); + + for (size_t i = 0; i < n; ++i) { + pair_first[i].first = getter.get_size(i); + pair_first[i].second = getter.get_value(i); + } - value_type m_value; -}; + std::sort(pair_first, pair_first + n, + [](const auto &lhs, const auto &rhs) { return lhs.first < rhs.first; }); -class huffman_encoder { -public: - /// @brief Iter doesn't necessarily need to be an iterator. - template - static decltype(auto) encode_tree(Iter first, Iter last, Getter getter) noexcept { - using size_type = typename Getter::size_type; - using value_type = typename Getter::value_type; - static constexpr size_type npos = std::numeric_limits::max(); - - const auto n = last - first; - fixed_vector> tmp_vec(n, in_place_reserve); - for (; first != last; ++first) { - tmp_vec.emplace_back(getter.get_size(first), getter.get_value(first)); - } + huffman_tree tree((n - 1) * sizeof(inner_type) + n * sizeof(leaf_type)); + inner_type *const inner_end = tree.root(); + auto *inner_first = inner_end + (n - 1); + auto *inner_last = inner_first; + auto *leaf_first = reinterpret_cast(inner_first); + auto *const leaf_last = leaf_first + n; - std::sort(tmp_vec.begin(), tmp_vec.end(), [](const auto &lhs, const auto &rhs) { - return lhs.first() < rhs.first(); - }); + for (size_t i = 0; i < n; ++i) { + wjr::construct_at(leaf_first + i, pair_first[i].second); } -}; + + if (n != 1) { + do { + size_t &total_size = size_last[-1]; + inner_type &new_node = inner_last[-1]; + do { + if (inner_first == inner_last) { + total_size = pair_first[0].first + pair_first[1].first; + new_node.set_left(leaf_first); + new_node.set_left(leaf_first + 1); + leaf_first += 2; + pair_first += 2; + break; + } + + size_t pair_size = pair_first->first; + do { + if (size_first[-1] < pair_size) { + total_size = size_first[-1]; + --inner_first; + --size_first; + new_node.set_left(inner_first); + + if (inner_first != inner_last && size_first[-1] < pair_size) { + total_size += size_first[-1]; + --inner_first; + --size_first; + new_node.set_right(inner_first); + + WJR_ASSUME(leaf_first != leaf_last); + break; + } + + total_size += pair_size; + new_node.set_right(leaf_first); + ++leaf_first; + ++pair_first; + break; + } + + total_size = pair_size; + new_node.set_left(leaf_first); + ++leaf_first; + ++pair_first; + + if (leaf_first == leaf_last || + (pair_size = pair_first->first, size_first[-1] < pair_size)) { + total_size += size_first[-1]; + --inner_first; + --size_first; + new_node.set_right(inner_first); + break; + } + + total_size += pair_size; + new_node.set_right(leaf_first); + ++leaf_first; + ++pair_first; + } while (0); + } while (0); + + --inner_last; + --size_last; + } while (leaf_first != leaf_last); + + if (inner_last != inner_end) { + do { + inner_type &new_node = inner_last[-1]; + size_t &total_size = size_last[-1]; + + total_size = size_first[-1] + size_first[-2]; + new_node.set_left(inner_first - 1); + new_node.set_right(inner_first - 2); + inner_first -= 2; + size_first -= 2; + + --inner_last; + --size_last; + } while (inner_last != inner_end); + } + } + + std::destroy_n(pair_first, n); + return tree; +} +} // namespace huffman } // namespace wjr diff --git a/include/wjr/memory/detail.hpp b/include/wjr/memory/detail.hpp index 054e24ed..431378d3 100644 --- a/include/wjr/memory/detail.hpp +++ b/include/wjr/memory/detail.hpp @@ -3,11 +3,17 @@ #include #include +#include #include namespace wjr { +template +struct get_relocate_mode> { + static constexpr relocate_t value = relocate_t::maybe_trivial; +}; + WJR_REGISTER_HAS_TYPE(pointer_traits_to_address, std::pointer_traits::to_address(std::declval()), Ptr); diff --git a/include/wjr/tp/detail.hpp b/include/wjr/tp/detail.hpp index 056f7a6e..65284ecd 100644 --- a/include/wjr/tp/detail.hpp +++ b/include/wjr/tp/detail.hpp @@ -514,8 +514,10 @@ struct tp_zip { C, std::make_index_sequence>>::template type; }; -/// @brief f(C, L, L ...) \ -/// -> L, C, ..., C> +/** + * @brief f(C, L, L ...) \ + * -> L, C, ..., C> + */ template