From 1efddc16d5c4fb22bd12837e61fa36446a9b7e28 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Steffan=20S=C3=B8lvsten?= Date: Fri, 3 Jun 2022 16:22:51 +0200 Subject: [PATCH 01/20] Fix Windows compilation cannot resolve std::max template --- tpie/pipelining/merge_sorter.cpp | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/tpie/pipelining/merge_sorter.cpp b/tpie/pipelining/merge_sorter.cpp index 89245a529..50f24b140 100644 --- a/tpie/pipelining/merge_sorter.cpp +++ b/tpie/pipelining/merge_sorter.cpp @@ -317,12 +317,14 @@ void merge_sorter_base::calculate_parameters() { // Phase 1 (run formation): // Run length: determined by the number of items we can hold in memory. // Fanout: unbounded - - memory_size_type streamMemory = m_element_file_stream_memory_usage; - memory_size_type tempFileMemory = 2*p.fanout*sizeof(temp_file); + + const memory_size_type streamMemory = m_element_file_stream_memory_usage; + const memory_size_type tempFileMemory = 2*p.fanout*sizeof(temp_file); log_pipe_debug() << "Phase 1: " << p.memoryPhase1 << " b available memory; " << streamMemory << " b for a single stream; " << tempFileMemory << " b for temp_files\n"; - memory_size_type min_m1 = std::max(128*1024UL, 16*m_item_size) + bits::run_positions::memory_usage() + streamMemory + tempFileMemory; + const memory_size_type minRunLength = std::max(128*1024UL, 16*m_item_size); + const memory_size_type min_m1 = minRunLength + bits::run_positions::memory_usage() + streamMemory + tempFileMemory; + if (p.memoryPhase1 < min_m1) { log_warning() << "Not enough phase 1 memory for 128 KB items and an open stream! (" << p.memoryPhase1 << " < " << min_m1 << ")\n"; p.memoryPhase1 = min_m1; From 3ec4dff9fd16c2161fbe6402f6c5c81715ced864 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Steffan=20S=C3=B8lvsten?= Date: Fri, 3 Jun 2022 18:14:00 +0200 Subject: [PATCH 02/20] Remove deprecated use of 'std::random_shuffle' This was removed with C++ 17 --- test/speed_regression/btree.cpp | 10 ++++-- test/unit/test_btree.cpp | 48 +++++++++++++++++++------ test/unit/test_freespace_collection.cpp | 44 ++++++++++++++++++----- 3 files changed, 82 insertions(+), 20 deletions(-) diff --git a/test/speed_regression/btree.cpp b/test/speed_regression/btree.cpp index 5c1f3a86f..8575786c4 100644 --- a/test/speed_regression/btree.cpp +++ b/test/speed_regression/btree.cpp @@ -19,7 +19,10 @@ #include "../app_config.h" #include "blocksize_2MB.h" + #include +#include + #include #include #include @@ -51,6 +54,9 @@ void test(size_t times, size_t size) { test_realtime_t start; test_realtime_t end; + std::random_device rd; + std::mt19937 gen(rd()); + for (size_t i = 0; i < times; ++i) { /*btree_internal_store store; btree > tree(store);*/ @@ -62,7 +68,7 @@ void test(size_t times, size_t size) { std::vector x(count); for(size_t i = 0; i < count; ++i) x[i] = i; - std::random_shuffle(x.begin(), x.end()); + std::shuffle(x.begin(), x.end(), gen); // insertion getTestRealtime(start); @@ -81,7 +87,7 @@ void test(size_t times, size_t size) { s(testRealtimeDiff(start,end)); // deletion - std::random_shuffle(x.begin(), x.end()); + std::shuffle(x.begin(), x.end(), gen); getTestRealtime(start); for(size_t i = 0; i < count; ++i) { diff --git a/test/unit/test_btree.cpp b/test/unit/test_btree.cpp index 50ce64731..f739b7374 100644 --- a/test/unit/test_btree.cpp +++ b/test/unit/test_btree.cpp @@ -22,6 +22,7 @@ #include #include #include +#include #include #include #include @@ -94,7 +95,11 @@ bool basic_test(TA, A && ... a) { std::vector x(12); //34); std::iota(x.begin(), x.end(), 0); - std::random_shuffle(x.begin(), x.end()); + + std::random_device rd; + std::mt19937 gen(rd()); + + std::shuffle(x.begin(), x.end(), gen); for (size_t v: x) { tree.insert(v); @@ -103,7 +108,7 @@ bool basic_test(TA, A && ... a) { TEST_ENSURE_EQUALITY(tree2.size(), tree.size(), "The tree has the wrong size during insert stage."); } - std::random_shuffle(x.begin(), x.end()); + std::shuffle(x.begin(), x.end(), gen); for (size_t v: x) { tree.erase(v); tree2.erase(v); @@ -156,7 +161,10 @@ bool dynamic_iterator_test(TA ta, A && ... a) { for (int i=0; i < 1234; ++i) { x.push_back(i); } - std::random_shuffle(x.begin(), x.end()); + + std::random_device rd; + std::mt19937 gen(rd()); + std::shuffle(x.begin(), x.end(), gen); for (size_t i=0; i < x.size(); ++i) { tree.insert(x[i]); @@ -219,16 +227,22 @@ bool key_and_comparator_test(TA, A && ... a) { TT...> tree(std::forward(a)..., comp); std::map, int, comparator > > tree2(comp); + std::random_device rd; + std::mt19937 gen(rd()); + std::vector x; for (int i=0; i < 1234; ++i) { item it; it.key.value = i; x.push_back(it); } - std::random_shuffle(x.begin(), x.end()); + + std::shuffle(x.begin(), x.end(), gen); + for (size_t i=0; i < x.size(); ++i) x[i].value = i; - std::random_shuffle(x.begin(), x.end()); + + std::shuffle(x.begin(), x.end(), gen); for (size_t i=0; i < x.size(); ++i) { tree.insert(x[i]); @@ -245,10 +259,12 @@ bool key_and_comparator_test(TA, A && ... a) { ++i2; } - std::random_shuffle(x.begin(), x.end()); + std::shuffle(x.begin(), x.end(), gen); + for (size_t i=0; i < x.size(); ++i) { tree.erase(x[i].key); } + return tree.empty(); } @@ -361,9 +377,15 @@ bool augment_test(TA ta, A && ... a) { default_comp c; ss_augmenter au; auto tree = get_btree(ta, c, au, std::forward(a)...); + + std::random_device rd; + std::mt19937 gen(rd()); + std::vector x; for (int i=0; i < 1234; ++i) x.push_back(i); - std::random_shuffle(x.begin(), x.end()); + + std::shuffle(x.begin(), x.end(), gen); + for (size_t i=0; i < x.size(); ++i) { tree.insert(x[i]); auto n=tree.root(); @@ -379,7 +401,9 @@ bool augment_test(TA ta, A && ... a) { } size_t e=x.size()/2; - std::random_shuffle(x.begin(), x.end()); + + std::shuffle(x.begin(), x.end(), gen); + for (size_t i=e; i < x.size(); ++i) tree.erase(x[i]); x.resize(e); @@ -444,11 +468,15 @@ bool bound_test(TA, A && ... a) { btree tree(std::forward(a)...); set tree2; + std::random_device rd; + std::mt19937 gen(rd()); + std::vector x; for (int i=0; i < 1234; ++i) { x.push_back(i); } - std::random_shuffle(x.begin(), x.end()); + + std::shuffle(x.begin(), x.end(), gen); for (size_t i=0; i < x.size(); ++i) { tree.insert(x[i]); @@ -464,7 +492,7 @@ bool bound_test(TA, A && ... a) { TEST_ENSURE(tree.upper_bound(r2) == tree.end() || *tree.upper_bound(r2) == *tree2.upper_bound(r2), "Upper bound compare failed during insert stage."); } - std::random_shuffle(x.begin(), x.end()); + std::shuffle(x.begin(), x.end(), gen); for (size_t i=0; i < x.size(); ++i) { tree.erase(x[i]); diff --git a/test/unit/test_freespace_collection.cpp b/test/unit/test_freespace_collection.cpp index a9430a7ad..cd7634ce8 100644 --- a/test/unit/test_freespace_collection.cpp +++ b/test/unit/test_freespace_collection.cpp @@ -44,13 +44,38 @@ memory_size_type random(memory_size_type seed, memory_size_type min, memory_size return (seed * 1009) % (max - min) + min; } -int random_generator(int i) { - return 10007 % i; -} +class unrandom_generator +{ +public: + typedef unsigned int result_type; + + unrandom_generator() = default; + unrandom_generator(size_t /*n*/) { } + +private: + result_type mod = 0; + static constexpr result_type val = 10007; + +public: + constexpr static result_type min() + { return 0u; } + + constexpr static result_type max() + { return val; } + + result_type g() + { + if (++mod == val) { mod = 1; } + return val % mod; + } + + result_type operator()() + { return g(); } +}; bool alloc_test(memory_size_type size, memory_size_type block_size) { typedef std::vector handles_t; - temp_file file; + temp_file file; freespace_collection collection(file.path(), block_size); handles_t handles; @@ -87,7 +112,7 @@ bool size_test(memory_size_type size, memory_size_type block_size) { for(memory_size_type i = 0; i < size; ++i) { TEST_ENSURE(collection.size() >= minimum_size, "The space used is too small."); - + minimum_size += block_size; block_handle handle = collection.alloc(); @@ -96,8 +121,11 @@ bool size_test(memory_size_type size, memory_size_type block_size) { } // the two arrays are shuffled the same way - std::random_shuffle(handles.begin(), handles.end(), random_generator); - std::random_shuffle(sizes.begin(), sizes.end(), random_generator); + unrandom_generator g1; + std::shuffle(handles.begin(), handles.end(), g1); + + unrandom_generator g2; + std::shuffle(sizes.begin(), sizes.end(), g2); for(memory_size_type i = 0; i < size; ++i) { TEST_ENSURE(collection.size() >= minimum_size, "The space used is too small."); @@ -112,4 +140,4 @@ int main(int argc, char **argv) { return tpie::tests(argc, argv) .test(alloc_test, "alloc", "size", 1000, "block_size", 1024) .test(size_test, "size", "size", 1000, "block_size", 1024); -} \ No newline at end of file +} From a185e8a6b172f5b644eabf08cdcf38a2e583d978 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Steffan=20S=C3=B8lvsten?= Date: Fri, 3 Jun 2022 18:24:25 +0200 Subject: [PATCH 03/20] Remove use of deprecated 'std::binary_function' --- test/unit/common.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/unit/common.h b/test/unit/common.h index f4003126b..00aeb2365 100644 --- a/test/unit/common.h +++ b/test/unit/common.h @@ -38,7 +38,7 @@ struct bit_permute { }; template > -struct bit_pertume_compare: std::binary_function { +struct bit_pertume_compare { bit_permute bp; T c; typedef uint64_t first_argument_type; From 43717872eb82d427ad9e6c67bbf8483ab54e3300 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Steffan=20S=C3=B8lvsten?= Date: Fri, 3 Jun 2022 18:43:45 +0200 Subject: [PATCH 04/20] Add missing import of Boost.System Or should this just be replaced with std::system_error? It's hard to tell, whether something further below still is from Boost and hence will throw such an exception --- test/unit/test_close_file.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/test/unit/test_close_file.cpp b/test/unit/test_close_file.cpp index cd446e4d3..95870c192 100644 --- a/test/unit/test_close_file.cpp +++ b/test/unit/test_close_file.cpp @@ -29,6 +29,7 @@ #include #include #include +#include #ifdef WIN32 class open_file_monitor { From 77a19768df3958eaa014fedd2476f6b6457ab109 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Steffan=20S=C3=B8lvsten?= Date: Fri, 3 Jun 2022 18:45:15 +0200 Subject: [PATCH 05/20] Add catch of std::system_error --- test/unit/test_close_file.cpp | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/test/unit/test_close_file.cpp b/test/unit/test_close_file.cpp index 95870c192..b0312b6c1 100644 --- a/test/unit/test_close_file.cpp +++ b/test/unit/test_close_file.cpp @@ -29,7 +29,9 @@ #include #include #include + #include +#include #ifdef WIN32 class open_file_monitor { @@ -45,8 +47,12 @@ class open_file_monitor { tpie::log_debug() << "Caught filesystem_error: " << e.what() << std::endl; // Already open? return false; + } catch (const std::system_error & e) { + tpie::log_debug() << "Caught (std) system_error: " << e.what() << std::endl; + // Already open? + return false; } catch (const boost::system::system_error & e) { - tpie::log_debug() << "Caught system_error: " << e.what() << std::endl; + tpie::log_debug() << "Caught (Boost) system_error: " << e.what() << std::endl; // Already open? return false; } From 0cb7ec4e19a26c7bdcf8fdf0387630797dbe0c5f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Steffan=20S=C3=B8lvsten?= Date: Sat, 4 Jun 2022 23:20:55 +0200 Subject: [PATCH 06/20] Change Windows CI Boost installation to MarkusJx/install-boost The use of Chocolatey is surprisingly inconsistent --- .github/workflows/build_windows.yml | 28 ++++++++++++++++++++-------- 1 file changed, 20 insertions(+), 8 deletions(-) diff --git a/.github/workflows/build_windows.yml b/.github/workflows/build_windows.yml index 9c1836720..ec43b1f03 100644 --- a/.github/workflows/build_windows.yml +++ b/.github/workflows/build_windows.yml @@ -46,18 +46,30 @@ jobs: with: arch: x64 - - name: Install dependencies - run: | - echo "================================" - echo "Boost" - choco install boost-msvc-14.2 + - name: Install Boost + uses: MarkusJx/install-boost@v2.3.0 + id: install-boost + with: + # List of all versions here: + # https://github.com/MarkusJx/prebuilt-boost/blob/main/versions-manifest.json + boost_version: 1.79.0 + platform_version: 2019 + toolset: msvc - - name: CMake + MSBuild + # Build + - name: Configure CMake + NMake all working-directory: ${{runner.workspace}} run: | cmake -E make_directory ${{github.workspace}}\build cd ${{github.workspace}}\build SET CXXFLAGS="%CXXFLAGS% -D_HAS_AUTO_PTR_ETC=1" - cmake -D CMAKE_BUILD_TYPE="${{matrix.build_type}}" -D CMAKE_CXX_STANDARD=17 .. + cmake -G "NMake Makefiles" -D CMAKE_BUILD_TYPE="${{matrix.build_type}}" -D CMAKE_CXX_STANDARD=17 -D Boost_INCLUDE_DIR=${{steps.install-boost.outputs.BOOST_ROOT}}/include -D Boost_LIBRARY_DIRS=${{steps.install-boost.outputs.BOOST_ROOT}}/lib .. + nmake + env: + BOOST_ROOT: ${{ steps.install-boost.outputs.BOOST_ROOT }} - msbuild ALL_BUILD.vcxproj + # Run unit tests + - name: NMake test + run: | + cd ${{github.workspace}}\build + nmake test From 1c69aefd77e89b40cac3f6f7e27f32e719aeaaa0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Steffan=20S=C3=B8lvsten?= Date: Sat, 4 Jun 2022 23:40:14 +0200 Subject: [PATCH 07/20] Fix incorrect call for running CTest on Windows --- .github/workflows/build_windows.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build_windows.yml b/.github/workflows/build_windows.yml index ec43b1f03..d0dc521d7 100644 --- a/.github/workflows/build_windows.yml +++ b/.github/workflows/build_windows.yml @@ -72,4 +72,4 @@ jobs: - name: NMake test run: | cd ${{github.workspace}}\build - nmake test + ctest From 4547b57009e21314b02ab8df7085cdb9a095ac6e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Steffan=20S=C3=B8lvsten?= Date: Sat, 4 Jun 2022 23:42:04 +0200 Subject: [PATCH 08/20] Fix README.md claims to support C++14 rather than C++17 --- README.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index ec8a31c96..e3c97dfcd 100644 --- a/README.md +++ b/README.md @@ -35,7 +35,7 @@ hosted [there](http://www.madalgo.au.dk/tpie/doc/) and on ## Dependencies TPIE has a mandatory dependency on the _Boost_ library and requires a C++ -compiler that supports the _14_ standard (e.g. GNU 7+ and Clang 10+). +compiler that supports the _17_ standard (e.g. GNU 7+ and Clang 10+). Furthermore, optionally TPIE can use the _Snappy_, _LZ4_, and _ZSTD_ compression algorithms, if available. @@ -56,7 +56,7 @@ TPIE is then linked to each target executable of choice. ```cmake add_executable( ) target_link_libraries( tpie) -set_target_properties( PROPERTIES CXX_STANDARD 14) +set_target_properties( PROPERTIES CXX_STANDARD 17) ``` Then build your project with CMake. For other ways to install TPIE, see @@ -72,7 +72,7 @@ commands. # Compile entire TPIE project mkdir build cd build -cmake -D CXX_STANDARD 14 .. +cmake -D CXX_STANDARD 17 .. # Compile tests make @@ -93,7 +93,7 @@ CMake enabled examples in _apps_ execute the following commands # CMake mkdir build cd build -cmake -D CXX_STANDARD 14 .. +cmake -D CXX_STANDARD 17 .. # Compile cd apps// From 4453f605b3aba6136ef1178f98bd01c641891fa4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Steffan=20S=C3=B8lvsten?= Date: Sat, 4 Jun 2022 23:58:48 +0200 Subject: [PATCH 09/20] Split 'Build + Test' CI into different jobs per OS --- .../{unit_test.yml => test_linux.yml} | 103 +--------------- .github/workflows/test_mac.yml | 116 ++++++++++++++++++ .../{build_windows.yml => test_windows.yml} | 14 +-- README.md | 4 +- 4 files changed, 131 insertions(+), 106 deletions(-) rename .github/workflows/{unit_test.yml => test_linux.yml} (51%) create mode 100644 .github/workflows/test_mac.yml rename .github/workflows/{build_windows.yml => test_windows.yml} (88%) diff --git a/.github/workflows/unit_test.yml b/.github/workflows/test_linux.yml similarity index 51% rename from .github/workflows/unit_test.yml rename to .github/workflows/test_linux.yml index eb1fec240..a938e35db 100644 --- a/.github/workflows/unit_test.yml +++ b/.github/workflows/test_linux.yml @@ -1,4 +1,4 @@ -name: unit tests +name: test (Linux) on: push: @@ -10,7 +10,7 @@ on: jobs: skip_duplicate: - name: 'Check whether to skip job' + name: 'Skip job? (Linux)' continue-on-error: true runs-on: ubuntu-latest @@ -23,8 +23,8 @@ jobs: outputs: should_skip: ${{ steps.skip_check.outputs.should_skip }} - linux_test: - name: 'Unit test (Linux, ${{matrix.cc.cc}}-${{matrix.cc.v}}, ${{matrix.build_type}})' + build_test: + name: 'Build + Test (Linux, ${{matrix.cc.cc}}-${{matrix.cc.v}}, ${{matrix.build_type}})' runs-on: ${{ matrix.os }} needs: skip_duplicate @@ -34,7 +34,7 @@ jobs: fail-fast: false matrix: os: [ubuntu-latest] - build_type: [Release] #, Debug, ExtraDebug] + build_type: [Release, Debug] cc: # GNU Compiler - { cc: gcc, v: 7, cxx: g++ } # oldest possible @@ -116,96 +116,3 @@ jobs: sudo apt install python3 python3-pip pip install cmakeast python3 scripts/check_missing_ctests.py - - - macos_test: - name: 'Unit test (Mac OS, ${{matrix.cc.cc}}@${{matrix.cc.v || matrix.cc.xcode}}, ${{matrix.build_type}})' - runs-on: ${{ matrix.os }} - - needs: skip_duplicate - if: ${{ needs.skip_duplicate.outputs.should_skip != 'true' }} - - strategy: - fail-fast: false - matrix: - os: [macos-latest] - build_type: [Release] #, Debug, ExtraDebug] - cc: - # GNU Compiler - - { cc: gcc, v: 7, cxx: g++, xcode: latest } - - { cc: gcc, v: 10, cxx: g++, xcode: latest } - - # Clang Compiler - - { cc: clang, cxx: clang++, xcode: 11.7 } # oldest - - { cc: clang, cxx: clang++, xcode: 12.4 } - - { cc: clang, cxx: clang++, xcode: 13.1 } - - { cc: clang, cxx: clang++, xcode: 13.2 } # newest - - steps: - # Git repo set up - - name: Checkout commit - uses: actions/checkout@v2 - - # Install dependencies - - name: Install xcode - uses: maxim-lobanov/setup-xcode@v1 - with: - xcode-version: ${{matrix.cc.xcode}} - - - name: Install dependencies - run: | - brew update - - if ["${{matrix.cc.cc}}" == "gcc"]; - then - echo "================================" - echo "Compiler" - brew install ${{matrix.cc.cc}}@${{matrix.cc.v}} - fi - - echo "================================" - echo "Boost" - brew install boost - - echo "================================" - echo "Snappy" - brew install snappy - - echo "================================" - echo "LZ4" - brew install lz4 - - echo "================================" - echo "ZSTD" - brew install zstd - - # CMake build and run - - name: CMake build - working-directory: ${{runner.workspace}} - run: | - if [ "${{ matrix.cc.cc }}" == "gcc" ] ; - then - export CC=/usr/bin/${{matrix.cc.cc}} - export CXX=/usr/bin/${{matrix.cc.cxx}} - else - export CC=${{matrix.cc.cc}} - export CXX=${{matrix.cc.cxx}} - fi - - cmake -E make_directory ${{github.workspace}}/build - cd ${{github.workspace}}/build - cmake -D CMAKE_BUILD_TYPE="${{matrix.build_type}}" -D CMAKE_CXX_STANDARD=14 .. - - make -j2 - - - name: CTest run - working-directory: ${{github.workspace}}/build - run: ctest --timeout 30 - - # Check if tests are missing - - name: Check missing CTests - working-directory: ${{github.workspace}} - run: | - brew install python3 - pip3 install cmakeast - python3 scripts/check_missing_ctests.py diff --git a/.github/workflows/test_mac.yml b/.github/workflows/test_mac.yml new file mode 100644 index 000000000..32c764e3b --- /dev/null +++ b/.github/workflows/test_mac.yml @@ -0,0 +1,116 @@ +name: test (Mac OS) + +on: + push: + branches: + - master + pull_request: + branches: + - master + +jobs: + skip_duplicate: + name: 'Skip job? (Mac OS)' + continue-on-error: true + runs-on: ubuntu-latest + + steps: + - id: skip_check + uses: fkirc/skip-duplicate-actions@master + with: + paths: '["tpie/", "test/"]' + + outputs: + should_skip: ${{ steps.skip_check.outputs.should_skip }} + + build_test: + name: 'Build + Test (Mac OS, ${{matrix.cc.cc}}@${{matrix.cc.v || matrix.cc.xcode}}, ${{matrix.build_type}})' + runs-on: ${{ matrix.os }} + + needs: skip_duplicate + if: ${{ needs.skip_duplicate.outputs.should_skip != 'true' }} + + strategy: + fail-fast: false + matrix: + os: [macos-latest] + build_type: [Release, Debug] + cc: + # GNU Compiler + - { cc: gcc, v: 7, cxx: g++, xcode: latest } + - { cc: gcc, v: 10, cxx: g++, xcode: latest } + + # Clang Compiler + - { cc: clang, cxx: clang++, xcode: 11.7 } # oldest + - { cc: clang, cxx: clang++, xcode: 12.4 } + - { cc: clang, cxx: clang++, xcode: 13.1 } + - { cc: clang, cxx: clang++, xcode: 13.2 } # newest + + steps: + # Git repo set up + - name: Checkout commit + uses: actions/checkout@v2 + + # Install dependencies + - name: Install xcode + uses: maxim-lobanov/setup-xcode@v1 + with: + xcode-version: ${{matrix.cc.xcode}} + + - name: Install dependencies + run: | + brew update + + if ["${{matrix.cc.cc}}" == "gcc"]; + then + echo "================================" + echo "Compiler" + brew install ${{matrix.cc.cc}}@${{matrix.cc.v}} + fi + + echo "================================" + echo "Boost" + brew install boost + + echo "================================" + echo "Snappy" + brew install snappy + + echo "================================" + echo "LZ4" + brew install lz4 + + echo "================================" + echo "ZSTD" + brew install zstd + + # CMake build and run + - name: CMake build + working-directory: ${{runner.workspace}} + run: | + if [ "${{ matrix.cc.cc }}" == "gcc" ] ; + then + export CC=/usr/bin/${{matrix.cc.cc}} + export CXX=/usr/bin/${{matrix.cc.cxx}} + else + export CC=${{matrix.cc.cc}} + export CXX=${{matrix.cc.cxx}} + fi + + cmake -E make_directory ${{github.workspace}}/build + cd ${{github.workspace}}/build + cmake -D CMAKE_BUILD_TYPE="${{matrix.build_type}}" -D CMAKE_CXX_STANDARD=14 .. + + make -j2 + + - name: CTest run + working-directory: ${{github.workspace}}/build + run: ctest --timeout 30 + + # Check if tests are missing + - name: Check missing CTests + working-directory: ${{github.workspace}} + run: | + brew install python3 + pip3 install cmakeast + python3 scripts/check_missing_ctests.py diff --git a/.github/workflows/build_windows.yml b/.github/workflows/test_windows.yml similarity index 88% rename from .github/workflows/build_windows.yml rename to .github/workflows/test_windows.yml index d0dc521d7..61973a829 100644 --- a/.github/workflows/build_windows.yml +++ b/.github/workflows/test_windows.yml @@ -1,4 +1,4 @@ -name: build (windows) +name: test (Windows) on: push: @@ -10,7 +10,7 @@ on: jobs: skip_duplicate: - name: 'Check whether to skip job' + name: 'Skip job? (Windows)' continue-on-error: true runs-on: ubuntu-latest @@ -18,13 +18,13 @@ jobs: - id: skip_check uses: fkirc/skip-duplicate-actions@master with: - paths: '["tpie/"]' + paths: '["tpie/", "test/"]' outputs: should_skip: ${{ steps.skip_check.outputs.should_skip }} - build: - name: 'Build (Windows, ${{matrix.build_type}})' + build_test: + name: 'Build + Test (Windows, ${{matrix.build_type}})' runs-on: windows-latest needs: skip_duplicate @@ -33,7 +33,7 @@ jobs: strategy: fail-fast: false matrix: - build_type: [Release, Debug, ExtraDebug] + build_type: [Release, Debug] steps: # Git repo set up @@ -69,7 +69,7 @@ jobs: BOOST_ROOT: ${{ steps.install-boost.outputs.BOOST_ROOT }} # Run unit tests - - name: NMake test + - name: CTest run run: | cd ${{github.workspace}}\build ctest diff --git a/README.md b/README.md index e3c97dfcd..f10e15be0 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,9 @@ # TPIE - The Templated Portable I/O Environment [![LGPL-3.0 License](https://img.shields.io/badge/license-LGPL%203.0-blue.svg)](COPYING.md) -[![unit tests](https://github.com/thomasmoelhave/tpie/actions/workflows/unit_test.yml/badge.svg)](https://github.com/thomasmoelhave/tpie/actions/workflows/unit_test.yml) +[![test (Linux)](https://github.com/thomasmoelhave/tpie/actions/workflows/test_linux.yml/badge.svg)](https://github.com/thomasmoelhave/tpie/actions/workflows/test_linux.yml) +[![test (Mac OS)](https://github.com/thomasmoelhave/tpie/actions/workflows/test_macos.yml/badge.svg)](https://github.com/thomasmoelhave/tpie/actions/workflows/test_macos.yml) +[![test (Windows)](https://github.com/thomasmoelhave/tpie/actions/workflows/test_windows.yml/badge.svg)](https://github.com/thomasmoelhave/tpie/actions/workflows/test_windows.yml) [![documentation](https://github.com/thomasmoelhave/tpie/actions/workflows/doxygen.yml/badge.svg)](https://thomasmoelhave.github.io/tpie) The TPIE (Templated Portable I/O Environment) library is a tool box providing From 9db091712a2d76caa6f2d6d05b551db5546a0d59 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Steffan=20S=C3=B8lvsten?= Date: Sun, 5 Jun 2022 00:04:33 +0200 Subject: [PATCH 10/20] Make Doxygen CI job name match test CI --- .github/workflows/doxygen.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/doxygen.yml b/.github/workflows/doxygen.yml index f4f94c1e0..6f3338030 100644 --- a/.github/workflows/doxygen.yml +++ b/.github/workflows/doxygen.yml @@ -10,7 +10,7 @@ on: jobs: skip_duplicate: - name: 'Check whether to skip job' + name: 'Skip job?' continue-on-error: true runs-on: ubuntu-latest From 17f4fe7b834b7e3dfe625d752cb2d519e66d931c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Steffan=20S=C3=B8lvsten?= Date: Thu, 9 Mar 2023 17:01:52 +0100 Subject: [PATCH 11/20] Update compiler versions for Linux and Mac CI --- .github/workflows/test_linux.yml | 11 ++++++----- .github/workflows/test_mac.yml | 9 +++++---- 2 files changed, 11 insertions(+), 9 deletions(-) diff --git a/.github/workflows/test_linux.yml b/.github/workflows/test_linux.yml index a938e35db..fa7f02dde 100644 --- a/.github/workflows/test_linux.yml +++ b/.github/workflows/test_linux.yml @@ -37,13 +37,14 @@ jobs: build_type: [Release, Debug] cc: # GNU Compiler - - { cc: gcc, v: 7, cxx: g++ } # oldest possible - - { cc: gcc, v: 9, cxx: g++ } # default - - { cc: gcc, v: 10, cxx: g++ } # newest + - { cc: gcc, v: 10, cxx: g++ } # oldest possible + - { cc: gcc, v: 11, cxx: g++ } # default + - { cc: gcc, v: 12, cxx: g++ } # newest # Clang Compiler - - { cc: clang, v: 7, cxx: clang++ } # oldest possible - - { cc: clang, v: 11, cxx: clang++ } # newst possible + - { cc: clang, v: 11, cxx: clang++ } # oldest possible + - { cc: clang, v: 14, cxx: clang++ } # default + - { cc: clang, v: 15, cxx: clang++ } # newst possible env: cc: ${{matrix.cc.cc}}-${{matrix.cc.v}} diff --git a/.github/workflows/test_mac.yml b/.github/workflows/test_mac.yml index 32c764e3b..ab632fb45 100644 --- a/.github/workflows/test_mac.yml +++ b/.github/workflows/test_mac.yml @@ -39,12 +39,13 @@ jobs: # GNU Compiler - { cc: gcc, v: 7, cxx: g++, xcode: latest } - { cc: gcc, v: 10, cxx: g++, xcode: latest } + - { cc: gcc, v: 12, cxx: g++, xcode: latest } # Clang Compiler - - { cc: clang, cxx: clang++, xcode: 11.7 } # oldest - - { cc: clang, cxx: clang++, xcode: 12.4 } - - { cc: clang, cxx: clang++, xcode: 13.1 } - - { cc: clang, cxx: clang++, xcode: 13.2 } # newest + - { cc: clang, cxx: clang++, xcode: 13.1 } # oldest + - { cc: clang, cxx: clang++, xcode: 13.4 } + - { cc: clang, cxx: clang++, xcode: 14.0 } + - { cc: clang, cxx: clang++, xcode: 14.2 } # newest steps: # Git repo set up From 1beaa9f4c13b2d9340a5a3bd24763c3f2556d46a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Steffan=20S=C3=B8lvsten?= Date: Mon, 13 Mar 2023 15:11:52 +0100 Subject: [PATCH 12/20] Update to newest version of MSVC setup action Otherwise, the default and newest version known is the 14.xxx, which is quite old. --- .github/workflows/test_windows.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/test_windows.yml b/.github/workflows/test_windows.yml index 61973a829..63abc4dfc 100644 --- a/.github/workflows/test_windows.yml +++ b/.github/workflows/test_windows.yml @@ -42,7 +42,7 @@ jobs: # Install dependencies - name: Set up Developer Command Prompt (p1) - uses: ilammy/msvc-dev-cmd@v1 + uses: ilammy/msvc-dev-cmd@v1.12.1 with: arch: x64 From fa28f329851298c1ab39bf483b136fe21f9776cd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Steffan=20S=C3=B8lvsten?= Date: Tue, 14 Mar 2023 14:44:15 +0100 Subject: [PATCH 13/20] Update Mac and Linux to the C++17 standard --- .github/workflows/test_linux.yml | 2 +- .github/workflows/test_mac.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/test_linux.yml b/.github/workflows/test_linux.yml index fa7f02dde..c4748c924 100644 --- a/.github/workflows/test_linux.yml +++ b/.github/workflows/test_linux.yml @@ -102,7 +102,7 @@ jobs: cmake -E make_directory ${{github.workspace}}/build cd ${{github.workspace}}/build - cmake -D CMAKE_BUILD_TYPE="${{matrix.build_type}}" -D CMAKE_CXX_STANDARD=14 -D CMAKE_C_FLAGS="$MACRO_FLAGS" -D CMAKE_CXX_FLAGS="$MACRO_FLAGS" .. + cmake -D CMAKE_BUILD_TYPE="${{matrix.build_type}}" -D CMAKE_CXX_STANDARD=17 -D CMAKE_C_FLAGS="$MACRO_FLAGS" -D CMAKE_CXX_FLAGS="$MACRO_FLAGS" .. make -j2 diff --git a/.github/workflows/test_mac.yml b/.github/workflows/test_mac.yml index ab632fb45..2b290a57a 100644 --- a/.github/workflows/test_mac.yml +++ b/.github/workflows/test_mac.yml @@ -100,7 +100,7 @@ jobs: cmake -E make_directory ${{github.workspace}}/build cd ${{github.workspace}}/build - cmake -D CMAKE_BUILD_TYPE="${{matrix.build_type}}" -D CMAKE_CXX_STANDARD=14 .. + cmake -D CMAKE_BUILD_TYPE="${{matrix.build_type}}" -D CMAKE_CXX_STANDARD=17 .. make -j2 From 4f957473811578898cbb3443b0d90cc9dd691295 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Steffan=20S=C3=B8lvsten?= Date: Wed, 15 Mar 2023 08:45:40 +0100 Subject: [PATCH 14/20] Cleanup of Windows CI --- .github/workflows/test_windows.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/test_windows.yml b/.github/workflows/test_windows.yml index 63abc4dfc..35a81c76e 100644 --- a/.github/workflows/test_windows.yml +++ b/.github/workflows/test_windows.yml @@ -41,7 +41,7 @@ jobs: uses: actions/checkout@v2 # Install dependencies - - name: Set up Developer Command Prompt (p1) + - name: Set up Developer Command Prompt uses: ilammy/msvc-dev-cmd@v1.12.1 with: arch: x64 @@ -63,7 +63,7 @@ jobs: cmake -E make_directory ${{github.workspace}}\build cd ${{github.workspace}}\build SET CXXFLAGS="%CXXFLAGS% -D_HAS_AUTO_PTR_ETC=1" - cmake -G "NMake Makefiles" -D CMAKE_BUILD_TYPE="${{matrix.build_type}}" -D CMAKE_CXX_STANDARD=17 -D Boost_INCLUDE_DIR=${{steps.install-boost.outputs.BOOST_ROOT}}/include -D Boost_LIBRARY_DIRS=${{steps.install-boost.outputs.BOOST_ROOT}}/lib .. + cmake -G "NMake Makefiles" -D CMAKE_BUILD_TYPE="${{matrix.build_type}}" -D CMAKE_CXX_STANDARD=17 -D Boost_INCLUDE_DIR=${{env.BOOST_ROOT}}/include -D Boost_LIBRARY_DIRS=${{env.BOOST_ROOT}}/lib .. nmake env: BOOST_ROOT: ${{ steps.install-boost.outputs.BOOST_ROOT }} From fbdc3b70cf609ecc287894d5ae7f56956f7a2836 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Steffan=20S=C3=B8lvsten?= Date: Tue, 21 Mar 2023 09:19:04 +0100 Subject: [PATCH 15/20] Fix running tests are mistakenly skipped if changes are in subfolders --- .github/workflows/test_linux.yml | 2 +- .github/workflows/test_mac.yml | 2 +- .github/workflows/test_windows.yml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/test_linux.yml b/.github/workflows/test_linux.yml index c4748c924..d0bac0b5a 100644 --- a/.github/workflows/test_linux.yml +++ b/.github/workflows/test_linux.yml @@ -18,7 +18,7 @@ jobs: - id: skip_check uses: fkirc/skip-duplicate-actions@master with: - paths: '["tpie/", "test/"]' + paths: '["tpie/**", "test/**"]' outputs: should_skip: ${{ steps.skip_check.outputs.should_skip }} diff --git a/.github/workflows/test_mac.yml b/.github/workflows/test_mac.yml index 2b290a57a..032cfffbf 100644 --- a/.github/workflows/test_mac.yml +++ b/.github/workflows/test_mac.yml @@ -18,7 +18,7 @@ jobs: - id: skip_check uses: fkirc/skip-duplicate-actions@master with: - paths: '["tpie/", "test/"]' + paths: '["tpie/**", "test/**"]' outputs: should_skip: ${{ steps.skip_check.outputs.should_skip }} diff --git a/.github/workflows/test_windows.yml b/.github/workflows/test_windows.yml index 35a81c76e..28fb60e81 100644 --- a/.github/workflows/test_windows.yml +++ b/.github/workflows/test_windows.yml @@ -18,7 +18,7 @@ jobs: - id: skip_check uses: fkirc/skip-duplicate-actions@master with: - paths: '["tpie/", "test/"]' + paths: '["tpie/**", "test/**"]' outputs: should_skip: ${{ steps.skip_check.outputs.should_skip }} From 30dc521c20762bdc7bf402844fdcf8ae143452f9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Steffan=20S=C3=B8lvsten?= Date: Tue, 21 Mar 2023 09:22:42 +0100 Subject: [PATCH 16/20] Ensure job completes with a checkmark even if skipped --- .github/workflows/test_linux.yml | 36 +++++++++++++++++++++++++---- .github/workflows/test_mac.yml | 37 ++++++++++++++++++++++++++---- .github/workflows/test_windows.yml | 25 ++++++++++++++++---- 3 files changed, 86 insertions(+), 12 deletions(-) diff --git a/.github/workflows/test_linux.yml b/.github/workflows/test_linux.yml index d0bac0b5a..710ce925a 100644 --- a/.github/workflows/test_linux.yml +++ b/.github/workflows/test_linux.yml @@ -9,7 +9,7 @@ on: - master jobs: - skip_duplicate: + check_skip: name: 'Skip job? (Linux)' continue-on-error: true runs-on: ubuntu-latest @@ -23,12 +23,12 @@ jobs: outputs: should_skip: ${{ steps.skip_check.outputs.should_skip }} - build_test: + build_and_test: name: 'Build + Test (Linux, ${{matrix.cc.cc}}-${{matrix.cc.v}}, ${{matrix.build_type}})' runs-on: ${{ matrix.os }} - needs: skip_duplicate - if: ${{ needs.skip_duplicate.outputs.should_skip != 'true' }} + needs: check_skip + if: ${{ needs.check_skip.outputs.should_skip != 'true' }} strategy: fail-fast: false @@ -117,3 +117,31 @@ jobs: sudo apt install python3 python3-pip pip install cmakeast python3 scripts/check_missing_ctests.py + + skip: + name: 'Build + Test (Linux, ${{matrix.cc.cc}}-${{matrix.cc.v}}, ${{matrix.build_type}})' + runs-on: ubuntu-latest + + needs: check_skip + if: ${{ needs.check_skip.outputs.should_skip == 'true' }} + + strategy: + fail-fast: false + matrix: + os: [ubuntu-latest] + build_type: [Release, Debug] + cc: + # GNU Compiler + - { cc: gcc, v: 10, cxx: g++ } # oldest possible + - { cc: gcc, v: 11, cxx: g++ } # default + - { cc: gcc, v: 12, cxx: g++ } # newest + + # Clang Compiler + - { cc: clang, v: 11, cxx: clang++ } # oldest possible + - { cc: clang, v: 14, cxx: clang++ } # default + - { cc: clang, v: 15, cxx: clang++ } # newst possible + + steps: + - name: Echo skip + run: | + echo "Running unit tests is skipped" diff --git a/.github/workflows/test_mac.yml b/.github/workflows/test_mac.yml index 032cfffbf..caa33fe96 100644 --- a/.github/workflows/test_mac.yml +++ b/.github/workflows/test_mac.yml @@ -9,7 +9,7 @@ on: - master jobs: - skip_duplicate: + check_skip: name: 'Skip job? (Mac OS)' continue-on-error: true runs-on: ubuntu-latest @@ -23,12 +23,12 @@ jobs: outputs: should_skip: ${{ steps.skip_check.outputs.should_skip }} - build_test: + build_and_test: name: 'Build + Test (Mac OS, ${{matrix.cc.cc}}@${{matrix.cc.v || matrix.cc.xcode}}, ${{matrix.build_type}})' runs-on: ${{ matrix.os }} - needs: skip_duplicate - if: ${{ needs.skip_duplicate.outputs.should_skip != 'true' }} + needs: check_skip + if: ${{ needs.check_skip.outputs.should_skip != 'true' }} strategy: fail-fast: false @@ -115,3 +115,32 @@ jobs: brew install python3 pip3 install cmakeast python3 scripts/check_missing_ctests.py + + skip: + name: 'Build + Test (Mac OS, ${{matrix.cc.cc}}@${{matrix.cc.v || matrix.cc.xcode}}, ${{matrix.build_type}})' + runs-on: ubuntu-latest + + needs: check_skip + if: ${{ needs.check_skip.outputs.should_skip == 'true' }} + + strategy: + fail-fast: false + matrix: + os: [ubuntu-latest] + build_type: [Release, Debug] + cc: + # GNU Compiler + - { cc: gcc, v: 10, cxx: g++ } # oldest possible + - { cc: gcc, v: 11, cxx: g++ } # default + - { cc: gcc, v: 12, cxx: g++ } # newest + + # Clang Compiler + - { cc: clang, v: 11, cxx: clang++ } # oldest possible + - { cc: clang, v: 14, cxx: clang++ } # default + - { cc: clang, v: 15, cxx: clang++ } # newst possible + + steps: + - name: Echo skip + run: | + echo "Running unit tests is skipped" + diff --git a/.github/workflows/test_windows.yml b/.github/workflows/test_windows.yml index 28fb60e81..668256ce5 100644 --- a/.github/workflows/test_windows.yml +++ b/.github/workflows/test_windows.yml @@ -9,7 +9,7 @@ on: - master jobs: - skip_duplicate: + check_skip: name: 'Skip job? (Windows)' continue-on-error: true runs-on: ubuntu-latest @@ -23,12 +23,12 @@ jobs: outputs: should_skip: ${{ steps.skip_check.outputs.should_skip }} - build_test: + build_and_test: name: 'Build + Test (Windows, ${{matrix.build_type}})' runs-on: windows-latest - needs: skip_duplicate - if: ${{ needs.skip_duplicate.outputs.should_skip != 'true' }} + needs: check_skip + if: ${{ needs.check_skip.outputs.should_skip != 'true' }} strategy: fail-fast: false @@ -73,3 +73,20 @@ jobs: run: | cd ${{github.workspace}}\build ctest + + skip: + name: 'Build + Test (Windows, ${{matrix.build_type}})' + runs-on: ubuntu-latest + + needs: check_skip + if: ${{ needs.check_skip.outputs.should_skip == 'true' }} + + strategy: + fail-fast: false + matrix: + build_type: [Release, Debug] + + steps: + - name: Echo skip + run: | + echo "Running unit tests is skipped" From 8fa5e9e3dd2b93f17edd06f92f9406ba8d84b074 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Steffan=20S=C3=B8lvsten?= Date: Fri, 22 Sep 2023 13:35:23 -0400 Subject: [PATCH 17/20] Remove trailing whitespace in tpie::packed_array --- tpie/packed_array.h | 62 ++++++++++++++++++++++----------------------- 1 file changed, 31 insertions(+), 31 deletions(-) diff --git a/tpie/packed_array.h b/tpie/packed_array.h index 567d806ae..6fdac68df 100644 --- a/tpie/packed_array.h +++ b/tpie/packed_array.h @@ -1,19 +1,19 @@ // -*- mode: c++; tab-width: 4; indent-tabs-mode: t; eval: (progn (c-set-style "stroustrup") (c-set-offset 'innamespace 0)); -*- // vi:set ts=4 sts=4 sw=4 noet : // Copyright 2008, The TPIE development team -// +// // This file is part of TPIE. -// +// // TPIE is free software: you can redistribute it and/or modify it under // the terms of the GNU Lesser General Public License as published by the // Free Software Foundation, either version 3 of the License, or (at your // option) any later version. -// +// // TPIE is distributed in the hope that it will be useful, but WITHOUT ANY // WARRANTY; without even the implied warranty of MERCHANTABILITY or // FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public // License for more details. -// +// // You should have received a copy of the GNU Lesser General Public License // along with TPIE. If not, see #ifndef __TPIE_PACKED_ARRAY_H__ @@ -147,11 +147,11 @@ class packed_array: public linear_memory_base >{ public: template friend class packed_array; operator T() const {return static_cast((elms[high(index)] >> low(index))&mask());} - iter_return_type & operator=(const T b) { + iter_return_type & operator=(const T b) { storage_type * p = elms+high(index); size_t i = low(index); *p = (*p & ~(mask()< >{ template class iter_base: public packed_array_iter_facade, forward, iter_return_type> { private: - iter_return_type elm; - + iter_return_type elm; + friend class const_iter_base; friend class packed_array; template friend class packed_array_iter_facade; @@ -176,13 +176,13 @@ class packed_array: public linear_memory_base >{ typedef iter_return_type value_type; typedef iter_return_type & reference; typedef iter_return_type * pointer; - + iter_return_type & operator*() {return elm;} iter_return_type * operator->() {return &elm;} iter_base & operator=(const iter_base & o) {elm.index = o.elm.index; elm.elms=o.elm.elms; return *this;} iter_base(iter_base const &o): elm(o.elm) {}; }; - + typedef T vssucks; ///////////////////////////////////////////////////////// /// \internal @@ -194,7 +194,7 @@ class packed_array: public linear_memory_base >{ private: const storage_type * elms; size_t idx; - + friend class packed_array; friend class boost::iterator_core_access; template friend class packed_array_iter_facade; @@ -211,7 +211,7 @@ class packed_array: public linear_memory_base >{ vssucks operator*() const {return static_cast(elms[high(idx)] >> low(idx) & mask());} const_iter_base(const_iter_base const& o): elms(o.elms), idx(o.idx) {} const_iter_base(iter_base const& o): elms(o.elm.elms), idx(o.elm.index) {} - }; + }; ///////////////////////////////////////////////////////// @@ -222,29 +222,29 @@ class packed_array: public linear_memory_base >{ struct return_type{ private: storage_type * p; - size_t i; + size_t i; return_type(storage_type * p_, size_t i_): p(p_), i(i_) {} friend class packed_array; public: - operator T() const {return static_cast((*p >> i) & mask());} - return_type & operator=(const T b) { + operator T() const {return static_cast((*p >> i) & mask());} + return_type & operator=(const T b) { *p = (*p & ~(mask()<(b) & mask()) << i); - return *this; + return *this; + } + return_type & operator=(const return_type & t){ + *this = (T) t; + return *this; } - return_type & operator=(const return_type & t){ - *this = (T) t; - return *this; - } }; storage_type * m_elements; size_t m_size; -public: +public: ///////////////////////////////////////////////////////// /// \brief Type of values containd in the array ///////////////////////////////////////////////////////// typedef T value_type; - + ///////////////////////////////////////////////////////// /// \brief Iterator over a const array ///////////////////////////////////////////////////////// @@ -272,14 +272,14 @@ class packed_array: public linear_memory_base >{ static double memory_coefficient(){ return B/8.0; } - + ///////////////////////////////////////////////////////// /// \copybrief linear_memory_structure_doc::memory_overhead() /// \copydetails linear_memory_structure_doc::memory_overhead() ///////////////////////////////////////////////////////// static double memory_overhead() { return (double)sizeof(packed_array)+(double)sizeof(storage_type); - } + } ///////////////////////////////////////////////////////// /// \brief Construct array of given size. @@ -311,7 +311,7 @@ class packed_array: public linear_memory_base >{ a.m_elements = nullptr; a.m_size = 0; } - + ///////////////////////////////////////////////////////// /// \brief Free up all memory used by the array ///////////////////////////////////////////////////////// @@ -364,13 +364,13 @@ class packed_array: public linear_memory_base >{ ///////////////////////////////////////////////////////// void fill(T value) { storage_type x=0; - for (size_t i=0; i < perword(); ++i) + for (size_t i=0; i < perword(); ++i) x = (x << B) + ((storage_type)value & mask()); for (size_t i=0; i < words(m_size); ++i) - m_elements[i] = x; + m_elements[i] = x; } - - + + ///////////////////////////////////////////////////////// /// \brief Change the size of the array /// @@ -407,8 +407,8 @@ class packed_array: public linear_memory_base >{ T operator[](size_t i)const { assert(i < m_size); return static_cast((m_elements[high(i)] >> low(i))&mask()); - } - + } + ///////////////////////////////////////////////////////// /// \brief Return a object behaving like a reference to an array entry /// From 7b9c1014ae8587f2bfed4cae94269ff59cbb5a95 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Steffan=20S=C3=B8lvsten?= Date: Fri, 22 Sep 2023 14:05:50 -0400 Subject: [PATCH 18/20] Clean up tpie::packed_array to decrease mental complexity There are many small things here, that unecessarily adds to the mental complexity of the codebase. Yet, I see no need to keep it as such to save sligthly on diskspace. - Made all comments align with column 80 (most were aligned with 65, but not consistently so) - Place `{` bracket for all class and function scope-openings on their own line. Furthemore, if the function is short, add whitespace around `{` and `}` to make it easier to identify. - Place inheritance and member initialization list on its own line. This makes it (1) more clearly separated from the rest and (2) better respects the column limit of the remaining code. - Add vertical whitespace between member functions to better convey what goes together. - Enforce each line has at most a single statement. - Make all classes follow the same ordering between *friend*, *variables*, *operators*, *constructors*, and so on. - Add empty documentation comment as separator between functions. - Add missing documentation comments for `tpie::packed_array` --- tpie/packed_array.h | 611 +++++++++++++++++++++++++++++++------------- 1 file changed, 430 insertions(+), 181 deletions(-) diff --git a/tpie/packed_array.h b/tpie/packed_array.h index 6fdac68df..d7e49b741 100644 --- a/tpie/packed_array.h +++ b/tpie/packed_array.h @@ -31,66 +31,159 @@ namespace tpie { -///////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////// /// \internal /// \brief Base class for the iterators +/// /// \tparam CT CRTP child class +/// /// \tparam forward Is this a forward iterator? -///////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////// template -class packed_array_iter_facade { +class packed_array_iter_facade +{ private: - CT & self() {return *reinterpret_cast(this);} template friend class packed_array_iter_facade; + /////////////////////////////////////////////////////////////////////////// + /// \brief Reference to `this` as the CRTP class `CT`. + /////////////////////////////////////////////////////////////////////////// + CT & self() + { return *reinterpret_cast(this); } + public: - const CT & self() const {return *reinterpret_cast(this);} + /////////////////////////////////////////////////////////////////////////// + const CT & self() const + { return *reinterpret_cast(this); } + /////////////////////////////////////////////////////////////////////////// typedef ptrdiff_t difference_type; + + /////////////////////////////////////////////////////////////////////////// typedef std::random_access_iterator_tag iterator_category; + + /////////////////////////////////////////////////////////////////////////// template - bool operator==(const TT & o) const {return (self()-o) == 0;} + bool operator==(const TT & o) const + { return (self()-o) == 0; } + + /////////////////////////////////////////////////////////////////////////// template - bool operator!=(const TT & o) const {return (self()-o) != 0;} - CT & operator++() {self().index() += forward?1:-1; return self();} - CT operator++(int) {CT x=self(); ++self(); return x;} - CT & operator--() {self().index() += forward?-1:1; return self();} - CT operator--(int) {CT x=self(); --self(); return x;} - bool operator<(const CT & o) const {return (self()-o) < 0;} - bool operator>(const CT & o) const {return (self()-o) > 0;} - bool operator<=(const CT & o) const {return (self()-o) <= 0;} - bool operator>=(const CT & o) const {return (self()-o) >= 0;} - ptrdiff_t operator-(const CT & o) const {return forward ? (self().index() - o.index()) : (o.index() - self().index());} - CT operator+(difference_type n) const {CT x=self(); return x += n;} - CT operator-(difference_type n) const {CT x=self(); return x -= n;} - CT & operator+=(difference_type n) {self().index() += (forward?n:-n); return self();} - CT & operator-=(difference_type n) {self().index() += (forward?n:-n); return self();} - RT operator[](difference_type n) {return *(self() + n);} + bool operator!=(const TT & o) const + { return (self()-o) != 0; } + + /////////////////////////////////////////////////////////////////////////// + CT & operator++() + { + self().index() += forward ? 1 : -1; + return self(); + } + + /////////////////////////////////////////////////////////////////////////// + CT operator++(int) + { + CT x = self(); + ++self(); + return x; + } + + /////////////////////////////////////////////////////////////////////////// + CT & operator--() + { + self().index() += forward ? -1 : 1; + return self(); + } + + /////////////////////////////////////////////////////////////////////////// + CT operator--(int) + { + CT x = self(); + --self(); + return x; + } + + /////////////////////////////////////////////////////////////////////////// + bool operator<(const CT & o) const + { return (self()-o) < 0; } + + /////////////////////////////////////////////////////////////////////////// + bool operator>(const CT & o) const + { return (self()-o) > 0; } + + /////////////////////////////////////////////////////////////////////////// + bool operator<=(const CT & o) const + { return (self()-o) <= 0; } + + /////////////////////////////////////////////////////////////////////////// + bool operator>=(const CT & o) const + { return (self()-o) >= 0; } + + /////////////////////////////////////////////////////////////////////////// + difference_type operator-(const CT & o) const + { return forward ? (self().index() - o.index()) : (o.index() - self().index()); } + + /////////////////////////////////////////////////////////////////////////// + CT operator+(difference_type n) const + { + CT x = self(); + return x += n; + } + + /////////////////////////////////////////////////////////////////////////// + CT operator-(difference_type n) const + { + CT x = self(); + return x -= n; + } + + /////////////////////////////////////////////////////////////////////////// + CT & operator+=(difference_type n) + { + self().index() += (forward?n:-n); + return self(); + } + + /////////////////////////////////////////////////////////////////////////// + CT & operator-=(difference_type n) + { + self().index() += (forward?n:-n); + return self(); + } + + /////////////////////////////////////////////////////////////////////////// + RT operator[](difference_type n) + { + return *(self() + n); + } }; +/////////////////////////////////////////////////////////////////////////////// template -CT operator+(ptrdiff_t n, const packed_array_iter_facade & i) { +CT operator+(ptrdiff_t n, const packed_array_iter_facade & i) +{ CT tmp(i.self()); tmp += n; return tmp; } -/////////////////////////////////////////////////////////////////////////// -/// \brief An array storring elements of type T using B -/// bits to to store a element. +/////////////////////////////////////////////////////////////////////////////// +/// \brief An array storing elements of type T using B bits to store an element. /// -/// T must be either bool or int. B must devide the word size, (XXX why?) -/// in reality only 1, 2 or 4 seems usamle +/// \tparam T The type of elements to store in the array. This has to be `bool` +/// or `int`. /// -/// \tparam T The type of elements to store in the array -/// \tparam B The number of bits used to store a single element -/////////////////////////////////////////////////////////////////////////// +/// \tparam B The number of bits used to store a single element. This value must +/// divide the word size, so it can in reality only be 1, 2, or 4. +/////////////////////////////////////////////////////////////////////////////// template -class packed_array: public linear_memory_base >{ +class packed_array + : public linear_memory_base > +{ public: typedef size_t storage_type; + private: - // TODO is this necessary? + // TODO: is this necessary? Can we slack this requirement to store more? static_assert(sizeof(storage_type) * 8 % B == 0, "Bad storrage"); /////////////////////////////////////////////////////////////////////////// @@ -128,26 +221,38 @@ class packed_array: public linear_memory_base >{ return (1 << B)-1; } + /////////////////////////////////////////////////////////////////////////// template class const_iter_base; + /////////////////////////////////////////////////////////////////////////// template class iter_base; - ///////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////////// /// \internal - /// \brief Iterator and reverse iterator will return an element - /// of this type, it can be cast to a T, and assigned a T value - ///////////////////////////////////////////////////////// + /// + /// \brief Iterator and reverse iterator will return an element of this + /// type, it can be cast to a T, and assigned a T value + /////////////////////////////////////////////////////////////////////////// class iter_return_type { private: - iter_return_type(storage_type * e, size_t i): elms(e), index(i) {} + template friend class packed_array; + storage_type * elms; size_t index; + + iter_return_type(storage_type * e, size_t i) + : elms(e), index(i) + { } public: - template friend class packed_array; - operator T() const {return static_cast((elms[high(index)] >> low(index))&mask());} - iter_return_type & operator=(const T b) { + /////////////////////////////////////////////////////////////////////// + operator T() const + { return static_cast((elms[high(index)] >> low(index))&mask()); } + + /////////////////////////////////////////////////////////////////////// + iter_return_type & operator=(const T b) + { storage_type * p = elms+high(index); size_t i = low(index); *p = (*p & ~(mask()< >{ } }; - ///////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////////// /// \internal + /// /// \brief Base class for iterator and reverse iterator + /// /// \tparam forward Is this a forward iterator? - ///////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////////// template - class iter_base: public packed_array_iter_facade, forward, iter_return_type> { + class iter_base + : public packed_array_iter_facade, forward, iter_return_type> + { private: - iter_return_type elm; - friend class const_iter_base; friend class packed_array; template friend class packed_array_iter_facade; - iter_base(storage_type * elms, size_t index): elm(elms, index) {}; - size_t & index() {return elm.index;} - const size_t & index() const {return elm.index;} + iter_return_type elm; + + /////////////////////////////////////////////////////////////////////// + iter_base(storage_type * elms, size_t index) + : elm(elms, index) + { } + + /////////////////////////////////////////////////////////////////////// + size_t & index() + { return elm.index; } + + /////////////////////////////////////////////////////////////////////// + const size_t & index() const + { return elm.index; } + public: typedef iter_return_type value_type; typedef iter_return_type & reference; typedef iter_return_type * pointer; - iter_return_type & operator*() {return elm;} - iter_return_type * operator->() {return &elm;} - iter_base & operator=(const iter_base & o) {elm.index = o.elm.index; elm.elms=o.elm.elms; return *this;} - iter_base(iter_base const &o): elm(o.elm) {}; + /////////////////////////////////////////////////////////////////////// + iter_return_type & operator*() + { return elm; } + + /////////////////////////////////////////////////////////////////////// + iter_return_type * operator->() + { return &elm; } + + /////////////////////////////////////////////////////////////////////// + iter_base & operator=(const iter_base & o) + { + elm.index = o.elm.index; + elm.elms=o.elm.elms; + return *this; + } + + /////////////////////////////////////////////////////////////////////// + iter_base(iter_base const &o) + : elm(o.elm) + { } }; typedef T vssucks; - ///////////////////////////////////////////////////////// + + /////////////////////////////////////////////////////////////////////////// /// \internal - /// \brief Base class for const ierator and const reverse iterator + /// + /// \brief Base class for const iterator and const reverse iterator + /// /// \tparam forward Is this a forward iterator? - ///////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////////// template - class const_iter_base: public packed_array_iter_facade, forward, vssucks> { + class const_iter_base + : public packed_array_iter_facade, forward, vssucks> + { private: - const storage_type * elms; - size_t idx; - friend class packed_array; friend class boost::iterator_core_access; template friend class packed_array_iter_facade; - const_iter_base(const storage_type * e, size_t i): elms(e), idx(i) {} - size_t & index() {return idx;} - const size_t & index() const {return idx;} + const storage_type * elms; + size_t idx; + + /////////////////////////////////////////////////////////////////////// + const_iter_base(const storage_type * e, size_t i) + : elms(e), idx(i) + { } + + /////////////////////////////////////////////////////////////////////// + size_t & index() + { return idx; } + + /////////////////////////////////////////////////////////////////////// + const size_t & index() const + { return idx; } + public: typedef vssucks value_type; typedef vssucks reference; typedef vssucks * pointer; - const_iter_base & operator=(const const_iter_base & o) {idx = o.idx; elms=o.elms; return *this;} - vssucks operator*() const {return static_cast(elms[high(idx)] >> low(idx) & mask());} - const_iter_base(const_iter_base const& o): elms(o.elms), idx(o.idx) {} - const_iter_base(iter_base const& o): elms(o.elm.elms), idx(o.elm.index) {} - }; + /////////////////////////////////////////////////////////////////////// + const_iter_base & operator=(const const_iter_base & o) + { + idx = o.idx; + elms=o.elms; + return *this; + } + + /////////////////////////////////////////////////////////////////////// + vssucks operator*() const + { return static_cast(elms[high(idx)] >> low(idx) & mask()); } + /////////////////////////////////////////////////////////////////////// + const_iter_base(const_iter_base const& o) + : elms(o.elms), idx(o.idx) + { } - ///////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////// + const_iter_base(iter_base const& o) + : elms(o.elm.elms), idx(o.elm.index) + { } + }; + + /////////////////////////////////////////////////////////////////////////// /// \internal - /// \brief This type is returned by the [] operator. - /// It can be cast to a T, and assigned a T value. - ///////////////////////////////////////////////////////// - struct return_type{ + /// + /// \brief Type of values returned by the [] operator. + /// + /// \details It can be cast to a T, and assigned a T value. That is, this + /// abstracts away packing and unpacking of logical values into and out of + /// the physical value that stores them. + /////////////////////////////////////////////////////////////////////////// + struct return_type + { private: + friend class packed_array; + storage_type * p; size_t i; - return_type(storage_type * p_, size_t i_): p(p_), i(i_) {} - friend class packed_array; + + /////////////////////////////////////////////////////////////////////// + return_type(storage_type * p_, size_t i_) + : p(p_), i(i_) + { } + public: - operator T() const {return static_cast((*p >> i) & mask());} - return_type & operator=(const T b) { + /////////////////////////////////////////////////////////////////////// + operator T() const + { return static_cast((*p >> i) & mask()); } + + /////////////////////////////////////////////////////////////////////// + return_type & operator=(const T b) + { *p = (*p & ~(mask()<(b) & mask()) << i); return *this; } - return_type & operator=(const return_type & t){ + + /////////////////////////////////////////////////////////////////////// + return_type & operator=(const return_type & t) + { *this = (T) t; return *this; } @@ -239,130 +424,146 @@ class packed_array: public linear_memory_base >{ storage_type * m_elements; size_t m_size; + public: - ///////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////////// /// \brief Type of values containd in the array - ///////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////////// typedef T value_type; - ///////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////////// /// \brief Iterator over a const array - ///////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////////// typedef const_iter_base const_iterator; - ///////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////////// /// \brief Reverse iterator over a const array - ///////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////////// typedef const_iter_base const_reverse_iterator; - ///////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////////// /// \brief Iterator over an array - ///////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////////// typedef iter_base iterator; - ///////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////////// /// \brief Reverse iterator over an array - ///////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////////// typedef iter_base reverse_iterator; - ///////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////////// /// \copybrief linear_memory_structure_doc::memory_coefficient() /// \copydetails linear_memory_structure_doc::memory_coefficient() - ///////////////////////////////////////////////////////// - static double memory_coefficient(){ - return B/8.0; - } + /////////////////////////////////////////////////////////////////////////// + static double memory_coefficient() + { return B/8.0; } - ///////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////////// /// \copybrief linear_memory_structure_doc::memory_overhead() /// \copydetails linear_memory_structure_doc::memory_overhead() - ///////////////////////////////////////////////////////// - static double memory_overhead() { - return (double)sizeof(packed_array)+(double)sizeof(storage_type); - } + /////////////////////////////////////////////////////////////////////////// + static double memory_overhead() + { return (double)sizeof(packed_array)+(double)sizeof(storage_type); } - ///////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////////// /// \brief Construct array of given size. /// - /// The elements have undefined values + /// \details The elements have undefined values + /// /// \param s The number of elements in the array - ///////////////////////////////////////////////////////// - packed_array(size_t s=0): m_elements(nullptr), m_size(0) {resize(s);} + /////////////////////////////////////////////////////////////////////////// + packed_array(size_t s = 0) + : m_elements(nullptr), m_size(0) + { resize(s); } - ///////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////////// /// \brief Construct array of given size. /// /// \param s The number of elements in the array + /// /// \param value Each entry of the array is initialized with this value - ///////////////////////////////////////////////////////// - packed_array(size_t s, T value): m_elements(nullptr), m_size(0) {resize(s,value);} + /////////////////////////////////////////////////////////////////////////// + packed_array(size_t s, T value) + : m_elements(nullptr), m_size(0) + { resize(s,value); } - ///////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////////// /// \brief Construct a copy of another array + /// /// \param a The array to copy - ///////////////////////////////////////////////////////// - packed_array(const packed_array & a): m_elements(nullptr), m_size(0) {*this=a;} + /////////////////////////////////////////////////////////////////////////// + packed_array(const packed_array & a) + : m_elements(nullptr), m_size(0) + { *this=a; } - ///////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////////// /// \brief Move another aray into me + /// /// \param a The array to copy - ///////////////////////////////////////////////////////// - packed_array(packed_array && a): m_elements(a.m_elements), m_size(a.m_size) { + /////////////////////////////////////////////////////////////////////////// + packed_array(packed_array && a) + : m_elements(a.m_elements), m_size(a.m_size) + { a.m_elements = nullptr; a.m_size = 0; } - ///////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////////// /// \brief Free up all memory used by the array - ///////////////////////////////////////////////////////// - ~packed_array() {resize(0);} + /////////////////////////////////////////////////////////////////////////// + ~packed_array() + { resize(0); } - ///////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////////// /// \brief Copy elements from another array into this. /// /// Note this array is resized to the size of other /// \param a The array to copy from /// \return a reference to this array - ///////////////////////////////////////////////////////// - packed_array & operator=(const packed_array & a) { + /////////////////////////////////////////////////////////////////////////// + packed_array & operator=(const packed_array & a) + { resize(a.m_size); for(size_t i=0;i(words(m_size)):nullptr; } - ///////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////////// /// \brief Fill the entier array with the given value /// /// \param value the initialization element - ///////////////////////////////////////////////////////// - void fill(T value) { + /////////////////////////////////////////////////////////////////////////// + void fill(T value) + { storage_type x=0; for (size_t i=0; i < perword(); ++i) x = (x << B) + ((storage_type)value & mask()); @@ -371,121 +572,169 @@ class packed_array: public linear_memory_base >{ } - ///////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////////// /// \brief Change the size of the array /// - /// All elements are lost, after resize the value of the entries - /// is initialized by a copy of elm + /// All elements are lost, after resize the value of the entries is + /// initialized by a copy of elm + /// /// \param s the new size of the array + /// /// \param value the initialization element - ///////////////////////////////////////////////////////// - void resize(size_t s, T value) { + /////////////////////////////////////////////////////////////////////////// + void resize(size_t s, T value) + { resize(s); fill(value); } - ///////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////////// /// \brief Return the size of the array /// /// \return the size of the array - ///////////////////////////////////////////////////////// - size_t size() const {return m_size;} + /////////////////////////////////////////////////////////////////////////// + size_t size() const + { return m_size; } - ///////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////////// /// \brief Check if the array is empty /// /// \return true if and only if size is 0 - ///////////////////////////////////////////////////////// - bool empty() const {return m_size ==0;} + /////////////////////////////////////////////////////////////////////////// + bool empty() const + { return m_size ==0; } - ///////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////////// /// \brief Return an array entry /// /// \param i the index of the entry to return + /// /// \return the array entry - ///////////////////////////////////////////////////////// - T operator[](size_t i)const { + /////////////////////////////////////////////////////////////////////////// + T operator[](size_t i) const + { assert(i < m_size); return static_cast((m_elements[high(i)] >> low(i))&mask()); } - ///////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////////// /// \brief Return a object behaving like a reference to an array entry /// /// \param i the index of the entry to return + /// /// \return The object behaving like a reference - ///////////////////////////////////////////////////////// - return_type operator[](size_t i) { + /////////////////////////////////////////////////////////////////////////// + return_type operator[](size_t i) + { assert(i < m_size); return return_type(m_elements+high(i), low(i)); } - ///////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////////// /// \brief Return an iterator to the i'th element of the array /// /// \param i the index of the element we want an iterator to + /// /// \return an iterator to the i'th element - ///////////////////////////////////////////////////////// - iterator find(size_type i) {return iterator(m_elements,i);} + /////////////////////////////////////////////////////////////////////////// + iterator find(size_type i) + { return iterator(m_elements,i); } - ///////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////////// /// \brief Return a const iterator to the i'th element of the array /// /// \param i the index of the element we want an iterator to + /// /// \return a const iterator to the i'th element - ///////////////////////////////////////////////////////// - const_iterator find(size_type i) const {return const_iterator(m_elements,i);} + /////////////////////////////////////////////////////////////////////////// + const_iterator find(size_type i) const + { return const_iterator(m_elements,i); } - ///////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////////// /// \brief Return an iterator to the beginning of the array /// - /// \return an iterator tho the beginning of the array - ///////////////////////////////////////////////////////// - iterator begin() {return iterator(m_elements,0);} + /// \return an iterator to the beginning of the array + /////////////////////////////////////////////////////////////////////////// + iterator begin() + { return iterator(m_elements,0); } - ///////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////////// /// \brief Return a const iterator to the beginning of the array /// - /// \return a const iterator tho the beginning of the array - ///////////////////////////////////////////////////////// - const_iterator begin() const {return const_iterator(m_elements,0);} + /// \return a const iterator to the beginning of the array + /////////////////////////////////////////////////////////////////////////// + const_iterator begin() const + { return const_iterator(m_elements,0); } - ///////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////////// /// \brief Return an iterator to the end of the array /// - /// \return an iterator tho the end of the array - ///////////////////////////////////////////////////////// - iterator end() {return iterator(m_elements,m_size);} + /// \return an iterator to the end of the array + /////////////////////////////////////////////////////////////////////////// + iterator end() + { return iterator(m_elements,m_size); } - ///////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////////// /// \brief Return a const iterator to the end of the array /// - /// \return a const iterator tho the end of the array - ///////////////////////////////////////////////////////// - const_iterator end() const {return const_iterator(m_elements,m_size);} + /// \return a const iterator to the end of the array + /////////////////////////////////////////////////////////////////////////// + const_iterator end() const + { return const_iterator(m_elements,m_size); } - //We use m_elements -1 as basic for the reverse operators - //To make sure that the index of rend is positive - reverse_iterator rbegin() {return reverse_iterator(m_elements-1, perword()+m_size-1);} - const_reverse_iterator rbegin() const {return const_reverse_iterator(m_elements-1, perword()+m_size-1);} - reverse_iterator rend() {return reverse_iterator(m_elements-1, perword()-1);} - const_reverse_iterator rend() const {return const_reverse_iterator(m_elements-1, perword()-1);} + /////////////////////////////////////////////////////////////////////////// + /// \brief Return a reverse iterator to the beginning of the array + /// + /// \return a reverse iterator to the beginning of the array + /// + /// \internal We use m_elements -1 as basis for the reverse operators To + // make sure that the index of rend is positive + /////////////////////////////////////////////////////////////////////////// + reverse_iterator rbegin() + { return reverse_iterator(m_elements-1, perword()+m_size-1); } + + /////////////////////////////////////////////////////////////////////////// + /// \brief Return a const reverse iterator to the beginning of the array + /// + /// \return a reverse iterator to the beginning of the array + /////////////////////////////////////////////////////////////////////////// + const_reverse_iterator rbegin() const + { return const_reverse_iterator(m_elements-1, perword()+m_size-1); } + + /////////////////////////////////////////////////////////////////////////// + /// \brief Return a reverse iterator to the end of the array + /// + /// \return a const reverse iterator to the end of the array + /////////////////////////////////////////////////////////////////////////// + reverse_iterator rend() + { return reverse_iterator(m_elements-1, perword()-1); } + + /////////////////////////////////////////////////////////////////////////// + /// \brief Return a const reverse iterator to the end of the array + /// + /// \return a const reverse iterator to the end of the array + /////////////////////////////////////////////////////////////////////////// + const_reverse_iterator rend() const + { return const_reverse_iterator(m_elements-1, perword()-1); } /////////////////////////////////////////////////////////////////////////// /// \brief Swap two arrays. /////////////////////////////////////////////////////////////////////////// - void swap(packed_array & o) { + void swap(packed_array & o) + { std::swap(m_elements, o.m_elements); std::swap(m_size, o.m_size); } }; +} // namespace tpie -} //namespace tpie - -namespace std { +namespace std +{ template -void swap(tpie::packed_array & a, tpie::packed_array & b) { +void swap(tpie::packed_array & a, tpie::packed_array & b) +{ a.swap(b); } -} //namespace std +} // namespace std + #endif //__TPIE_PACKED_ARRAY_H__ From e8e0f07ef3ca0c1c10b0067268c54c41928e0713 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Steffan=20S=C3=B8lvsten?= Date: Fri, 22 Sep 2023 14:40:38 -0400 Subject: [PATCH 19/20] Add explanatory comment for typedef This workaround is not necessary anymore for newer versions of Visual Studio --- tpie/packed_array.h | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/tpie/packed_array.h b/tpie/packed_array.h index d7e49b741..327102631 100644 --- a/tpie/packed_array.h +++ b/tpie/packed_array.h @@ -318,6 +318,15 @@ class packed_array { } }; + /////////////////////////////////////////////////////////////////////////// + /// \internal + /// + /// Added in `c9d7154f0` (10th of May, 2011) as a quick fix in Visual + /// Studio. Given the date, this was version 10.0 or earlier. This + /// workaround is not necessary anymore with Visual Studio 2019+ and hence + /// can be reverted (at the cost of slightly breaking backwards + /// compatibility). + /////////////////////////////////////////////////////////////////////////// typedef T vssucks; /////////////////////////////////////////////////////////////////////////// From c02854034b8e3179f4ebddd9556681da3c2cff99 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Steffan=20S=C3=B8lvsten?= Date: Fri, 22 Sep 2023 14:43:24 -0400 Subject: [PATCH 20/20] Fix tpie::packed_array cannot compile with MSVC 19.28+ Microsoft's standard library assumes that a const version of tpie::packed_array::iterator and similar only are immutable with respect to the index, not the value in said index. That is, they assume the iterator reflects a 'T* const' semantics, whereas the prior version implemented a 'const T* const' semantics." --- tpie/packed_array.h | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/tpie/packed_array.h b/tpie/packed_array.h index 327102631..25f174cf9 100644 --- a/tpie/packed_array.h +++ b/tpie/packed_array.h @@ -300,10 +300,18 @@ class packed_array iter_return_type & operator*() { return elm; } + /////////////////////////////////////////////////////////////////////// + iter_return_type & operator*() const + { return const_cast(elm); } + /////////////////////////////////////////////////////////////////////// iter_return_type * operator->() { return &elm; } + /////////////////////////////////////////////////////////////////////// + iter_return_type * operator->() const + { return &elm; } + /////////////////////////////////////////////////////////////////////// iter_base & operator=(const iter_base & o) {