Skip to content

Commit

Permalink
flattened-iterator
Browse files Browse the repository at this point in the history
  • Loading branch information
alfC committed Feb 15, 2025
1 parent 2aba019 commit 0866c03
Show file tree
Hide file tree
Showing 9 changed files with 130 additions and 37 deletions.
64 changes: 56 additions & 8 deletions include/boost/multi/array_ref.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -508,7 +508,7 @@ struct array_iterator // NOLINT(fuchsia-multiple-inheritance) for facades

using ptr_type = subarray_ptr<element, D-1, element_ptr, layout_t<D-1>>;

using stride_type = index;
using stride_type = Stride;
using layout_type = typename reference::layout_type; // layout_t<D - 1>

// BOOST_MULTI_HD constexpr explicit array_iterator(std::nullptr_t nil) : ptr_{nil} {}
Expand Down Expand Up @@ -583,7 +583,7 @@ struct array_iterator // NOLINT(fuchsia-multiple-inheritance) for facades
return 0 < other - *this;
}

BOOST_MULTI_HD constexpr explicit array_iterator(typename subarray<element, D-1, element_ptr>::element_ptr base, layout_t<D-1> const& lyt, index stride)
BOOST_MULTI_HD constexpr explicit array_iterator(typename subarray<element, D-1, element_ptr>::element_ptr base, layout_t<D-1> const& lyt, Stride stride)
: ptr_{base, lyt}, stride_{stride} {}

template<class, dimensionality_type, class, class> friend struct const_subarray;
Expand Down Expand Up @@ -1351,12 +1351,6 @@ struct const_subarray : array_types<T, D, ElementPtr, Layout> {
return const_subarray<T, D-1, ElementPtr>{new_layout, types::base_};
}

void flattened() const = delete;
// {
// multi::biiterator<std::decay_t<decltype(this->begin())>> biit{this->begin(), 0, size(*(this->begin()))};
// return basic_array<T, D-1, decltype(biit)>(this->layout().sub, biit);
// }

constexpr auto broadcasted() const& {
multi::layout_t<D + 1> const new_layout{layout(), 0, 0, (std::numeric_limits<size_type>::max)()}; // paren for MSVC macros
return const_subarray<T, D+1, typename const_subarray::element_const_ptr>{new_layout, types::base_};
Expand Down Expand Up @@ -1586,6 +1580,60 @@ struct const_subarray : array_types<T, D, ElementPtr, Layout> {
#pragma clang diagnostic pop
#endif

struct bistride_t {
difference_type stride_;
difference_type size_;
difference_type sub_stride_;
difference_type rest_;

using category = std::random_access_iterator_tag;

#if defined(__clang__)
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wunknown-warning-option"
#pragma clang diagnostic ignored "-Wunsafe-buffer-usage" // TODO(correaa) use checked span
#endif

friend auto operator+=(ElementPtr& ptr, bistride_t& self) noexcept -> auto& {
ptr += self.sub_stride_;
++self.rest_;
if(self.rest_ != self.size_) { return ptr; }
ptr -= self.size_*self.sub_stride_;
self.rest_ = 0;
ptr += self.stride_;
return ptr;
}

friend auto operator-=(ElementPtr& ptr, bistride_t& self) noexcept -> auto& {
ptr -= self.sub_stride_;
--self.rest_;
if(self.rest_ != -1) { return ptr; }
self.rest_ = self.size_ - 1;
ptr += self.size_*self.sub_stride_;
ptr -= self.stride_;

return ptr;
}

#if defined(__clang__)
#pragma clang diagnostic pop
#endif
};

auto flattened_begin() {
if constexpr(D == 2) {
return array_iterator<T, D - 1, ElementPtr, false, false, bistride_t>(this->base_ , bistride_t{this->stride(), this->sub().size(), this->sub().stride(), 0});
} else {
return array_iterator<T, D - 1, ElementPtr, false, false, bistride_t>(this->base_, this->sub().sub(), bistride_t{this->stride(), this->sub().size(), this->sub().stride(), 0});
}
}

void flattened() const = delete;
// {
// multi::biiterator<std::decay_t<decltype(this->begin())>> biit{this->begin(), 0, size(*(this->begin()))};
// return basic_array<T, D-1, decltype(biit)>(this->layout().sub, biit);
// }

private:
#if defined(__clang__)
#pragma clang diagnostic push
Expand Down
19 changes: 5 additions & 14 deletions include/boost/multi/detail/static_allocator.hpp
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright 2023-2024 Alfredo A. Correa
// Copyright 2023-2025 Alfredo A. Correa
// Distributed under the Boost Software License, Version 1.0.
// https://www.boost.org/LICENSE_1_0.txt

Expand All @@ -20,23 +20,14 @@ namespace boost::multi::detail {
#pragma clang diagnostic ignored "-Wpadded"
#endif

template<class T, std::size_t N>
template<class T, std::size_t N = std::extent_v<T> > // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
class static_allocator { // NOSONAR(cpp:S4963) this allocator has special semantics
#ifdef _MSC_VER
#pragma warning(push)
#pragma warning(disable : 4324) // Warning that the structure is padded due to the below
#endif

// #if defined(__clang__)
// #pragma clang diagnostic push
// #pragma clang diagnostic ignored "-Wpadded"
// #endif

BOOST_MULTI_NO_UNIQUE_ADDRESS alignas(T) std::array<std::byte, sizeof(T) * N> buffer_;

// #if defined(__clang__)
// #pragma clang diagnostic pop
// #endif
BOOST_MULTI_NO_UNIQUE_ADDRESS alignas(T) std::array<std::byte, sizeof(T) * N> buffer_;

#ifdef _MSC_VER
#pragma warning(pop)
Expand All @@ -45,8 +36,8 @@ class static_allocator { // NOSONAR(cpp:S4963) this allocator has special seman
bool dirty_ = false;

public:
using value_type = T;
using pointer = T*;
using value_type = std::remove_extent_t<T> ;
using pointer = std::remove_extent_t<T>*;

template<class TT> struct rebind {
using other = static_allocator<TT, N>;
Expand Down
14 changes: 7 additions & 7 deletions pre-push
Original file line number Diff line number Diff line change
Expand Up @@ -38,19 +38,19 @@ if [[ $(uname -m) != 'arm64' ]]; then

export VALGRIND_EXE="valgrind --trace-children=yes --leak-check=full --track-origins=yes --show-leak-kinds=all --suppressions=.valgrind_suppressions --gen-suppressions=all --error-exitcode=1 "

(mkdir -p .build.clang++-rel && cd .build.clang++-rel && CXX=clang++ cmake .. -DCMAKE_BUILD_TYPE=Release && cmake --build . $CMT && ctest --parallel 2 --output-on-failure $CTR) || exit 666
(mkdir -p .build.g++ && cd .build.g++ && CXX=g++ cmake .. -DCMAKE_BUILD_TYPE=Debug -DCMAKE_EXPORT_COMPILE_COMMANDS=ON && cmake --build . $CMT && ctest --parallel 2 --output-on-failure $CTR ) || exit 666
(mkdir -p .build.clang++ && cd .build.clang++ && CXX=clang++ cmake .. -DCMAKE_BUILD_TYPE=Debug && cmake --build . $CMT && ctest --parallel 2 --output-on-failure $CTR) || exit 666
(mkdir -p .build.clang++.libcpp && cd .build.clang++.libcpp && CXX=clang++ cmake .. -DCMAKE_BUILD_TYPE=Debug -DCMAKE_CXX_STANDARD=20 -DCMAKE_CXX_FLAGS="-stdlib=libc++" && cmake --build . $CMT && ctest --parallel 2 --output-on-failure $CTR) || exit 666
(mkdir -p .build.g++-rel && cd .build.g++-rel && CXX=g++ cmake .. -DCMAKE_BUILD_TYPE=Release && cmake --build . $CMT && ctest --parallel 2 --output-on-failure $CTR) || exit 666
(mkdir -p .build.clang++-rel && cd .build.clang++-rel && CXX=clang++ cmake .. -DCMAKE_BUILD_TYPE=Release && cmake --build . $CMT && (ctest --parallel 2 $CTR || ctest --rerun-failed --output-on-failure $CTR) ) || exit 666
(mkdir -p .build.g++ && cd .build.g++ && CXX=g++ cmake .. -DCMAKE_BUILD_TYPE=Debug -DCMAKE_EXPORT_COMPILE_COMMANDS=ON && cmake --build . $CMT && ctest --parallel 2 --output-on-failure $CTR) || exit 666
(mkdir -p .build.clang++ && cd .build.clang++ && CXX=clang++ cmake .. -DCMAKE_BUILD_TYPE=Debug && cmake --build . $CMT && ctest --parallel 2 --output-on-failure $CTR) || exit 666
(mkdir -p .build.clang++.libcpp && cd .build.clang++.libcpp && CXX=clang++ cmake .. -DCMAKE_BUILD_TYPE=Debug -DCMAKE_CXX_STANDARD=20 -DCMAKE_CXX_FLAGS="-stdlib=libc++" && cmake --build . $CMT && ctest --parallel 2 --output-on-failure $CTR) || exit 666
(mkdir -p .build.g++-rel && cd .build.g++-rel && CXX=g++ cmake .. -DCMAKE_BUILD_TYPE=Release && cmake --build . $CMT && ctest --parallel 2 --output-on-failure $CTR) || exit 666
#(mkdir -p .build.g++.m32 && cd .build.g++.m32 && CXX=g++ CXXFLAGS="-m32" cmake .. -DCMAKE_BUILD_TYPE=Debug && cmake --build . && ctest --parallel 2 --output-on-failure) || exit 666
(mkdir -p .build.g++.plus && cd .build.g++.plus && CXX=g++ cmake .. -DCMAKE_BUILD_TYPE=Release -DCMAKE_CXX_STANDARD=23 -DBLA_VENDOR=OpenBLAS `#-DCMAKE_CXX_CPPCHECK="cppcheck;--enable=all;--suppress=missingIncludeSystem;--inline-suppr;--std=c++17;--checkers-report=cppcheck.report;--error-exitcode=1"` -DCMAKE_CXX_FLAGS="-D_GLIBCXX_DEBUG=1" -DCMAKE_CXX_FLAGS="-fimplicit-constexpr -fanalyzer -Wno-analyzer-null-dereference -Wno-analyzer-possible-null-dereference -Wno-analyzer-malloc-leak -Wno-analyzer-use-of-uninitialized-value -Wno-analyzer-use-after-free" && cmake --build . $CMT && ctest --parallel --output-on-failure -T memcheck $CTR) || exit 666
(mkdir -p .build.clang++.plus && cd .build.clang++.plus && CXX=clang++ cmake .. -DCMAKE_BUILD_TYPE=Release -DCMAKE_CXX_STANDARD=20 -DBLA_VENDOR=Generic -DCMAKE_CXX_CLANG_TIDY="clang-tidy" `#-DCMAKE_CXX_INCLUDE_WHAT_YOU_USE="iwyu;-Xiwyu;--mapping_file=/home/correaa/boost-multi/.iwyu-test.imp;-Xiwyu;--no_fwd_decls"` && cmake --build . $CMT && ASAN_OPTIONS="new_delete_type_mismatch=0" ctest --parallel --output-on-failure $CTR) || exit 666
#(mkdir -p .build.hip && cd .build.hip && CXX=clang++ cmake .. -DCMAKE_BUILD_TYPE=Release -DCMAKE_HIP_COMPILER=/opt/rocm/llvm/bin/clang++ -DCMAKE_CXX_FLAGS="-DMULTI_USE_HIP" -DCMAKE_HIP_FLAGS="-DMULTI_USE_HIP" -DENABLE_HIP=1 -DCMAKE_HIP_ARCHITECTURES=gfx90a && cmake --build . ) || exit 666
#(mkdir -p .build.g++-.cov && cd .build.g++-.cov && CXX=g++ cmake .. -DCMAKE_BUILD_TYPE=Debug -DCMAKE_CXX_FLAGS="--coverage -lgcov -fno-inline -fno-inline-small-functions -fno-default-inline" -DCMAKE_EXE_LINKER_FLAGS="-lgcov --coverage" && cmake --build . && ASAN_OPTIONS="new_delete_type_mismatch=0" ctest -j 12 --output-on-failure -T Test `# && lcov --directory . --capture --output-file coverage.info && lcov --remove coverage.info '/usr/*' --output-file coverage.info && lcov --list coverage.info && genhtml coverage.info`) || exit 666

if [[ $(uname -m) != 'aarch64' ]]; then
(mkdir -p .build.circle && cd .build.circle && CXX="$HOME/bin/circle" cmake .. -DCMAKE_BUILD_TYPE=Debug -DCMAKE_CXX_STANDARD=20 -DDISABLE_MPI=1 -DCMAKE_CXX_EXTENSIONS=OFF -DENABLE_CIRCLE=1 -DCMAKE_THREAD_LIBS_INIT="-lpthread" && cmake --build . $CMT && ctest --parallel --output-on-failure $CTR) || exit 666
(mkdir -p .build.circle && cd .build.circle && CXX="$HOME/bin/circle" cmake .. -DCMAKE_BUILD_TYPE=Debug -DCMAKE_CXX_STANDARD=20 -DDISABLE_MPI=1 -DCMAKE_CXX_EXTENSIONS=OFF -DENABLE_CIRCLE=1 -DCMAKE_THREAD_LIBS_INIT="-lpthread" && cmake --build . $CMT && (ctest --parallel $CTR || ctest --rerun-failed --output-on-failure $CTR)) || exit 666
(mkdir -p .build.nvcc && cd .build.nvcc && cmake .. -DCMAKE_BUILD_TYPE=Release -DCMAKE_CXX_STANDARD=20 -DENABLE_CUDA=1 -DCMAKE_CUDA_COMPILER=nvcc -DCMAKE_CUDA_HOST_COMPILER=g++ -DCMAKE_CXX_COMPILER=g++ -DCMAKE_CUDA_ARCHITECTURES=75 && cmake --build . $CMT && ctest --parallel --output-on-failure $CTR) || exit 666
(mkdir -p .build.icpx && cd .build.icpx && CXX=/opt/intel/oneapi/compiler/latest/bin/icpx cmake .. -DCMAKE_BUILD_TYPE=Release -DCMAKE_CXX_STANDARD=23 && cmake --build . $CMT && ctest --parallel --output-on-failure $CTR) || exit 666
(mkdir -p .build.nvc++ && cd .build.nvc++ && CXX=/opt/nvidia/hpc_sdk/Linux_x86_64/2024/compilers/bin/nvc++ cmake .. -DCMAKE_BUILD_TYPE=Release -DCMAKE_CXX_FLAGS="-stdpar=multicore" -DBLA_PREFER_PKGCONFIG=ON-DCMAKE_CXX_COMPILER=/opt/nvidia/hpc_sdk/Linux_x86_64/2024/compilers/bin/nvc++ && cmake --build . $CMT && ctest --parallel --output-on-failure $CTR) || exit 666
Expand All @@ -71,7 +71,7 @@ else
# brew install boost ccache clang-tidy cmake cppcheck cpplint ninja
# ln -s "$(brew --prefix llvm)/bin/clang-tidy" "/usr/local/bin/clang-tidy"
#(mkdir -p .build.g++-14 && cd .build.g++-14 && CXX=g++-14 cmake .. -DCMAKE_BUILD_TYPE=Debug -DCMAKE_CXX_STANDARD=23 && cmake --build . $CMT && ctest -j 12 --output-on-failure $CTR) || exit 666
(mkdir -p .build.c++.std23 && cd .build.c++.std23 && CXX=c++ CXXFLAGS="-fexperimental-library" cmake .. -DCMAKE_EXPORT_COMPILE_COMMANDS=ON -DCMAKE_BUILD_TYPE=Release -DCMAKE_CXX_STANDARD=23 && cmake --build . $CMT && ctest -j 12 --output-on-failure $CTR) || exit 666
(mkdir -p .build.c++.std23 && cd .build.c++.std23 && CXX=c++ CXXFLAGS="-fexperimental-library" cmake .. -DCMAKE_EXPORT_COMPILE_COMMANDS=ON -DCMAKE_BUILD_TYPE=Release -DCMAKE_CXX_STANDARD=23 && cmake --build . $CMT && (ctest --parallel $CTR || ctest --rerun-failed --output-on-failure $CTR) ) || exit 666
#(mkdir -p .build.mull && cd .build.mull && CXX=c++ CXXFLAGS="-O1 -fpass-plugin=~/bin/mull-ir-frontend-16 -g -grecord-command-line -fprofile-instr-generate -fcoverage-mapping" cmake .. && cmake --build . $CMT && (ls *.x | xargs -n 1 sh -c 'echo $0 && ((~/bin/mull-runner-16 $0 -test-program=ctest -- -j2 --stop-on-failure) || exit 255)')) || exit 666
(mkdir -p .build.c++.asan && cd .build.c++.asan && CXX=c++ cmake .. -DCMAKE_BUILD_TYPE=Debug -DCMAKE_CXX_STANDARD=20 -DCMAKE_CXX_FLAGS="-D_LIBCPP_DEBUG=1 -fsanitize=undefined -fsanitize=pointer-overflow -fsanitize-trap=pointer-overflow -fsanitize=address -fno-omit-frame-pointer -fsanitize=signed-integer-overflow" && cmake --build . $CMT && ASAN_OPTIONS="new_delete_type_mismatch=1" ctest -j 12 --output-on-failure $CTR) || exit 666
(mkdir -p .build.c++.m32 && cd .build.c++.m32 && CXX=c++ cmake .. -DCMAKE_BUILD_TYPE=Debug && cmake --build . $CMT && ctest -j 12 --output-on-failure $CTR) || exit 666
Expand Down
1 change: 1 addition & 0 deletions test/Testing/Temporary/CTestCostData.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
---
3 changes: 3 additions & 0 deletions test/Testing/Temporary/LastTest.log
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
Start testing: Feb 14 08:19 PST
----------------------------------------------------------
End testing: Feb 14 08:19 PST
9 changes: 5 additions & 4 deletions test/allocator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,12 +23,12 @@

namespace multi = boost::multi;

template<class T, multi::dimensionality_type D, std::size_t Capacity = 4UL * 4UL>
using small_array = multi::static_array<T, D, multi::detail::static_allocator<T, Capacity>>;
// https://godbolt.org/z/d8ozWahna

#define BOOST_AUTO_TEST_CASE(CasenamE) /**/

template<class T, multi::dimensionality_type D, std::size_t Capacity = 256/sizeof(T)>
using small_array = multi::static_array<T, D, multi::detail::static_allocator<T[Capacity]>>; // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
// https://godbolt.org/z/d8ozWahna

auto main() -> int { // NOLINT(readability-function-cognitive-complexity,bugprone-exception-escape)
BOOST_AUTO_TEST_CASE(static_array_allocator) {
multi::array<int, 2> const ma({2, 3}, 99);
Expand Down Expand Up @@ -432,6 +432,7 @@ auto main() -> int { // NOLINT(readability-function-cognitive-complexity,bugpro

#if !defined(_MSC_VER) || (_MSC_VER > 193030706) // TODO(correaa) doesn't work on MSVC 14.3 in c++17 mode
BOOST_AUTO_TEST_CASE(small_array_int) {

small_array<int, 2, 4UL * 4UL> vv({4, 4}, 42);

BOOST_TEST( vv[3][3] == 42 );
Expand Down
6 changes: 4 additions & 2 deletions test/array_ref.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -265,8 +265,10 @@ BOOST_AUTO_TEST_CASE(array_ref_test_no_ub) {
BOOST_TEST(( arr2[1][1] == multi::array<int, 1>{7, 8} ));

BOOST_TEST(( arr2 == multi::array<int, 3>{
{{1, 2}, {3, 4}},
{{5, 6}, {7, 8}}
{{1, 2},
{3, 4}},
{{5, 6},
{7, 8}}
}));
}

Expand Down
49 changes: 48 additions & 1 deletion test/flatted.cpp
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright 2018-2024 Alfredo A. Correa
// Copyright 2018-2025 Alfredo A. Correa
// Copyright 2024 Matt Borland
// Distributed under the Boost Software License, Version 1.0.
// https://www.boost.org/LICENSE_1_0.txt
Expand All @@ -11,6 +11,53 @@ namespace multi = boost::multi;
#define BOOST_AUTO_TEST_CASE(CasenamE)

auto main() -> int { // NOLINT(readability-function-cognitive-complexity,bugprone-exception-escape)

// BOOST_AUTO_TEST_CASE(array_flattened_2d) {
// multi::array<int, 2> arr = {
// {0, 1, 2},
// {3, 4, 5},
// };

// auto bit = arr({0, 2}, {0, 2}).flattened_begin();

// BOOST_TEST( *bit == 0 );

// ++bit; BOOST_TEST( *bit == 1 );
// ++bit; BOOST_TEST( *bit == 3 );
// ++bit; BOOST_TEST( *bit == 4 );
// ++bit;

// --bit; BOOST_TEST( *bit == 4 );
// --bit; BOOST_TEST( *bit == 3 );
// --bit; BOOST_TEST( *bit == 1 );
// --bit; BOOST_TEST( *bit == 0 );
// }

BOOST_AUTO_TEST_CASE(array_flattened_4d) {
multi::array<int, 4> arr = {
{
{{0, 0}, {0, 0}}, {{1, 1}, {1, 1}}, {{2, 2}, {2, 2}}
},
{ {{3, 3}, {3, 3}}, {{4, 4}, {4, 4}}, {{5, 5}, {5, 5}}
}
};

auto bit = arr({0, 2}, {0, 2}).flattened_begin();

BOOST_TEST(( *bit == multi::array<int, 2>({{0, 0}, {0, 0}}) ));

++bit; BOOST_TEST(( *bit == multi::array<int, 2>({{1, 1}, {1, 1}}) ));
++bit; BOOST_TEST(( *bit == multi::array<int, 2>({{3, 3}, {3, 3}}) ));
++bit; BOOST_TEST(( *bit == multi::array<int, 2>({{4, 4}, {4, 4}}) ));

++bit;

--bit; BOOST_TEST(( *bit == multi::array<int, 2>({{4, 4}, {4, 4}}) ));
--bit; BOOST_TEST(( *bit == multi::array<int, 2>({{3, 3}, {3, 3}}) ));
--bit; BOOST_TEST(( *bit == multi::array<int, 2>({{1, 1}, {1, 1}}) ));
--bit; BOOST_TEST(( *bit == multi::array<int, 2>({{0, 0}, {0, 0}}) ));
}

BOOST_AUTO_TEST_CASE(array_flatted_2d) {
multi::array<int, 2> arr = {
{0, 1, 2},
Expand Down
2 changes: 1 addition & 1 deletion test/partitioned.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ auto main() -> int { // NOLINT(readability-function-cognitive-complexity,bugpro
{13, 14, 15, 16}
}));

BOOST_TEST(( arr.halved().extensions() == multi::extensions_t{2, 2, 4} ));
BOOST_TEST(( arr.halved().extensions() == multi::extensions_t{2, 2, 4} ));
BOOST_TEST(( arr.halved() == multi::array<int, 3>{
{
{ 1, 2, 3, 4},
Expand Down

0 comments on commit 0866c03

Please sign in to comment.