From 22c285111d701440bb3e1377d84e6aa28cd2bd9a Mon Sep 17 00:00:00 2001 From: yamacir-kit Date: Sun, 17 Dec 2023 01:05:51 +0900 Subject: [PATCH 01/12] Lipsticks Signed-off-by: yamacir-kit --- README.md | 6 +++--- VERSION | 2 +- include/meevax/kernel/procedure.hpp | 7 ++++--- 3 files changed, 8 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index fd5737181..d647947bb 100644 --- a/README.md +++ b/README.md @@ -91,7 +91,7 @@ Procedures for each standard are provided by the following R7RS-style libraries: cmake -B build -DCMAKE_BUILD_TYPE=Release cd build make package -sudo apt install build/meevax_0.5.107_amd64.deb +sudo apt install build/meevax_0.5.108_amd64.deb ``` or @@ -123,9 +123,9 @@ sudo rm -rf /usr/local/share/meevax | Target Name | Description |-------------|------------- -| `all` | Build shared-library `libmeevax.0.5.107.so` and executable `meevax` +| `all` | Build shared-library `libmeevax.0.5.108.so` and executable `meevax` | `test` | Test executable `meevax` -| `package` | Generate debian package `meevax_0.5.107_amd64.deb` +| `package` | Generate debian package `meevax_0.5.108_amd64.deb` | `install` | Copy files into `/usr/local` directly ## Usage diff --git a/VERSION b/VERSION index 1722d5958..e26991083 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -0.5.107 +0.5.108 diff --git a/include/meevax/kernel/procedure.hpp b/include/meevax/kernel/procedure.hpp index 186592ee8..338f06808 100644 --- a/include/meevax/kernel/procedure.hpp +++ b/include/meevax/kernel/procedure.hpp @@ -45,9 +45,10 @@ inline namespace kernel { std::enable_if_t or std::is_invocable_v, F> invocable; - explicit generic_procedure(std::string const& name, F f) - : primitive_procedure { name } - , invocable { f } + template + explicit generic_procedure(T && x, U && y) + : primitive_procedure { std::forward(x) } + , invocable { std::forward(y) } {} auto operator ()(object & xs) const -> object override From 5f9e789fe21dfeadea8b3a6b7c559a8b80e8f2a4 Mon Sep 17 00:00:00 2001 From: yamacir-kit Date: Sun, 17 Dec 2023 02:24:19 +0900 Subject: [PATCH 02/12] Split the library into `libmeevax-kernel.so` and `libmeevax-basis.so` Signed-off-by: yamacir-kit --- .gitignore | 2 +- CMakeLists.txt | 49 +++++++++++++++++++++--------- README.md | 6 ++-- VERSION | 2 +- basis/include/meevax/basis.hpp | 27 ++++++++++++++++ configure/basis.cmake | 15 --------- configure/{basis.hpp => basis.cpp} | 23 +++----------- example/CMakeLists.txt | 2 +- example/example.cpp | 1 + src/main.cpp | 2 +- test/environment.cpp | 2 +- 11 files changed, 75 insertions(+), 56 deletions(-) create mode 100644 basis/include/meevax/basis.hpp delete mode 100644 configure/basis.cmake rename configure/{basis.hpp => basis.cpp} (72%) diff --git a/.gitignore b/.gitignore index a77f72f2a..9628118d8 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,4 @@ +basis/src build -include/meevax/basis include/meevax/unicode src/kernel/version.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 6008cbafa..a1e3569b2 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -64,6 +64,33 @@ string(TOLOWER ${CMAKE_SYSTEM_NAME} ${PROJECT_NAME}_SYSTEM_NAME) configure_file(${CMAKE_CURRENT_SOURCE_DIR}/configure/README.md ${CMAKE_CURRENT_SOURCE_DIR}/README.md) configure_file(${CMAKE_CURRENT_SOURCE_DIR}/configure/version.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/kernel/version.cpp) +# ---- Target basis ------------------------------------------------------------ + +file(GLOB ${PROJECT_NAME}_BASIS_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/basis/*.ss) + +foreach(EACH IN LISTS ${PROJECT_NAME}_BASIS_SOURCES) + get_filename_component(FILENAME ${EACH} NAME) + file(READ ${EACH} ${FILENAME}) +endforeach() + +configure_file( + ${CMAKE_CURRENT_SOURCE_DIR}/configure/basis.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/basis/src/basis.cpp) + +add_library(basis SHARED) + +target_sources(basis PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/basis/src/basis.cpp) + +target_include_directories(basis + PUBLIC $ + PUBLIC $) + +set_target_properties(basis PROPERTIES + OUTPUT_NAME ${PROJECT_NAME}-basis # Rename libbasis => libmeevax-basis + VERSION ${PROJECT_VERSION} + SOVERSION ${PROJECT_VERSION_MAJOR} + LINK_FLAGS_RELEASE -s) + # ---- Target kernel ----------------------------------------------------------- add_library(kernel SHARED) @@ -81,25 +108,18 @@ target_link_libraries(kernel PUBLIC gmp) set_target_properties(kernel PROPERTIES - OUTPUT_NAME ${PROJECT_NAME} # Rename libkernel => libmeevax + OUTPUT_NAME ${PROJECT_NAME}-kernel # Rename libkernel => libmeevax-kernel VERSION ${PROJECT_VERSION} SOVERSION ${PROJECT_VERSION_MAJOR} LINK_FLAGS_RELEASE -s) -# ---- Target basis ------------------------------------------------------------ - -add_custom_target(basis - COMMAND ${CMAKE_COMMAND} -P ${CMAKE_CURRENT_SOURCE_DIR}/configure/basis.cmake) - # ---- Target shell ------------------------------------------------------------ add_executable(shell) -add_dependencies(shell basis) - target_sources(shell PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/src/main.cpp) -target_link_libraries(shell PRIVATE kernel) +target_link_libraries(shell PRIVATE basis kernel) set_target_properties(shell PROPERTIES OUTPUT_NAME ${PROJECT_NAME} # Rename shell => meevax @@ -116,7 +136,7 @@ write_basic_package_version_file( # ---- Target install ---------------------------------------------------------- install( # /usr/lib/libmeevax - TARGETS kernel + TARGETS basis kernel EXPORT ${PROJECT_NAME}-config ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}) @@ -126,7 +146,8 @@ install( # /usr/bin/meevax RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}) install( # /usr/include/meevax - DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/include/ + DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/include/ + ${CMAKE_CURRENT_SOURCE_DIR}/basis/include/ DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}) install( # /usr/share/meevax/meevax-config.cmake @@ -135,8 +156,7 @@ install( # /usr/share/meevax/meevax-config.cmake DESTINATION ${CMAKE_INSTALL_DATADIR}/${PROJECT_NAME} NAMESPACE Meevax::) -# /usr/share/meevax/meevax-config-version.cmake -install( +install( # /usr/share/meevax/meevax-config-version.cmake FILES ${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}-config-version.cmake DESTINATION ${CMAKE_INSTALL_DATADIR}/${PROJECT_NAME}) @@ -181,8 +201,7 @@ file(GLOB ${PROJECT_NAME}_TEST_CPP ${CMAKE_CURRENT_SOURCE_DIR}/test/*.cpp) foreach(EACH IN LISTS ${PROJECT_NAME}_TEST_CPP) get_filename_component(FILENAME ${EACH} NAME_WE) add_executable(assert-${FILENAME} ${EACH}) - add_dependencies(assert-${FILENAME} basis) - target_link_libraries(assert-${FILENAME} PRIVATE kernel) + target_link_libraries(assert-${FILENAME} PRIVATE basis kernel) add_test( NAME assert-${FILENAME} COMMAND ${${PROJECT_NAME}_MEMORY_CHECK_COMMAND} diff --git a/README.md b/README.md index d647947bb..265d58135 100644 --- a/README.md +++ b/README.md @@ -91,7 +91,7 @@ Procedures for each standard are provided by the following R7RS-style libraries: cmake -B build -DCMAKE_BUILD_TYPE=Release cd build make package -sudo apt install build/meevax_0.5.108_amd64.deb +sudo apt install build/meevax_0.5.109_amd64.deb ``` or @@ -123,9 +123,9 @@ sudo rm -rf /usr/local/share/meevax | Target Name | Description |-------------|------------- -| `all` | Build shared-library `libmeevax.0.5.108.so` and executable `meevax` +| `all` | Build shared-library `libmeevax.0.5.109.so` and executable `meevax` | `test` | Test executable `meevax` -| `package` | Generate debian package `meevax_0.5.108_amd64.deb` +| `package` | Generate debian package `meevax_0.5.109_amd64.deb` | `install` | Copy files into `/usr/local` directly ## Usage diff --git a/VERSION b/VERSION index e26991083..0799517fb 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -0.5.108 +0.5.109 diff --git a/basis/include/meevax/basis.hpp b/basis/include/meevax/basis.hpp new file mode 100644 index 000000000..9fe642b3a --- /dev/null +++ b/basis/include/meevax/basis.hpp @@ -0,0 +1,27 @@ +/* + Copyright 2018-2023 Tatsuya Yamasaki. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +#ifndef INCLUDED_MEEVAX_KERNEL_BASIS_HPP +#define INCLUDED_MEEVAX_KERNEL_BASIS_HPP + +#include + +namespace meevax +{ + auto basis() -> std::vector; +} // namespace meevax + +#endif // INCLUDED_MEEVAX_KERNEL_BASIS_HPP diff --git a/configure/basis.cmake b/configure/basis.cmake deleted file mode 100644 index 32884bc9c..000000000 --- a/configure/basis.cmake +++ /dev/null @@ -1,15 +0,0 @@ -execute_process( - COMMAND git rev-parse --show-toplevel - COMMAND tr -d "\n" - OUTPUT_VARIABLE TOPLEVEL) - -file(GLOB ${PROJECT_NAME}_BASIS_SOURCES ${TOPLEVEL}/basis/*.ss) - -foreach(EACH IN LISTS ${PROJECT_NAME}_BASIS_SOURCES) - get_filename_component(FILENAME ${EACH} NAME) - file(READ ${EACH} ${FILENAME}) -endforeach() - -configure_file( - ${TOPLEVEL}/configure/basis.hpp - ${TOPLEVEL}/include/meevax/basis/scheme.hpp) diff --git a/configure/basis.hpp b/configure/basis.cpp similarity index 72% rename from configure/basis.hpp rename to configure/basis.cpp index eac3bb9ee..cc6bc4a33 100644 --- a/configure/basis.hpp +++ b/configure/basis.cpp @@ -14,24 +14,13 @@ limitations under the License. */ -#ifndef INCLUDED_MEEVAX_KERNEL_BASIS_HPP -#define INCLUDED_MEEVAX_KERNEL_BASIS_HPP - -#include +#include namespace meevax { -inline namespace kernel -{ - template - constexpr auto make_array(Ts&&... xs) -> std::array>, sizeof...(Ts)> - { - return { std::forward(xs)... }; - } - - constexpr auto basis() + auto basis() -> std::vector { - return make_array( + return { R"##(${meevax.ss})##", R"##(${r4rs.ss})##", R"##(${r5rs.ss})##", @@ -53,9 +42,7 @@ inline namespace kernel R"##(${srfi-78.ss})##", R"##(${srfi-98.ss})##", R"##(${srfi-111.ss})##", - R"##(${srfi-149.ss})##"); + R"##(${srfi-149.ss})##", + }; } -} // namespace kernel } // namespace meevax - -#endif // INCLUDED_MEEVAX_KERNEL_BASIS_HPP diff --git a/example/CMakeLists.txt b/example/CMakeLists.txt index 89ab24b6b..ddfccd93a 100644 --- a/example/CMakeLists.txt +++ b/example/CMakeLists.txt @@ -10,7 +10,7 @@ add_library(${PROJECT_NAME} SHARED ${CMAKE_CURRENT_SOURCE_DIR}/${PROJECT_NAME}.c target_compile_options(${PROJECT_NAME} PUBLIC "-Wno-return-type-c-linkage") -target_link_libraries(${PROJECT_NAME} PRIVATE Meevax::kernel) +target_link_libraries(${PROJECT_NAME} PRIVATE Meevax::kernel Meevax::basis) enable_testing() diff --git a/example/example.cpp b/example/example.cpp index ce76447fd..7d3e75608 100644 --- a/example/example.cpp +++ b/example/example.cpp @@ -1,3 +1,4 @@ +#include #include using namespace meevax; // NOTE: DIRTY HACK diff --git a/src/main.cpp b/src/main.cpp index 33a6a6424..2dfdc45b7 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -14,7 +14,7 @@ limitations under the License. */ -#include +#include #include #include #include diff --git a/test/environment.cpp b/test/environment.cpp index 9665f6cdd..a0b2b51ff 100644 --- a/test/environment.cpp +++ b/test/environment.cpp @@ -1,7 +1,7 @@ #undef NDEBUG #include -#include +#include #include #include #include From 5a93a8af8f77681f03ebc2e3cc8a35e197ac9160 Mon Sep 17 00:00:00 2001 From: yamacir-kit Date: Sun, 24 Dec 2023 02:15:00 +0900 Subject: [PATCH 03/12] Rename `mutator::location` to `mutator::object` Signed-off-by: yamacir-kit --- README.md | 6 +++--- VERSION | 2 +- include/meevax/memory/collector.hpp | 12 ++++++------ include/meevax/memory/gc_pointer.hpp | 4 ++-- src/memory/collector.cpp | 8 ++++---- 5 files changed, 16 insertions(+), 16 deletions(-) diff --git a/README.md b/README.md index 265d58135..9629044d5 100644 --- a/README.md +++ b/README.md @@ -91,7 +91,7 @@ Procedures for each standard are provided by the following R7RS-style libraries: cmake -B build -DCMAKE_BUILD_TYPE=Release cd build make package -sudo apt install build/meevax_0.5.109_amd64.deb +sudo apt install build/meevax_0.5.110_amd64.deb ``` or @@ -123,9 +123,9 @@ sudo rm -rf /usr/local/share/meevax | Target Name | Description |-------------|------------- -| `all` | Build shared-library `libmeevax.0.5.109.so` and executable `meevax` +| `all` | Build shared-library `libmeevax.0.5.110.so` and executable `meevax` | `test` | Test executable `meevax` -| `package` | Generate debian package `meevax_0.5.109_amd64.deb` +| `package` | Generate debian package `meevax_0.5.110_amd64.deb` | `install` | Copy files into `/usr/local` directly ## Usage diff --git a/VERSION b/VERSION index 0799517fb..917f1bf5a 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -0.5.109 +0.5.110 diff --git a/include/meevax/memory/collector.hpp b/include/meevax/memory/collector.hpp index 02ce15d9b..a0aa973c8 100644 --- a/include/meevax/memory/collector.hpp +++ b/include/meevax/memory/collector.hpp @@ -121,14 +121,14 @@ inline namespace memory friend class collector; protected: - tag * location = nullptr; + tag * object = nullptr; explicit constexpr mutator() = default; - explicit mutator(tag * location) noexcept - : location { location } + explicit mutator(tag * object) noexcept + : object { object } { - if (location) + if (object) { mutators.insert(this); } @@ -136,7 +136,7 @@ inline namespace memory ~mutator() noexcept { - if (location) + if (object) { mutators.erase(this); } @@ -144,7 +144,7 @@ inline namespace memory auto reset(tag * after = nullptr) noexcept -> void { - if (auto before = std::exchange(location, after); not before and after) + if (auto before = std::exchange(object, after); not before and after) { mutators.insert(this); } diff --git a/include/meevax/memory/gc_pointer.hpp b/include/meevax/memory/gc_pointer.hpp index 3161b8b14..c737a9398 100644 --- a/include/meevax/memory/gc_pointer.hpp +++ b/include/meevax/memory/gc_pointer.hpp @@ -33,7 +33,7 @@ inline namespace memory gc_pointer(gc_pointer const& gcp) : pointer { gcp } - , collector::mutator { gcp.location } + , collector::mutator { gcp.object } {} gc_pointer(pointer const& p) @@ -72,7 +72,7 @@ inline namespace memory auto reset(gc_pointer const& gcp) -> void { pointer::reset(gcp); - collector::mutator::reset(gcp.location); + collector::mutator::reset(gcp.object); } auto reset(pointer const& p) -> void diff --git a/src/memory/collector.cpp b/src/memory/collector.cpp index ac3de4ded..9c5413ba0 100644 --- a/src/memory/collector.cpp +++ b/src/memory/collector.cpp @@ -123,11 +123,11 @@ inline namespace memory for (auto&& mutator : mutators) { assert(mutator); - assert(mutator->location); + assert(mutator->object); - if (not mutator->location->marked() and is_root_object(mutator)) + if (not mutator->object->marked() and is_root_object(mutator)) { - mark(mutator->location); + mark(mutator->object); } } } @@ -145,7 +145,7 @@ inline namespace memory for (auto iter = mutators.lower_bound(lower_address); iter != mutators.end() and *iter < upper_address; ++iter) { - mark((*iter)->location); + mark((*iter)->object); } } } From 96fe91dffa719e3378b662ce3229fd0b3a9eb614 Mon Sep 17 00:00:00 2001 From: yamacir-kit Date: Sat, 13 Jan 2024 17:52:17 +0900 Subject: [PATCH 04/12] Remove data member `cache` from class `pointer_set` Signed-off-by: yamacir-kit --- README.md | 6 ++-- VERSION | 2 +- include/meevax/memory/pointer_set.hpp | 40 +++++++-------------------- 3 files changed, 14 insertions(+), 34 deletions(-) diff --git a/README.md b/README.md index 9629044d5..21b27f833 100644 --- a/README.md +++ b/README.md @@ -91,7 +91,7 @@ Procedures for each standard are provided by the following R7RS-style libraries: cmake -B build -DCMAKE_BUILD_TYPE=Release cd build make package -sudo apt install build/meevax_0.5.110_amd64.deb +sudo apt install build/meevax_0.5.111_amd64.deb ``` or @@ -123,9 +123,9 @@ sudo rm -rf /usr/local/share/meevax | Target Name | Description |-------------|------------- -| `all` | Build shared-library `libmeevax.0.5.110.so` and executable `meevax` +| `all` | Build shared-library `libmeevax.0.5.111.so` and executable `meevax` | `test` | Test executable `meevax` -| `package` | Generate debian package `meevax_0.5.110_amd64.deb` +| `package` | Generate debian package `meevax_0.5.111_amd64.deb` | `install` | Copy files into `/usr/local` directly ## Usage diff --git a/VERSION b/VERSION index 917f1bf5a..aadb619e1 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -0.5.110 +0.5.111 diff --git a/include/meevax/memory/pointer_set.hpp b/include/meevax/memory/pointer_set.hpp index 45f87af0c..acee94a8f 100644 --- a/include/meevax/memory/pointer_set.hpp +++ b/include/meevax/memory/pointer_set.hpp @@ -37,7 +37,7 @@ namespace meevax inline namespace memory { template typename Map = simple_flat_map, + template typename OrderedMap = simple_flat_map, template typename Bitset = simple_bitset, std::size_t N = 4096 * 8> // getconf PAGE_SIZE class pointer_set @@ -92,9 +92,7 @@ inline namespace memory } }; - Map chunks; - - std::unordered_map::iterator> cache; + OrderedMap chunks; public: struct iterator @@ -109,14 +107,14 @@ inline namespace memory using difference_type = std::ptrdiff_t; - Map const& chunks; + OrderedMap const& chunks; - typename Map::const_iterator outer; + typename OrderedMap::const_iterator outer; typename chunk::const_iterator inner; - explicit iterator(Map const& chunks, - typename Map::const_iterator outer, + explicit iterator(OrderedMap const& chunks, + typename OrderedMap::const_iterator outer, std::size_t hint) : chunks { chunks } , outer { outer } @@ -129,7 +127,7 @@ inline namespace memory } } - explicit iterator(Map const& chunks) + explicit iterator(OrderedMap const& chunks) : chunks { chunks } , outer { chunks.end() } , inner {} @@ -240,23 +238,6 @@ inline namespace memory assert(begin() == end()); } - auto chunks_lower_bound(std::size_t offset) - { - if (auto iter = cache.find(offset); iter != cache.end()) - { - return iter->second; - } - else if (auto iter = chunks.lower_bound(offset); iter != chunks.end()) - { - cache.emplace(iter->first, iter); - return iter; - } - else - { - return iter; - } - } - auto size() const -> std::size_t { return std::distance(begin(), end()); @@ -264,7 +245,7 @@ inline namespace memory auto insert(compact_pointer p) { - if (auto iter = chunks_lower_bound(p.offset()); iter != chunks.end() and iter->first == p.offset()) + if (auto iter = chunks.lower_bound(p.offset()); iter != chunks.end() and iter->first == p.offset()) { iter->second.set(p.index()); } @@ -272,13 +253,12 @@ inline namespace memory { assert(iter == chunks.end() or p.offset() < iter->first); chunks.emplace_hint(iter, p.offset(), p.index()); - cache.clear(); } } auto erase(compact_pointer p) { - auto iter = chunks_lower_bound(p.offset()); + auto iter = chunks.lower_bound(p.offset()); assert(iter != chunks.end()); iter->second.reset(p.index()); } @@ -295,7 +275,7 @@ inline namespace memory auto lower_bound(compact_pointer p) { - if (auto iter = chunks_lower_bound(p.offset()); iter != chunks.end()) + if (auto iter = chunks.lower_bound(p.offset()); iter != chunks.end()) { return iterator(chunks, iter, p.index()); } From e63ce6b231cf369c7f47e0991f06fc6507e08300 Mon Sep 17 00:00:00 2001 From: yamacir-kit Date: Sun, 11 Feb 2024 01:23:03 +0900 Subject: [PATCH 05/12] Add experimental container `integer_set` Signed-off-by: yamacir-kit --- README.md | 6 +- VERSION | 2 +- include/meevax/memory/integer_set.hpp | 441 ++++++++++++++++++++++++++ test/pointer_set.cpp | 4 + 4 files changed, 449 insertions(+), 4 deletions(-) create mode 100644 include/meevax/memory/integer_set.hpp diff --git a/README.md b/README.md index 21b27f833..424adf11b 100644 --- a/README.md +++ b/README.md @@ -91,7 +91,7 @@ Procedures for each standard are provided by the following R7RS-style libraries: cmake -B build -DCMAKE_BUILD_TYPE=Release cd build make package -sudo apt install build/meevax_0.5.111_amd64.deb +sudo apt install build/meevax_0.5.112_amd64.deb ``` or @@ -123,9 +123,9 @@ sudo rm -rf /usr/local/share/meevax | Target Name | Description |-------------|------------- -| `all` | Build shared-library `libmeevax.0.5.111.so` and executable `meevax` +| `all` | Build shared-library `libmeevax.0.5.112.so` and executable `meevax` | `test` | Test executable `meevax` -| `package` | Generate debian package `meevax_0.5.111_amd64.deb` +| `package` | Generate debian package `meevax_0.5.112_amd64.deb` | `install` | Copy files into `/usr/local` directly ## Usage diff --git a/VERSION b/VERSION index aadb619e1..71d478751 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -0.5.111 +0.5.112 diff --git a/include/meevax/memory/integer_set.hpp b/include/meevax/memory/integer_set.hpp new file mode 100644 index 000000000..16a279c5b --- /dev/null +++ b/include/meevax/memory/integer_set.hpp @@ -0,0 +1,441 @@ +/* + Copyright 2018-2023 Tatsuya Yamasaki. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +#ifndef INCLUDED_MEEVAX_MEMORY_INTEGER_SET_HPP +#define INCLUDED_MEEVAX_MEMORY_INTEGER_SET_HPP + +#include +#include +#include +#include +#include +#include + +namespace meevax +{ +inline namespace memory +{ + template + struct integer_set + { + static constexpr auto N = static_cast(1) << E; + + using subset = integer_set; + + using superset = std::array, N>; + + superset data {}; + + struct const_iterator + { + using iterator_category = std::bidirectional_iterator_tag; + + using value_type = T; + + using reference = T const&; + + using pointer = T *; + + using difference_type = std::ptrdiff_t; + + superset const* data = nullptr; + + std::size_t index = std::numeric_limits::max(); + + typename subset::const_iterator iter; + + constexpr const_iterator() = default; + + explicit const_iterator(integer_set const& iset, std::size_t index) + : data { std::addressof(iset.data) } + , index { index } + { + assert(data); + assert(data->size() == N); + assert(index <= N); + increment_unless_truthy(); + } + + explicit const_iterator(integer_set const& iset) + : data { std::addressof(iset.data) } + , index { N } + { + assert(data); + decrement_unless_truthy(); + assert(iter.data); + } + + explicit const_iterator(integer_set const& set, std::tuple const& tuple) + : data { std::addressof(set.data) } + , index { std::get<0>(tuple) } + { + assert(data); + assert(data->size() == N); + assert(index <= N); + + auto child_index = std::get<1>(tuple); + + while (not out_of_range()) + { + if ((*data)[index]) + { + if (iter = (*data)[index]->lower_bound(child_index); not iter.out_of_range()) + { + return; + } + } + + while (++index < N and not (*data)[index]); + + child_index = 0; + } + + iter = {}; + } + + auto out_of_range() const -> bool + { + return not data or N <= index; + } + + auto increment_unless_truthy() -> void + { + assert(data); // incrementing end iterator + + while (not out_of_range()) + { + assert(data); + + if ((*data)[index]) + { + if (iter = typename subset::const_iterator(*(*data)[index], 0); not iter.out_of_range()) + { + assert(**this); + return; + } + } + + while (++index < N and not (*data)[index]); + } + + iter = {}; + } + + auto decrement_unless_truthy() -> void + { + assert(data); + + index = std::min(index, N - 1); + + assert(index < N); + + while (not out_of_range()) + { + assert(data); + + if (auto & datum = (*data)[index]) + { + if (iter = typename subset::const_iterator(*datum); not iter.out_of_range()) + { + assert(**this); + return; + } + } + + while (--index < N and not (*data)[index]); + } + + assert(data); + + iter = {}; + } + + auto operator ++() -> auto & + { + assert(data); + + if (++iter; iter.out_of_range()) + { + ++index; + increment_unless_truthy(); + } + + return *this; + } + + auto operator --() -> auto & + { + assert(data); + + if (not iter.data) + { + decrement_unless_truthy(); + return *this; + } + else + { + if (--iter; iter.out_of_range()) + { + --index; + decrement_unless_truthy(); + } + + return *this; + } + } + + auto operator *() const -> T + { + assert(index < N); + return reinterpret_cast(reinterpret_cast(index << (Es + ...)) bitor + reinterpret_cast(*iter)); + } + + auto is_end() const -> bool + { + return out_of_range() or iter.is_end(); + } + + auto is_same_index(const_iterator const& other) const -> bool + { + return index == other.index and iter.is_same_index(other.iter); + } + + friend auto operator ==(const_iterator const& a, const_iterator const& b) + { + return a.is_same_index(b) or (a.is_end() and b.is_end()); + } + + friend auto operator !=(const_iterator const& a, const_iterator const& b) + { + return not (a == b); + } + }; + + integer_set() + : data {} + { + assert(begin() == end()); + } + + template + static auto split(U p) -> std::tuple + { + auto datum = reinterpret_cast(p); + + constexpr std::size_t mask = (N - 1) << (Es + ...); + + return { (datum & mask) >> (Es + ...), reinterpret_cast(datum & ~mask) }; + } + + auto insert(T value) + { + if (auto [key, datum] = split(value); data[key]) + { + data[key]->insert(datum); + } + else + { + data[key] = std::make_unique(); + data[key]->insert(datum); + } + } + + auto erase(T value) + { + auto [key, datum] = split(value); + + data[key]->erase(datum); + } + + auto begin() const + { + return const_iterator(*this, 0); + } + + auto end() const + { + return const_iterator(*this, N); + } + + auto lower_bound(T value) const + { + return const_iterator(*this, split(value)); + } + + auto size() const -> std::size_t + { + return std::distance(begin(), end()); + } + }; + + template + struct integer_set + { + static constexpr auto N = static_cast(1) << E; + + using subset = std::bitset; + + subset data {}; + + struct const_iterator + { + using iterator_category = std::bidirectional_iterator_tag; + + using value_type = bool; + + using reference = bool &; + + using pointer = std::add_pointer_t; + + using difference_type = std::ptrdiff_t; + + subset const* data = nullptr; + + std::size_t index = std::numeric_limits::max(); + + auto increment_unless_truthy() + { + assert(data); + + while (index < N and not (*data)[index]) + { + ++index; + } + + assert(N <= index or (*data)[index]); + } + + auto decrement_unless_truthy() + { + assert(data); + + while (index < N and not (*data)[index]) + { + --index; + } + + assert(N <= index or (*data)[index]); + } + + auto out_of_range() const -> bool + { + return not data or N <= index; + } + + constexpr const_iterator() = default; + + explicit const_iterator(integer_set const& iset, std::size_t index) + : data { std::addressof(iset.data) } + , index { index } + { + increment_unless_truthy(); + assert(out_of_range() or (*data)[this->index]); + } + + explicit const_iterator(integer_set const& iset) + : data { std::addressof(iset.data) } + , index { N - 1 } + { + decrement_unless_truthy(); + } + + auto operator ++() -> decltype(auto) + { + ++index; + increment_unless_truthy(); + return *this; + } + + auto operator --() -> decltype(auto) + { + --index; + decrement_unless_truthy(); + return *this; + } + + auto operator *() const + { + assert(index < N); + return reinterpret_cast(index); + } + + auto is_end() const -> bool + { + return out_of_range(); + } + + auto is_same_index(const_iterator const& other) const -> bool + { + return index == other.index; + } + + friend auto operator ==(const_iterator const& a, const_iterator const& b) + { + return a.is_same_index(b) or (a.is_end() and b.is_end()); + } + + friend auto operator !=(const_iterator const& a, const_iterator const& b) + { + return not (a == b); + } + }; + + constexpr integer_set() + { + assert(data.none()); + } + + template + static constexpr auto split(U value) + { + return reinterpret_cast(value); + } + + auto insert(T value) + { + data.set(reinterpret_cast(value)); + } + + auto erase(T value) + { + data.reset(reinterpret_cast(value)); + } + + auto begin() const + { + return const_iterator(data, 0); + } + + auto end() const + { + return const_iterator(data); + } + + auto lower_bound(T value) const + { + return const_iterator(*this, split(value)); + } + + auto size() const + { + return std::distance(begin(), end()); + } + }; +} // namespace memory +} // namespace meevax + +#endif // INCLUDED_MEEVAX_MEMORY_INTEGER_SET_HPP diff --git a/test/pointer_set.cpp b/test/pointer_set.cpp index 273312e22..848712936 100644 --- a/test/pointer_set.cpp +++ b/test/pointer_set.cpp @@ -5,6 +5,7 @@ #include #include +#include #include #include #include @@ -117,5 +118,8 @@ auto main() -> int std::cout << measure>() << std::endl; std::cout << measure>() << std::endl; + std::cout << measure>() << std::endl; + std::cout << measure>() << std::endl; + return EXIT_SUCCESS; } From de928aa667b529ca1da255ef235a5b62ef6734e3 Mon Sep 17 00:00:00 2001 From: yamacir-kit Date: Sun, 11 Feb 2024 04:11:35 +0900 Subject: [PATCH 06/12] Update `integer_set` to optimize pointer types Signed-off-by: yamacir-kit --- README.md | 6 +- VERSION | 2 +- include/meevax/memory/collector.hpp | 4 +- include/meevax/memory/integer_set.hpp | 99 ++++++++++++++++++--------- include/meevax/memory/pointer_set.hpp | 11 +++ test/pointer_set.cpp | 11 ++- 6 files changed, 90 insertions(+), 43 deletions(-) diff --git a/README.md b/README.md index 424adf11b..1a017817d 100644 --- a/README.md +++ b/README.md @@ -91,7 +91,7 @@ Procedures for each standard are provided by the following R7RS-style libraries: cmake -B build -DCMAKE_BUILD_TYPE=Release cd build make package -sudo apt install build/meevax_0.5.112_amd64.deb +sudo apt install build/meevax_0.5.113_amd64.deb ``` or @@ -123,9 +123,9 @@ sudo rm -rf /usr/local/share/meevax | Target Name | Description |-------------|------------- -| `all` | Build shared-library `libmeevax.0.5.112.so` and executable `meevax` +| `all` | Build shared-library `libmeevax.0.5.113.so` and executable `meevax` | `test` | Test executable `meevax` -| `package` | Generate debian package `meevax_0.5.112_amd64.deb` +| `package` | Generate debian package `meevax_0.5.113_amd64.deb` | `install` | Copy files into `/usr/local` directly ## Usage diff --git a/VERSION b/VERSION index 71d478751..13cd94de8 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -0.5.112 +0.5.113 diff --git a/include/meevax/memory/collector.hpp b/include/meevax/memory/collector.hpp index a0aa973c8..0c9675431 100644 --- a/include/meevax/memory/collector.hpp +++ b/include/meevax/memory/collector.hpp @@ -181,9 +181,9 @@ inline namespace memory protected: static inline tag * cache = nullptr; - static inline pointer_set tags {}; + static inline v2::pointer_set tags {}; - static inline pointer_set mutators {}; + static inline v2::pointer_set mutators {}; static inline std::size_t allocation = 0; diff --git a/include/meevax/memory/integer_set.hpp b/include/meevax/memory/integer_set.hpp index 16a279c5b..849273475 100644 --- a/include/meevax/memory/integer_set.hpp +++ b/include/meevax/memory/integer_set.hpp @@ -18,24 +18,67 @@ #define INCLUDED_MEEVAX_MEMORY_INTEGER_SET_HPP #include -#include #include #include #include #include +#include + +#include +#include namespace meevax { inline namespace memory { + template + constexpr auto compressible_bitwidth_of = log2(alignof(std::remove_pointer_t)) - 1; + template struct integer_set { - static constexpr auto N = static_cast(1) << E; + static_assert(sizeof(T) <= sizeof(std::uintptr_t)); - using subset = integer_set; + static constexpr auto chunk_size() + { + if constexpr (std::is_pointer_v) + { + static_assert(compressible_bitwidth_of < E); + return static_cast(1) << (E - compressible_bitwidth_of); + } + else + { + return static_cast(1) << E; + } + } - using superset = std::array, N>; + static constexpr auto compress(T value) + { + if constexpr (std::is_pointer_v) + { + return reinterpret_cast(value) >> compressible_bitwidth_of; + } + else + { + return reinterpret_cast(value); + } + } + + static constexpr auto decompress(std::uintptr_t value) + { + if constexpr (std::is_pointer_v) + { + return reinterpret_cast(value << compressible_bitwidth_of); + } + else + { + return reinterpret_cast(value); + } + } + + using subset = integer_set; // Only the outermost implementation knows the original type name T. + + using superset = std::array, chunk_size()>; superset data {}; @@ -64,27 +107,27 @@ inline namespace memory , index { index } { assert(data); - assert(data->size() == N); - assert(index <= N); + assert(data->size() == chunk_size()); + assert(index <= chunk_size()); increment_unless_truthy(); } explicit const_iterator(integer_set const& iset) : data { std::addressof(iset.data) } - , index { N } + , index { chunk_size() } { assert(data); decrement_unless_truthy(); assert(iter.data); } - explicit const_iterator(integer_set const& set, std::tuple const& tuple) + explicit const_iterator(integer_set const& set, std::tuple const& tuple) : data { std::addressof(set.data) } , index { std::get<0>(tuple) } { assert(data); - assert(data->size() == N); - assert(index <= N); + assert(data->size() == chunk_size()); + assert(index <= chunk_size()); auto child_index = std::get<1>(tuple); @@ -98,7 +141,7 @@ inline namespace memory } } - while (++index < N and not (*data)[index]); + while (++index < chunk_size() and not (*data)[index]); child_index = 0; } @@ -108,7 +151,7 @@ inline namespace memory auto out_of_range() const -> bool { - return not data or N <= index; + return not data or chunk_size() <= index; } auto increment_unless_truthy() -> void @@ -128,7 +171,7 @@ inline namespace memory } } - while (++index < N and not (*data)[index]); + while (++index < chunk_size() and not (*data)[index]); } iter = {}; @@ -138,9 +181,9 @@ inline namespace memory { assert(data); - index = std::min(index, N - 1); + index = std::min(index, chunk_size() - 1); - assert(index < N); + assert(index < chunk_size()); while (not out_of_range()) { @@ -155,7 +198,7 @@ inline namespace memory } } - while (--index < N and not (*data)[index]); + while (--index < chunk_size() and not (*data)[index]); } assert(data); @@ -199,9 +242,9 @@ inline namespace memory auto operator *() const -> T { - assert(index < N); - return reinterpret_cast(reinterpret_cast(index << (Es + ...)) bitor - reinterpret_cast(*iter)); + assert(index < chunk_size()); + + return decompress(index << (Es + ...) bitor *iter); } auto is_end() const -> bool @@ -231,14 +274,13 @@ inline namespace memory assert(begin() == end()); } - template - static auto split(U p) -> std::tuple + static constexpr auto split(T p) { - auto datum = reinterpret_cast(p); + auto datum = compress(p); - constexpr std::size_t mask = (N - 1) << (Es + ...); + constexpr std::uintptr_t mask = (chunk_size() - 1) << (Es + ...); - return { (datum & mask) >> (Es + ...), reinterpret_cast(datum & ~mask) }; + return std::make_pair((datum & mask) >> (Es + ...), datum & ~mask); } auto insert(T value) @@ -268,7 +310,7 @@ inline namespace memory auto end() const { - return const_iterator(*this, N); + return const_iterator(*this, chunk_size()); } auto lower_bound(T value) const @@ -287,7 +329,7 @@ inline namespace memory { static constexpr auto N = static_cast(1) << E; - using subset = std::bitset; + using subset = simple_bitset; subset data {}; @@ -394,11 +436,6 @@ inline namespace memory } }; - constexpr integer_set() - { - assert(data.none()); - } - template static constexpr auto split(U value) { diff --git a/include/meevax/memory/pointer_set.hpp b/include/meevax/memory/pointer_set.hpp index acee94a8f..bcffe600a 100644 --- a/include/meevax/memory/pointer_set.hpp +++ b/include/meevax/memory/pointer_set.hpp @@ -31,10 +31,13 @@ #include #include #include +#include namespace meevax { inline namespace memory +{ +inline namespace v1 { template typename OrderedMap = simple_flat_map, @@ -285,6 +288,14 @@ inline namespace memory } } }; +} // namespace v1 + +namespace v2 +{ + template + struct pointer_set : integer_set + {}; +} // namespace v2 } // namespace memory } // namespace meevax diff --git a/test/pointer_set.cpp b/test/pointer_set.cpp index 848712936..2e58330fb 100644 --- a/test/pointer_set.cpp +++ b/test/pointer_set.cpp @@ -113,13 +113,12 @@ auto measure() auto main() -> int { - std::cout << measure>() << std::endl; - std::cout << measure>() << std::endl; - std::cout << measure>() << std::endl; - std::cout << measure>() << std::endl; + std::cout << measure>() << std::endl; + std::cout << measure>() << std::endl; + std::cout << measure>() << std::endl; + std::cout << measure>() << std::endl; - std::cout << measure>() << std::endl; - std::cout << measure>() << std::endl; + std::cout << measure>() << std::endl; return EXIT_SUCCESS; } From 0fa3d77e883de71768cca1c3fbebae5e784a32de Mon Sep 17 00:00:00 2001 From: yamacir-kit Date: Sun, 11 Feb 2024 05:20:43 +0900 Subject: [PATCH 07/12] Cleanup struct template `integer_set` Signed-off-by: yamacir-kit --- README.md | 6 +-- VERSION | 2 +- include/meevax/memory/integer_set.hpp | 60 +++++---------------------- 3 files changed, 15 insertions(+), 53 deletions(-) diff --git a/README.md b/README.md index 1a017817d..67224a4db 100644 --- a/README.md +++ b/README.md @@ -91,7 +91,7 @@ Procedures for each standard are provided by the following R7RS-style libraries: cmake -B build -DCMAKE_BUILD_TYPE=Release cd build make package -sudo apt install build/meevax_0.5.113_amd64.deb +sudo apt install build/meevax_0.5.114_amd64.deb ``` or @@ -123,9 +123,9 @@ sudo rm -rf /usr/local/share/meevax | Target Name | Description |-------------|------------- -| `all` | Build shared-library `libmeevax.0.5.113.so` and executable `meevax` +| `all` | Build shared-library `libmeevax.0.5.114.so` and executable `meevax` | `test` | Test executable `meevax` -| `package` | Generate debian package `meevax_0.5.113_amd64.deb` +| `package` | Generate debian package `meevax_0.5.114_amd64.deb` | `install` | Copy files into `/usr/local` directly ## Usage diff --git a/VERSION b/VERSION index 13cd94de8..b7e7193f5 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -0.5.113 +0.5.114 diff --git a/include/meevax/memory/integer_set.hpp b/include/meevax/memory/integer_set.hpp index 849273475..1469b2688 100644 --- a/include/meevax/memory/integer_set.hpp +++ b/include/meevax/memory/integer_set.hpp @@ -76,7 +76,7 @@ inline namespace memory } } - using subset = integer_set; // Only the outermost implementation knows the original type name T. + using subset = integer_set; // Only the outermost implementation knows the original type name T. using superset = std::array, chunk_size()>; @@ -102,76 +102,44 @@ inline namespace memory constexpr const_iterator() = default; - explicit const_iterator(integer_set const& iset, std::size_t index) + explicit const_iterator(integer_set const& iset, std::size_t index, std::uintptr_t child_index = 0) : data { std::addressof(iset.data) } , index { index } { - assert(data); - assert(data->size() == chunk_size()); assert(index <= chunk_size()); - increment_unless_truthy(); + increment_unless_truthy(child_index); } explicit const_iterator(integer_set const& iset) : data { std::addressof(iset.data) } , index { chunk_size() } { - assert(data); decrement_unless_truthy(); assert(iter.data); } - explicit const_iterator(integer_set const& set, std::tuple const& tuple) - : data { std::addressof(set.data) } - , index { std::get<0>(tuple) } - { - assert(data); - assert(data->size() == chunk_size()); - assert(index <= chunk_size()); - - auto child_index = std::get<1>(tuple); - - while (not out_of_range()) - { - if ((*data)[index]) - { - if (iter = (*data)[index]->lower_bound(child_index); not iter.out_of_range()) - { - return; - } - } - - while (++index < chunk_size() and not (*data)[index]); - - child_index = 0; - } - - iter = {}; - } - auto out_of_range() const -> bool { return not data or chunk_size() <= index; } - auto increment_unless_truthy() -> void + auto increment_unless_truthy(std::uintptr_t child_index = 0) -> void { assert(data); // incrementing end iterator - while (not out_of_range()) + while (index < chunk_size()) { - assert(data); - if ((*data)[index]) { - if (iter = typename subset::const_iterator(*(*data)[index], 0); not iter.out_of_range()) + if (iter = (*data)[index]->lower_bound(child_index); not iter.out_of_range()) { - assert(**this); return; } } while (++index < chunk_size() and not (*data)[index]); + + child_index = 0; } iter = {}; @@ -185,7 +153,7 @@ inline namespace memory assert(index < chunk_size()); - while (not out_of_range()) + while (index < chunk_size()) { assert(data); @@ -268,12 +236,6 @@ inline namespace memory } }; - integer_set() - : data {} - { - assert(begin() == end()); - } - static constexpr auto split(T p) { auto datum = compress(p); @@ -299,7 +261,6 @@ inline namespace memory auto erase(T value) { auto [key, datum] = split(value); - data[key]->erase(datum); } @@ -315,7 +276,8 @@ inline namespace memory auto lower_bound(T value) const { - return const_iterator(*this, split(value)); + auto [index, child_index] = split(value); + return const_iterator(*this, index, child_index); } auto size() const -> std::size_t From 9926a2b35028459e464b1ef3d54198f93158463f Mon Sep 17 00:00:00 2001 From: yamacir-kit Date: Tue, 13 Feb 2024 01:07:39 +0900 Subject: [PATCH 08/12] Cleanup struct template `integer_set` Signed-off-by: yamacir-kit --- README.md | 6 +- VERSION | 2 +- include/meevax/memory/integer_set.hpp | 242 ++++++++++---------------- 3 files changed, 93 insertions(+), 157 deletions(-) diff --git a/README.md b/README.md index 67224a4db..ddc1c6839 100644 --- a/README.md +++ b/README.md @@ -91,7 +91,7 @@ Procedures for each standard are provided by the following R7RS-style libraries: cmake -B build -DCMAKE_BUILD_TYPE=Release cd build make package -sudo apt install build/meevax_0.5.114_amd64.deb +sudo apt install build/meevax_0.5.115_amd64.deb ``` or @@ -123,9 +123,9 @@ sudo rm -rf /usr/local/share/meevax | Target Name | Description |-------------|------------- -| `all` | Build shared-library `libmeevax.0.5.114.so` and executable `meevax` +| `all` | Build shared-library `libmeevax.0.5.115.so` and executable `meevax` | `test` | Test executable `meevax` -| `package` | Generate debian package `meevax_0.5.114_amd64.deb` +| `package` | Generate debian package `meevax_0.5.115_amd64.deb` | `install` | Copy files into `/usr/local` directly ## Usage diff --git a/VERSION b/VERSION index b7e7193f5..11e4875e9 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -0.5.114 +0.5.115 diff --git a/include/meevax/memory/integer_set.hpp b/include/meevax/memory/integer_set.hpp index 1469b2688..da830268f 100644 --- a/include/meevax/memory/integer_set.hpp +++ b/include/meevax/memory/integer_set.hpp @@ -21,7 +21,6 @@ #include #include #include -#include #include #include @@ -39,18 +38,9 @@ inline namespace memory { static_assert(sizeof(T) <= sizeof(std::uintptr_t)); - static constexpr auto chunk_size() - { - if constexpr (std::is_pointer_v) - { - static_assert(compressible_bitwidth_of < E); - return static_cast(1) << (E - compressible_bitwidth_of); - } - else - { - return static_cast(1) << E; - } - } + static_assert(not std::is_pointer_v or compressible_bitwidth_of < E); + + static constexpr auto N = static_cast(1) << E - (std::is_pointer_v ? compressible_bitwidth_of : 0); static constexpr auto compress(T value) { @@ -78,68 +68,44 @@ inline namespace memory using subset = integer_set; // Only the outermost implementation knows the original type name T. - using superset = std::array, chunk_size()>; + using superset = std::array; superset data {}; - struct const_iterator + struct const_iterator : public std::iterator { - using iterator_category = std::bidirectional_iterator_tag; - - using value_type = T; - - using reference = T const&; - - using pointer = T *; - - using difference_type = std::ptrdiff_t; - superset const* data = nullptr; - std::size_t index = std::numeric_limits::max(); + std::size_t i = std::numeric_limits::max(); typename subset::const_iterator iter; constexpr const_iterator() = default; - explicit const_iterator(integer_set const& iset, std::size_t index, std::uintptr_t child_index = 0) - : data { std::addressof(iset.data) } - , index { index } + explicit const_iterator(integer_set const* container, std::size_t i, std::uintptr_t j = 0) + : data { std::addressof(container->data) } + , i { i } { - assert(index <= chunk_size()); - increment_unless_truthy(child_index); + assert(i <= N); + increment_unless_truthy(j); } - explicit const_iterator(integer_set const& iset) - : data { std::addressof(iset.data) } - , index { chunk_size() } + explicit const_iterator(integer_set const* container) + : data { std::addressof(container->data) } + , i { N } { decrement_unless_truthy(); assert(iter.data); } - auto out_of_range() const -> bool - { - return not data or chunk_size() <= index; - } - - auto increment_unless_truthy(std::uintptr_t child_index = 0) -> void + auto increment_unless_truthy(std::uintptr_t j = 0) -> void { - assert(data); // incrementing end iterator - - while (index < chunk_size()) + for (assert(data); good(); ++i, j = 0) { - if ((*data)[index]) + if (auto datum = (*data)[i]; datum and (iter = datum->lower_bound(j)).good()) { - if (iter = (*data)[index]->lower_bound(child_index); not iter.out_of_range()) - { - return; - } + return; } - - while (++index < chunk_size() and not (*data)[index]); - - child_index = 0; } iter = {}; @@ -147,40 +113,26 @@ inline namespace memory auto decrement_unless_truthy() -> void { - assert(data); - - index = std::min(index, chunk_size() - 1); + i = std::min(i, N - 1); - assert(index < chunk_size()); + assert(good()); - while (index < chunk_size()) + for (assert(data); good(); --i) { - assert(data); - - if (auto & datum = (*data)[index]) + if (auto datum = (*data)[i]; datum and (iter = typename subset::const_iterator(datum)).good()) { - if (iter = typename subset::const_iterator(*datum); not iter.out_of_range()) - { - assert(**this); - return; - } + return; } - - while (--index < chunk_size() and not (*data)[index]); } - assert(data); - iter = {}; } auto operator ++() -> auto & { - assert(data); - - if (++iter; iter.out_of_range()) + if (++iter; not iter.good()) { - ++index; + ++i; increment_unless_truthy(); } @@ -189,45 +141,44 @@ inline namespace memory auto operator --() -> auto & { - assert(data); - if (not iter.data) { decrement_unless_truthy(); - return *this; } - else + else if (--iter; not iter.good()) { - if (--iter; iter.out_of_range()) - { - --index; - decrement_unless_truthy(); - } - - return *this; + --i; + decrement_unless_truthy(); } + + return *this; } auto operator *() const -> T { - assert(index < chunk_size()); + assert(good()); + return decompress(i << (Es + ...) bitor *iter); + } - return decompress(index << (Es + ...) bitor *iter); + auto good() const noexcept -> bool + { + assert(data); + return i < N; } - auto is_end() const -> bool + auto at_end() const -> bool { - return out_of_range() or iter.is_end(); + return not data or not good() or iter.at_end(); } auto is_same_index(const_iterator const& other) const -> bool { - return index == other.index and iter.is_same_index(other.iter); + return i == other.i and iter.is_same_index(other.iter); } friend auto operator ==(const_iterator const& a, const_iterator const& b) { - return a.is_same_index(b) or (a.is_end() and b.is_end()); + return a.is_same_index(b) or (a.at_end() and b.at_end()); } friend auto operator !=(const_iterator const& a, const_iterator const& b) @@ -240,9 +191,17 @@ inline namespace memory { auto datum = compress(p); - constexpr std::uintptr_t mask = (chunk_size() - 1) << (Es + ...); + constexpr std::uintptr_t mask = (N - 1) << (Es + ...); - return std::make_pair((datum & mask) >> (Es + ...), datum & ~mask); + return std::make_pair((datum & mask) >> (Es + ...), datum & ~mask); + } + + ~integer_set() + { + for (auto datum : data) + { + delete datum; + } } auto insert(T value) @@ -253,31 +212,31 @@ inline namespace memory } else { - data[key] = std::make_unique(); + data[key] = new subset(); data[key]->insert(datum); } } auto erase(T value) { - auto [key, datum] = split(value); - data[key]->erase(datum); + auto [i, j] = split(value); + data[i]->erase(j); } auto begin() const { - return const_iterator(*this, 0); + return const_iterator(this, 0); } auto end() const { - return const_iterator(*this, chunk_size()); + return const_iterator(this, N); } auto lower_bound(T value) const { - auto [index, child_index] = split(value); - return const_iterator(*this, index, child_index); + auto [i, j] = split(value); + return const_iterator(this, i, j); } auto size() const -> std::size_t @@ -295,101 +254,84 @@ inline namespace memory subset data {}; - struct const_iterator + struct const_iterator : public std::iterator { - using iterator_category = std::bidirectional_iterator_tag; - - using value_type = bool; - - using reference = bool &; - - using pointer = std::add_pointer_t; - - using difference_type = std::ptrdiff_t; - subset const* data = nullptr; - std::size_t index = std::numeric_limits::max(); + std::size_t i = std::numeric_limits::max(); auto increment_unless_truthy() { - assert(data); + for (assert(data); good() and not (*data)[i]; ++i) + {} - while (index < N and not (*data)[index]) - { - ++index; - } - - assert(N <= index or (*data)[index]); + assert(not good() or (*data)[i]); } auto decrement_unless_truthy() { - assert(data); - - while (index < N and not (*data)[index]) - { - --index; - } - - assert(N <= index or (*data)[index]); - } + for (assert(data); good() and not (*data)[i]; --i) + {} - auto out_of_range() const -> bool - { - return not data or N <= index; + assert(not good() or (*data)[i]); } constexpr const_iterator() = default; - explicit const_iterator(integer_set const& iset, std::size_t index) - : data { std::addressof(iset.data) } - , index { index } + explicit const_iterator(integer_set const* container, std::size_t i) + : data { std::addressof(container->data) } + , i { i } { increment_unless_truthy(); - assert(out_of_range() or (*data)[this->index]); + assert(not good() or (*data)[this->i]); } - explicit const_iterator(integer_set const& iset) - : data { std::addressof(iset.data) } - , index { N - 1 } + explicit const_iterator(integer_set const* container) + : data { std::addressof(container->data) } + , i { N - 1 } { decrement_unless_truthy(); } auto operator ++() -> decltype(auto) { - ++index; + ++i; increment_unless_truthy(); return *this; } auto operator --() -> decltype(auto) { - --index; + --i; decrement_unless_truthy(); return *this; } auto operator *() const { - assert(index < N); - return reinterpret_cast(index); + assert(good()); + return reinterpret_cast(i); + } + + auto good() const noexcept -> bool + { + assert(data); + return i < N; } - auto is_end() const -> bool + auto at_end() const -> bool { - return out_of_range(); + return not data or not good(); } auto is_same_index(const_iterator const& other) const -> bool { - return index == other.index; + return i == other.i; } friend auto operator ==(const_iterator const& a, const_iterator const& b) { - return a.is_same_index(b) or (a.is_end() and b.is_end()); + return a.is_same_index(b) or (a.at_end() and b.at_end()); } friend auto operator !=(const_iterator const& a, const_iterator const& b) @@ -398,12 +340,6 @@ inline namespace memory } }; - template - static constexpr auto split(U value) - { - return reinterpret_cast(value); - } - auto insert(T value) { data.set(reinterpret_cast(value)); @@ -421,12 +357,12 @@ inline namespace memory auto end() const { - return const_iterator(data); + return const_iterator(data, N); } auto lower_bound(T value) const { - return const_iterator(*this, split(value)); + return const_iterator(this, reinterpret_cast(value)); } auto size() const From fa086024d954bae1623c0db02854eb370224b8bd Mon Sep 17 00:00:00 2001 From: yamacir-kit Date: Thu, 15 Feb 2024 23:32:40 +0900 Subject: [PATCH 09/12] Declare `v1::pointer_set` deprecated Signed-off-by: yamacir-kit --- CMakeLists.txt | 9 +++++---- README.md | 6 +++--- VERSION | 2 +- include/meevax/kernel/pair.hpp | 6 +++++- include/meevax/memory/integer_set.hpp | 24 ++++++++++++------------ include/meevax/memory/pointer_set.hpp | 2 +- src/kernel/pair.cpp | 4 ++++ 7 files changed, 31 insertions(+), 22 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index a1e3569b2..dcd7e9160 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -200,13 +200,14 @@ file(GLOB ${PROJECT_NAME}_TEST_CPP ${CMAKE_CURRENT_SOURCE_DIR}/test/*.cpp) foreach(EACH IN LISTS ${PROJECT_NAME}_TEST_CPP) get_filename_component(FILENAME ${EACH} NAME_WE) - add_executable(assert-${FILENAME} ${EACH}) - target_link_libraries(assert-${FILENAME} PRIVATE basis kernel) + add_executable(test_${FILENAME} ${EACH}) + target_link_libraries(test_${FILENAME} PRIVATE basis kernel) + target_compile_options(test_${FILENAME} PUBLIC -Wno-deprecated-declarations) add_test( - NAME assert-${FILENAME} + NAME test/${FILENAME} COMMAND ${${PROJECT_NAME}_MEMORY_CHECK_COMMAND} ${${PROJECT_NAME}_MEMORY_CHECK_OPTIONS} - ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/assert-${FILENAME}) + ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/test_${FILENAME}) endforeach() # ---- Additional Targets ------------------------------------------------------ diff --git a/README.md b/README.md index ddc1c6839..775f6851e 100644 --- a/README.md +++ b/README.md @@ -91,7 +91,7 @@ Procedures for each standard are provided by the following R7RS-style libraries: cmake -B build -DCMAKE_BUILD_TYPE=Release cd build make package -sudo apt install build/meevax_0.5.115_amd64.deb +sudo apt install build/meevax_0.5.116_amd64.deb ``` or @@ -123,9 +123,9 @@ sudo rm -rf /usr/local/share/meevax | Target Name | Description |-------------|------------- -| `all` | Build shared-library `libmeevax.0.5.115.so` and executable `meevax` +| `all` | Build shared-library `libmeevax.0.5.116.so` and executable `meevax` | `test` | Test executable `meevax` -| `package` | Generate debian package `meevax_0.5.115_amd64.deb` +| `package` | Generate debian package `meevax_0.5.116_amd64.deb` | `install` | Copy files into `/usr/local` directly ## Usage diff --git a/VERSION b/VERSION index 11e4875e9..34076ef25 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -0.5.115 +0.5.116 diff --git a/include/meevax/kernel/pair.hpp b/include/meevax/kernel/pair.hpp index 2ea70c124..a5b02366f 100644 --- a/include/meevax/kernel/pair.hpp +++ b/include/meevax/kernel/pair.hpp @@ -136,7 +136,11 @@ inline namespace kernel using const_iterator = forward_iterator; - explicit pair(object const& = unit, object const& = unit); + constexpr pair() = default; + + explicit pair(object const&); + + explicit pair(object const&, object const&); template > explicit pair(object const& a, Ts&&... xs) diff --git a/include/meevax/memory/integer_set.hpp b/include/meevax/memory/integer_set.hpp index da830268f..a380d1909 100644 --- a/include/meevax/memory/integer_set.hpp +++ b/include/meevax/memory/integer_set.hpp @@ -68,13 +68,13 @@ inline namespace memory using subset = integer_set; // Only the outermost implementation knows the original type name T. - using superset = std::array; + using subsets = subset *[N]; - superset data {}; + subsets data = {}; struct const_iterator : public std::iterator { - superset const* data = nullptr; + subset const* const* data = nullptr; std::size_t i = std::numeric_limits::max(); @@ -83,7 +83,7 @@ inline namespace memory constexpr const_iterator() = default; explicit const_iterator(integer_set const* container, std::size_t i, std::uintptr_t j = 0) - : data { std::addressof(container->data) } + : data { container->data } , i { i } { assert(i <= N); @@ -91,7 +91,7 @@ inline namespace memory } explicit const_iterator(integer_set const* container) - : data { std::addressof(container->data) } + : data { container->data } , i { N } { decrement_unless_truthy(); @@ -100,9 +100,11 @@ inline namespace memory auto increment_unless_truthy(std::uintptr_t j = 0) -> void { - for (assert(data); good(); ++i, j = 0) + assert(data); + + for (; good(); ++i, j = 0) { - if (auto datum = (*data)[i]; datum and (iter = datum->lower_bound(j)).good()) + if (data[i] and (iter = data[i]->lower_bound(j)).good()) { return; } @@ -113,13 +115,11 @@ inline namespace memory auto decrement_unless_truthy() -> void { - i = std::min(i, N - 1); - - assert(good()); + assert(data); - for (assert(data); good(); --i) + for (i = std::min(i, N - 1); good(); --i) { - if (auto datum = (*data)[i]; datum and (iter = typename subset::const_iterator(datum)).good()) + if (data[i] and (iter = typename subset::const_iterator(data[i])).good()) { return; } diff --git a/include/meevax/memory/pointer_set.hpp b/include/meevax/memory/pointer_set.hpp index bcffe600a..b0fd052de 100644 --- a/include/meevax/memory/pointer_set.hpp +++ b/include/meevax/memory/pointer_set.hpp @@ -43,7 +43,7 @@ inline namespace v1 template typename OrderedMap = simple_flat_map, template typename Bitset = simple_bitset, std::size_t N = 4096 * 8> // getconf PAGE_SIZE - class pointer_set + class [[deprecated]] pointer_set { static_assert(std::is_pointer_v); diff --git a/src/kernel/pair.cpp b/src/kernel/pair.cpp index bd4604808..3d8ca0305 100644 --- a/src/kernel/pair.cpp +++ b/src/kernel/pair.cpp @@ -22,6 +22,10 @@ inline namespace kernel { let unit { nullptr }; + pair::pair(object const& a) + : std::pair { a, unit } + {} + pair::pair(object const& a, object const& b) : std::pair { a, b } {} From c996534da4ab5b1e114034812105b36d6bd4fab3 Mon Sep 17 00:00:00 2001 From: yamacir-kit Date: Fri, 16 Feb 2024 02:48:05 +0900 Subject: [PATCH 10/12] Cleanup struct template `integer_set` Signed-off-by: yamacir-kit --- README.md | 6 +- VERSION | 2 +- include/meevax/memory/integer_set.hpp | 164 +++++++++++--------------- 3 files changed, 73 insertions(+), 99 deletions(-) diff --git a/README.md b/README.md index 775f6851e..8ada62fa9 100644 --- a/README.md +++ b/README.md @@ -91,7 +91,7 @@ Procedures for each standard are provided by the following R7RS-style libraries: cmake -B build -DCMAKE_BUILD_TYPE=Release cd build make package -sudo apt install build/meevax_0.5.116_amd64.deb +sudo apt install build/meevax_0.5.117_amd64.deb ``` or @@ -123,9 +123,9 @@ sudo rm -rf /usr/local/share/meevax | Target Name | Description |-------------|------------- -| `all` | Build shared-library `libmeevax.0.5.116.so` and executable `meevax` +| `all` | Build shared-library `libmeevax.0.5.117.so` and executable `meevax` | `test` | Test executable `meevax` -| `package` | Generate debian package `meevax_0.5.116_amd64.deb` +| `package` | Generate debian package `meevax_0.5.117_amd64.deb` | `install` | Copy files into `/usr/local` directly ## Usage diff --git a/VERSION b/VERSION index 34076ef25..b24ff4ab9 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -0.5.116 +0.5.117 diff --git a/include/meevax/memory/integer_set.hpp b/include/meevax/memory/integer_set.hpp index a380d1909..c175f4dfc 100644 --- a/include/meevax/memory/integer_set.hpp +++ b/include/meevax/memory/integer_set.hpp @@ -19,58 +19,33 @@ #include #include +#include #include #include #include +#include #include -#include namespace meevax { inline namespace memory { - template - constexpr auto compressible_bitwidth_of = log2(alignof(std::remove_pointer_t)) - 1; + template + constexpr auto compressible_bitwidth_of = std::is_pointer_v ? log2(alignof(std::remove_pointer_t)) - 1 : 0; template struct integer_set { static_assert(sizeof(T) <= sizeof(std::uintptr_t)); - static_assert(not std::is_pointer_v or compressible_bitwidth_of < E); + static_assert(compressible_bitwidth_of < E); - static constexpr auto N = static_cast(1) << E - (std::is_pointer_v ? compressible_bitwidth_of : 0); - - static constexpr auto compress(T value) - { - if constexpr (std::is_pointer_v) - { - return reinterpret_cast(value) >> compressible_bitwidth_of; - } - else - { - return reinterpret_cast(value); - } - } - - static constexpr auto decompress(std::uintptr_t value) - { - if constexpr (std::is_pointer_v) - { - return reinterpret_cast(value << compressible_bitwidth_of); - } - else - { - return reinterpret_cast(value); - } - } + static constexpr auto N = static_cast(1) << (E - compressible_bitwidth_of); using subset = integer_set; // Only the outermost implementation knows the original type name T. - using subsets = subset *[N]; - - subsets data = {}; + subset * data[N] = {}; struct const_iterator : public std::iterator { @@ -82,7 +57,7 @@ inline namespace memory constexpr const_iterator() = default; - explicit const_iterator(integer_set const* container, std::size_t i, std::uintptr_t j = 0) + explicit const_iterator(integer_set const* container, std::size_t i, std::uintptr_t j = 0) noexcept : data { container->data } , i { i } { @@ -90,7 +65,7 @@ inline namespace memory increment_unless_truthy(j); } - explicit const_iterator(integer_set const* container) + explicit const_iterator(integer_set const* container) noexcept : data { container->data } , i { N } { @@ -98,7 +73,7 @@ inline namespace memory assert(iter.data); } - auto increment_unless_truthy(std::uintptr_t j = 0) -> void + auto increment_unless_truthy(std::uintptr_t j = 0) noexcept -> void { assert(data); @@ -113,7 +88,7 @@ inline namespace memory iter = {}; } - auto decrement_unless_truthy() -> void + auto decrement_unless_truthy() noexcept -> void { assert(data); @@ -128,7 +103,7 @@ inline namespace memory iter = {}; } - auto operator ++() -> auto & + auto operator ++() noexcept -> auto & { if (++iter; not iter.good()) { @@ -139,7 +114,7 @@ inline namespace memory return *this; } - auto operator --() -> auto & + auto operator --() noexcept -> auto & { if (not iter.data) { @@ -154,10 +129,10 @@ inline namespace memory return *this; } - auto operator *() const -> T + auto operator *() const noexcept -> T { assert(good()); - return decompress(i << (Es + ...) bitor *iter); + return reinterpret_cast((i << (Es + ...) bitor *iter) << compressible_bitwidth_of); } auto good() const noexcept -> bool @@ -166,34 +141,50 @@ inline namespace memory return i < N; } - auto at_end() const -> bool + auto at_end() const noexcept -> bool { return not data or not good() or iter.at_end(); } - auto is_same_index(const_iterator const& other) const -> bool + auto is_same_index(const_iterator const& other) const noexcept -> bool { return i == other.i and iter.is_same_index(other.iter); } - friend auto operator ==(const_iterator const& a, const_iterator const& b) + friend auto operator ==(const_iterator const& a, const_iterator const& b) noexcept { return a.is_same_index(b) or (a.at_end() and b.at_end()); } - friend auto operator !=(const_iterator const& a, const_iterator const& b) + friend auto operator !=(const_iterator const& a, const_iterator const& b) noexcept { return not (a == b); } }; - static constexpr auto split(T p) + static constexpr auto split(T p) noexcept { - auto datum = compress(p); + static_assert(E + (Es + ...) <= sizeof(T) * CHAR_BIT); - constexpr std::uintptr_t mask = (N - 1) << (Es + ...); + struct big_endian + { + std::uintptr_t ignore : sizeof(std::uintptr_t) * CHAR_BIT - E - (Es + ...); + std::uintptr_t key : E - compressible_bitwidth_of; + std::uintptr_t value : (Es + ...); + std::uintptr_t : compressible_bitwidth_of; + }; - return std::make_pair((datum & mask) >> (Es + ...), datum & ~mask); + struct little_endian + { + std::uintptr_t : compressible_bitwidth_of; + std::uintptr_t value : (Es + ...); + std::uintptr_t key : E - compressible_bitwidth_of; + std::uintptr_t ignore : sizeof(std::uintptr_t) * CHAR_BIT - E - (Es + ...); + }; + + const auto bits = bit_cast(p); + + return std::make_pair(bits.key, bits.value); } ~integer_set() @@ -217,29 +208,29 @@ inline namespace memory } } - auto erase(T value) + auto erase(T value) noexcept { auto [i, j] = split(value); data[i]->erase(j); } - auto begin() const + auto begin() const noexcept { return const_iterator(this, 0); } - auto end() const + auto end() const noexcept { return const_iterator(this, N); } - auto lower_bound(T value) const + auto lower_bound(T value) const noexcept { auto [i, j] = split(value); return const_iterator(this, i, j); } - auto size() const -> std::size_t + auto size() const noexcept -> std::size_t { return std::distance(begin(), end()); } @@ -250,64 +241,62 @@ inline namespace memory { static constexpr auto N = static_cast(1) << E; - using subset = simple_bitset; - - subset data {}; + bool data[N] {}; struct const_iterator : public std::iterator { - subset const* data = nullptr; + bool const* data = nullptr; std::size_t i = std::numeric_limits::max(); - auto increment_unless_truthy() + auto increment_unless_truthy() noexcept { - for (assert(data); good() and not (*data)[i]; ++i) + for (assert(data); good() and not data[i]; ++i) {} - assert(not good() or (*data)[i]); + assert(not good() or data[i]); } - auto decrement_unless_truthy() + auto decrement_unless_truthy() noexcept { - for (assert(data); good() and not (*data)[i]; --i) + for (assert(data); good() and not data[i]; --i) {} - assert(not good() or (*data)[i]); + assert(not good() or data[i]); } constexpr const_iterator() = default; - explicit const_iterator(integer_set const* container, std::size_t i) - : data { std::addressof(container->data) } + explicit const_iterator(integer_set const* container, std::size_t i) noexcept + : data { container->data } , i { i } { increment_unless_truthy(); - assert(not good() or (*data)[this->i]); + assert(not good() or data[this->i]); } - explicit const_iterator(integer_set const* container) - : data { std::addressof(container->data) } + explicit const_iterator(integer_set const* container) noexcept + : data { container->data } , i { N - 1 } { decrement_unless_truthy(); } - auto operator ++() -> decltype(auto) + auto operator ++() noexcept -> decltype(auto) { ++i; increment_unless_truthy(); return *this; } - auto operator --() -> decltype(auto) + auto operator --() noexcept -> decltype(auto) { --i; decrement_unless_truthy(); return *this; } - auto operator *() const + auto operator *() const noexcept { assert(good()); return reinterpret_cast(i); @@ -319,56 +308,41 @@ inline namespace memory return i < N; } - auto at_end() const -> bool + auto at_end() const noexcept -> bool { return not data or not good(); } - auto is_same_index(const_iterator const& other) const -> bool + auto is_same_index(const_iterator const& other) const noexcept -> bool { return i == other.i; } - friend auto operator ==(const_iterator const& a, const_iterator const& b) + friend auto operator ==(const_iterator const& a, const_iterator const& b) noexcept { return a.is_same_index(b) or (a.at_end() and b.at_end()); } - friend auto operator !=(const_iterator const& a, const_iterator const& b) + friend auto operator !=(const_iterator const& a, const_iterator const& b) noexcept { return not (a == b); } }; - auto insert(T value) + auto insert(T value) noexcept { - data.set(reinterpret_cast(value)); + data[reinterpret_cast(value)] = true; } - auto erase(T value) + auto erase(T value) noexcept { - data.reset(reinterpret_cast(value)); + data[reinterpret_cast(value)] = false; } - auto begin() const - { - return const_iterator(data, 0); - } - - auto end() const - { - return const_iterator(data, N); - } - - auto lower_bound(T value) const + auto lower_bound(T value) const noexcept { return const_iterator(this, reinterpret_cast(value)); } - - auto size() const - { - return std::distance(begin(), end()); - } }; } // namespace memory } // namespace meevax From 80cca00a74062f37ea45ceab7059df6efb9003f5 Mon Sep 17 00:00:00 2001 From: yamacir-kit Date: Fri, 16 Feb 2024 03:53:14 +0900 Subject: [PATCH 11/12] Lipsticks Signed-off-by: yamacir-kit --- README.md | 6 +++--- VERSION | 2 +- include/meevax/memory/heterogeneous_pointer.hpp | 4 +++- src/kernel/exact_integer.cpp | 2 +- src/kernel/number.cpp | 4 ++-- 5 files changed, 10 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index 8ada62fa9..f632461dd 100644 --- a/README.md +++ b/README.md @@ -91,7 +91,7 @@ Procedures for each standard are provided by the following R7RS-style libraries: cmake -B build -DCMAKE_BUILD_TYPE=Release cd build make package -sudo apt install build/meevax_0.5.117_amd64.deb +sudo apt install build/meevax_0.5.118_amd64.deb ``` or @@ -123,9 +123,9 @@ sudo rm -rf /usr/local/share/meevax | Target Name | Description |-------------|------------- -| `all` | Build shared-library `libmeevax.0.5.117.so` and executable `meevax` +| `all` | Build shared-library `libmeevax.0.5.118.so` and executable `meevax` | `test` | Test executable `meevax` -| `package` | Generate debian package `meevax_0.5.117_amd64.deb` +| `package` | Generate debian package `meevax_0.5.118_amd64.deb` | `install` | Copy files into `/usr/local` directly ## Usage diff --git a/VERSION b/VERSION index b24ff4ab9..8a3133c5c 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -0.5.117 +0.5.118 diff --git a/include/meevax/memory/heterogeneous_pointer.hpp b/include/meevax/memory/heterogeneous_pointer.hpp index 4f6d1bc87..6a7443487 100644 --- a/include/meevax/memory/heterogeneous_pointer.hpp +++ b/include/meevax/memory/heterogeneous_pointer.hpp @@ -43,7 +43,9 @@ inline namespace memory { template explicit constexpr binder(Us&&... xs) - : std::conditional_t, Top, Bound> { std::forward(xs)... } + : std::conditional_t and std::is_constructible_v, Top, Bound> { + std::forward(xs)... + } {} ~binder() override = default; diff --git a/src/kernel/exact_integer.cpp b/src/kernel/exact_integer.cpp index 826af9c93..85ab62834 100644 --- a/src/kernel/exact_integer.cpp +++ b/src/kernel/exact_integer.cpp @@ -103,7 +103,7 @@ inline namespace kernel if (mpz_init_set_str(value, (s.at(0) == '+' ? s.substr(1) : s).c_str(), radix)) { mpz_clear(value); - throw std::invalid_argument("not a integer"); + throw std::invalid_argument("not an exact-integer"); } } diff --git a/src/kernel/number.cpp b/src/kernel/number.cpp index 9e01b36d0..c723d3e93 100644 --- a/src/kernel/number.cpp +++ b/src/kernel/number.cpp @@ -424,7 +424,7 @@ inline namespace kernel } catch (std::invalid_argument const&) { - return make(ratio(literal, radix)); + return make(literal, radix); } } @@ -487,7 +487,7 @@ inline namespace kernel } catch (std::invalid_argument const&) { - return make(complex(literal, radix)); + return make(literal, radix); } } From e6dbc6463ac8ad9f963725ead69005c4a0b74e8b Mon Sep 17 00:00:00 2001 From: yamacir-kit Date: Mon, 19 Feb 2024 04:05:38 +0900 Subject: [PATCH 12/12] Update `(increment|decrement)_unless_truthy` to be faster Signed-off-by: yamacir-kit --- README.md | 8 +-- VERSION | 2 +- configure/README.md | 2 +- include/meevax/memory/integer_set.hpp | 74 +++++++++++++++++++-------- 4 files changed, 58 insertions(+), 28 deletions(-) diff --git a/README.md b/README.md index f632461dd..6a483660c 100644 --- a/README.md +++ b/README.md @@ -25,7 +25,7 @@ Latest release is [here](https://github.com/yamacir-kit/meevax/releases). - Low-level hygienic macro system, known as *syntactic closures* [[Bawden and Rees 1988](#Bawden-and-Rees-1988); [Hanson 1991](#Hanson-1991)] and *explicit renaming* [[Clinger 1991](#Clinger-1991)]. For these, the well-known macro - transformers `sc-macro-transformer`, `rsc-macro-transformer`, and + transformers `sc-macro-transformer`, `rsc-macro-transformer` and `er-macro-transformer` from the library [`(meevax macro-transformer)`](./basis/meevax.ss) are provided. Note that these are non-Scheme standards. @@ -91,7 +91,7 @@ Procedures for each standard are provided by the following R7RS-style libraries: cmake -B build -DCMAKE_BUILD_TYPE=Release cd build make package -sudo apt install build/meevax_0.5.118_amd64.deb +sudo apt install build/meevax_0.5.119_amd64.deb ``` or @@ -123,9 +123,9 @@ sudo rm -rf /usr/local/share/meevax | Target Name | Description |-------------|------------- -| `all` | Build shared-library `libmeevax.0.5.118.so` and executable `meevax` +| `all` | Build shared-library `libmeevax.0.5.119.so` and executable `meevax` | `test` | Test executable `meevax` -| `package` | Generate debian package `meevax_0.5.118_amd64.deb` +| `package` | Generate debian package `meevax_0.5.119_amd64.deb` | `install` | Copy files into `/usr/local` directly ## Usage diff --git a/VERSION b/VERSION index 8a3133c5c..e8b2b30cf 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -0.5.118 +0.5.119 diff --git a/configure/README.md b/configure/README.md index fae35493a..41ccda9b2 100644 --- a/configure/README.md +++ b/configure/README.md @@ -25,7 +25,7 @@ Latest release is [here](https://github.com/yamacir-kit/meevax/releases). - Low-level hygienic macro system, known as *syntactic closures* [[Bawden and Rees 1988](#Bawden-and-Rees-1988); [Hanson 1991](#Hanson-1991)] and *explicit renaming* [[Clinger 1991](#Clinger-1991)]. For these, the well-known macro - transformers `sc-macro-transformer`, `rsc-macro-transformer`, and + transformers `sc-macro-transformer`, `rsc-macro-transformer` and `er-macro-transformer` from the library [`(meevax macro-transformer)`](./basis/meevax.ss) are provided. Note that these are non-Scheme standards. diff --git a/include/meevax/memory/integer_set.hpp b/include/meevax/memory/integer_set.hpp index c175f4dfc..1394c74f5 100644 --- a/include/meevax/memory/integer_set.hpp +++ b/include/meevax/memory/integer_set.hpp @@ -20,6 +20,7 @@ #include #include #include +#include #include #include #include @@ -239,59 +240,84 @@ inline namespace memory template struct integer_set { - static constexpr auto N = static_cast(1) << E; + static_assert(std::is_same_v); - bool data[N] {}; + static constexpr auto N = 1ul << E; + + std::uint64_t data[N / 64] {}; struct const_iterator : public std::iterator { - bool const* data = nullptr; + std::uint64_t const* data = nullptr; - std::size_t i = std::numeric_limits::max(); + std::size_t index = std::numeric_limits::max(); auto increment_unless_truthy() noexcept { - for (assert(data); good() and not data[i]; ++i) - {} + auto i = index / 64; + auto j = index % 64; + + for (; i < N / 64; ++i, j = 0) + { + if (auto datum = data[i] & (~0ul << j); datum) + { + index = i * 64 + __builtin_ctzl(datum); + assert(data[index / 64] & (1ul << index % 64)); + return; + } + } - assert(not good() or data[i]); + index = N; + + assert(not good()); } auto decrement_unless_truthy() noexcept { - for (assert(data); good() and not data[i]; --i) - {} + auto i = index / 64; + auto j = index % 64; + + for (; i < N / 64; --i, j = 63) + { + if (auto datum = data[i] & (~0ul >> (63 - j)); datum) + { + index = i * 64 + (63 - __builtin_clzl(datum)); + assert(data[index / 64] & (1ul << index % 64)); + return; + } + } - assert(not good() or data[i]); + index = N; + + assert(not good()); } constexpr const_iterator() = default; explicit const_iterator(integer_set const* container, std::size_t i) noexcept - : data { container->data } - , i { i } + : data { container->data } + , index { i } { increment_unless_truthy(); - assert(not good() or data[this->i]); } explicit const_iterator(integer_set const* container) noexcept - : data { container->data } - , i { N - 1 } + : data { container->data } + , index { N - 1 } { decrement_unless_truthy(); } auto operator ++() noexcept -> decltype(auto) { - ++i; + ++index; increment_unless_truthy(); return *this; } auto operator --() noexcept -> decltype(auto) { - --i; + --index; decrement_unless_truthy(); return *this; } @@ -299,13 +325,13 @@ inline namespace memory auto operator *() const noexcept { assert(good()); - return reinterpret_cast(i); + return reinterpret_cast(index); } auto good() const noexcept -> bool { assert(data); - return i < N; + return index < N; } auto at_end() const noexcept -> bool @@ -315,7 +341,7 @@ inline namespace memory auto is_same_index(const_iterator const& other) const noexcept -> bool { - return i == other.i; + return index == other.index; } friend auto operator ==(const_iterator const& a, const_iterator const& b) noexcept @@ -331,12 +357,16 @@ inline namespace memory auto insert(T value) noexcept { - data[reinterpret_cast(value)] = true; + auto i = reinterpret_cast(value) / 64; + auto j = reinterpret_cast(value) % 64; + data[i] |= (1ul << j); } auto erase(T value) noexcept { - data[reinterpret_cast(value)] = false; + auto i = reinterpret_cast(value) / 64; + auto j = reinterpret_cast(value) % 64; + data[i] &= ~(1ul << j); } auto lower_bound(T value) const noexcept