Skip to content

Commit

Permalink
Merge branch 'halve' into 'master'
Browse files Browse the repository at this point in the history
test for halved operation

See merge request correaa/boost-multi!1352
  • Loading branch information
correaa committed Feb 12, 2025
2 parents 4560fe4 + 830e94a commit b323270
Show file tree
Hide file tree
Showing 6 changed files with 450 additions and 138 deletions.
27 changes: 20 additions & 7 deletions include/boost/multi/array_ref.hpp
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
// Distributed under the Boost Software License, Version 1.0.
// https://www.boost.org/LICENSE_1_0.txt

Expand Down Expand Up @@ -1192,12 +1192,7 @@ struct const_subarray : array_types<T, D, ElementPtr, Layout> {
private:
constexpr auto taked_aux_(difference_type n) const {
assert( n <= this->size() );
typename types::layout_t const new_layout(
this->layout().sub(),
this->layout().stride(),
this->layout().offset(),
this->stride()*n
);
auto const new_layout = this->layout().take(n);
return const_subarray(new_layout, this->base_);
}

Expand All @@ -1206,6 +1201,15 @@ struct const_subarray : array_types<T, D, ElementPtr, Layout> {
// constexpr auto taked(difference_type n) && -> const_subarray { return taked_aux_(n); }
// constexpr auto taked(difference_type n) & -> const_subarray { return taked_aux_(n); }

private:
BOOST_MULTI_HD constexpr auto halved_aux_() const {
auto new_layout = this->layout().halve();
return subarray<T, D + 1, element_ptr>(new_layout, this->base_);
}

public:
BOOST_MULTI_HD constexpr auto halved() const& -> const_subarray<T, D + 1, element_ptr> {return halved_aux_();}

private:
constexpr auto dropped_aux_(difference_type n) const {
assert( n <= this->size() );
Expand Down Expand Up @@ -2972,6 +2976,15 @@ struct const_subarray<T, 1, ElementPtr, Layout> // NOLINT(fuchsia-multiple-inhe
BOOST_MULTI_HD constexpr auto operator()(Args&&... args) const&
->decltype(paren_(*this, std::forward<Args>(args)...)) {
return paren_(*this, std::forward<Args>(args)...); }

private:
BOOST_MULTI_HD constexpr auto halved_aux_() const {
auto new_layout = this->layout().halve();
return subarray<T, 2, element_ptr>(new_layout, this->base_);
}

public:
BOOST_MULTI_HD constexpr auto halved() const& -> const_subarray<T, 2, element_ptr> {return halved_aux_();}

private:
BOOST_MULTI_HD constexpr auto partitioned_aux_(size_type size) const {
Expand Down
2 changes: 1 addition & 1 deletion include/boost/multi/detail/implicit_cast.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
#include <type_traits>
#include <utility>

namespace boost::multi::detail {
namespace boost::multi::detail { // this library requires C++17 and above !!!

template<class From, class To> constexpr bool is_implicitly_convertible_v = std::is_convertible_v<From, To>; // this library needs C++17 or higher (e.g. -std=c++17)
template<class From, class To> constexpr bool is_explicitly_convertible_v = std::is_constructible_v<To, From>;
Expand Down
283 changes: 154 additions & 129 deletions include/boost/multi/detail/layout.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -556,132 +556,6 @@ class contiguous_stride_t {
#endif
};

template<typename SSize>
struct layout_t<0, SSize>
: multi::equality_comparable<layout_t<0, SSize> >
{
using dimensionality_type = multi::dimensionality_type;
using rank = std::integral_constant<dimensionality_type, 0>;

using size_type = SSize;
using difference_type = std::make_signed_t<size_type>;
using index = difference_type;
using index_extension = multi::index_extension;
using index_range = multi::range<index>;

using sub_type = monostate;
using stride_type = monostate;
using offset_type = index;
using nelems_type = index;

using strides_type = tuple<>;
using offsets_type = tuple<>;
using nelemss_type = tuple<>;

using extension_type = void;

using extensions_type = extensions_t<rank::value>;
using sizes_type = tuple<>;

static constexpr dimensionality_type rank_v = rank::value;
static constexpr dimensionality_type dimensionality = rank_v; // TODO(correaa) : consider deprecation

friend constexpr auto dimensionality(layout_t const& /*self*/) {return rank_v;}

private:
#if defined(__clang__)
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wpadded"
#endif
BOOST_MULTI_NO_UNIQUE_ADDRESS sub_type sub_ ;
BOOST_MULTI_NO_UNIQUE_ADDRESS stride_type stride_; // TODO(correaa) padding struct 'boost::multi::layout_t<0>' with 1 byte to align 'stride_' [-Werror,-Wpadded]

offset_type offset_;

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

nelems_type nelems_;

template<dimensionality_type, typename> friend struct layout_t;

public:
layout_t() = default;

BOOST_MULTI_HD constexpr explicit layout_t(extensions_type const& /*nil*/)
: offset_{0}, nelems_{1} {}

// BOOST_MULTI_HD constexpr explicit layout_t(extensions_type const& /*nil*/, strides_type const& /*nil*/) {}

BOOST_MULTI_HD constexpr layout_t(sub_type sub, stride_type stride, offset_type offset, nelems_type nelems) // NOLINT(bugprone-easily-swappable-parameters)
: sub_{sub}, stride_{stride}, offset_{offset}, nelems_{nelems} {}

[[nodiscard]] constexpr auto extensions() const {return extensions_type{};}
friend constexpr auto extensions(layout_t const& self) {return self.extensions();}

[[nodiscard]] constexpr auto num_elements() const {return nelems_;}
friend constexpr auto num_elements(layout_t const& self) {return self.num_elements();}

[[nodiscard]] constexpr auto sizes() const {return tuple<>{};}
friend constexpr auto sizes(layout_t const& self) {return self.sizes();}

[[nodiscard]] constexpr auto strides() const {return strides_type{};}
[[nodiscard]] constexpr auto offsets() const {return offsets_type{};}
[[nodiscard]] constexpr auto nelemss() const {return nelemss_type{};}

constexpr auto operator()() const { return offset_; }
// constexpr explicit operator offset_type() const {return offset_;}

constexpr auto stride() const -> stride_type = delete;
constexpr auto offset() const -> offset_type {return offset_;}
constexpr auto nelems() const -> nelems_type {return nelems_;}
constexpr auto sub() const -> sub_type = delete;

constexpr auto size() const -> size_type = delete;
constexpr auto extension() const -> extension_type = delete;

constexpr auto is_empty() const noexcept {return nelems_ == 0;}
[[nodiscard/*for c++20 ("empty checks for emptyness")*/]]
constexpr auto empty() const noexcept {return nelems_ == 0;}
friend
constexpr auto empty(layout_t const& self) noexcept {return self.empty();}

[[deprecated("is going to be removed")]]
constexpr auto is_compact() const -> bool = delete;

constexpr auto base_size() const -> size_type {return 0;}
constexpr auto origin() const -> offset_type {return 0;}

constexpr auto reverse() -> layout_t& {return *this;}
// [[deprecated("use two arg version")]] constexpr auto scale(size_type /*size*/) const {return *this;}
constexpr auto scale(size_type /*num*/, size_type /*den*/) const {return *this;}

// friend constexpr auto operator!=(layout_t const& self, layout_t const& other) {return not(self == other);}
friend BOOST_MULTI_HD constexpr auto operator==(layout_t const& self, layout_t const& other) {
return
std::tie(self .sub_, self .stride_, self .offset_, self .nelems_)
== std::tie(other.sub_, other.stride_, other.offset_, other.nelems_)
;
}

friend BOOST_MULTI_HD constexpr auto operator!=(layout_t const& self, layout_t const& other) {
return
std::tie(self .sub_, self .stride_, self .offset_, self .nelems_)
!= std::tie(other.sub_, other.stride_, other.offset_, other.nelems_)
;
}

constexpr auto operator< (layout_t const& other) const -> bool {
return std::tie(offset_, nelems_) < std::tie(other.offset_, other.nelems_);
}

constexpr auto rotate() -> layout_t& {return *this;}
constexpr auto unrotate() -> layout_t& {return *this;}

constexpr auto hull_size() const -> size_type {return num_elements();} // not in bytes
};

template<typename SSize = multi::index>
class contiguous_layout {

Expand Down Expand Up @@ -785,8 +659,6 @@ class contiguous_layout {
this->nelems() / this->size() * (last - first)
};
}


};

template<dimensionality_type D, typename SSize>
Expand Down Expand Up @@ -1034,7 +906,6 @@ struct layout_t

template<typename Size>
constexpr auto partition(Size const& count) -> layout_t& {
using std::swap;
stride_ *= count;
nelems_ *= count;
sub_.partition(count);
Expand Down Expand Up @@ -1079,6 +950,25 @@ struct layout_t
#pragma clang diagnostic ignored "-Wlarge-by-value-copy" // TODO(correaa) use checked span
#endif

auto take(size_type n) const {
return layout_t(
this->sub(),
this->stride(),
this->offset(),
this->stride()*n
);
}

BOOST_MULTI_HD constexpr auto halve() const {
assert(this->size()%2 == 0);
return layout_t<D + 1>(
this->take(this->size()/2),
this->nelems()/2,
0,
this->nelems()
);
}

constexpr auto scale(size_type num, size_type den) const {
assert( (stride_*num) % den == 0 );
assert(offset_ == 0); // TODO(correaa) implement ----------------vvv
Expand All @@ -1090,6 +980,141 @@ struct layout_t
#endif
};

template<typename SSize>
struct layout_t<0, SSize>
: multi::equality_comparable<layout_t<0, SSize> >
{
using dimensionality_type = multi::dimensionality_type;
using rank = std::integral_constant<dimensionality_type, 0>;

using size_type = SSize;
using difference_type = std::make_signed_t<size_type>;
using index = difference_type;
using index_extension = multi::index_extension;
using index_range = multi::range<index>;

using sub_type = monostate;
using stride_type = monostate;
using offset_type = index;
using nelems_type = index;

using strides_type = tuple<>;
using offsets_type = tuple<>;
using nelemss_type = tuple<>;

using extension_type = void;

using extensions_type = extensions_t<rank::value>;
using sizes_type = tuple<>;

static constexpr dimensionality_type rank_v = rank::value;
static constexpr dimensionality_type dimensionality = rank_v; // TODO(correaa) : consider deprecation

friend constexpr auto dimensionality(layout_t const& /*self*/) {return rank_v;}

private:
#if defined(__clang__)
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wpadded"
#endif
BOOST_MULTI_NO_UNIQUE_ADDRESS sub_type sub_ ;
BOOST_MULTI_NO_UNIQUE_ADDRESS stride_type stride_; // TODO(correaa) padding struct 'boost::multi::layout_t<0>' with 1 byte to align 'stride_' [-Werror,-Wpadded]

offset_type offset_;

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

nelems_type nelems_;

template<dimensionality_type, typename> friend struct layout_t;

public:
layout_t() = default;

BOOST_MULTI_HD constexpr explicit layout_t(extensions_type const& /*nil*/)
: offset_{0}, nelems_{1} {}

// BOOST_MULTI_HD constexpr explicit layout_t(extensions_type const& /*nil*/, strides_type const& /*nil*/) {}

BOOST_MULTI_HD constexpr layout_t(sub_type sub, stride_type stride, offset_type offset, nelems_type nelems) // NOLINT(bugprone-easily-swappable-parameters)
: sub_{sub}, stride_{stride}, offset_{offset}, nelems_{nelems} {}

[[nodiscard]] constexpr auto extensions() const {return extensions_type{};}
friend constexpr auto extensions(layout_t const& self) {return self.extensions();}

[[nodiscard]] constexpr auto num_elements() const {return nelems_;}
friend constexpr auto num_elements(layout_t const& self) {return self.num_elements();}

[[nodiscard]] constexpr auto sizes() const {return tuple<>{};}
friend constexpr auto sizes(layout_t const& self) {return self.sizes();}

[[nodiscard]] constexpr auto strides() const {return strides_type{};}
[[nodiscard]] constexpr auto offsets() const {return offsets_type{};}
[[nodiscard]] constexpr auto nelemss() const {return nelemss_type{};}

constexpr auto operator()() const { return offset_; }
// constexpr explicit operator offset_type() const {return offset_;}

constexpr auto stride() const -> stride_type = delete;
constexpr auto offset() const -> offset_type {return offset_;}
constexpr auto nelems() const -> nelems_type {return nelems_;}
constexpr auto sub() const -> sub_type = delete;

constexpr auto size() const -> size_type = delete;
constexpr auto extension() const -> extension_type = delete;

constexpr auto is_empty() const noexcept {return nelems_ == 0;}
[[nodiscard/*for c++20 ("empty checks for emptyness")*/]]
constexpr auto empty() const noexcept {return nelems_ == 0;}
friend
constexpr auto empty(layout_t const& self) noexcept {return self.empty();}

[[deprecated("is going to be removed")]]
constexpr auto is_compact() const -> bool = delete;

constexpr auto base_size() const -> size_type {return 0;}
constexpr auto origin() const -> offset_type {return 0;}

constexpr auto reverse() -> layout_t& {return *this;}

BOOST_MULTI_HD constexpr auto take(size_type /*n*/) const {
return layout_t<0, SSize>{};
}

BOOST_MULTI_HD constexpr auto halve() const {
return layout_t<1, SSize>(*this, 0, 0, 0);
}

// [[deprecated("use two arg version")]] constexpr auto scale(size_type /*size*/) const {return *this;}
constexpr auto scale(size_type /*num*/, size_type /*den*/) const {return *this;}

// friend constexpr auto operator!=(layout_t const& self, layout_t const& other) {return not(self == other);}
friend BOOST_MULTI_HD constexpr auto operator==(layout_t const& self, layout_t const& other) {
return
std::tie(self .sub_, self .stride_, self .offset_, self .nelems_)
== std::tie(other.sub_, other.stride_, other.offset_, other.nelems_)
;
}

friend BOOST_MULTI_HD constexpr auto operator!=(layout_t const& self, layout_t const& other) {
return
std::tie(self .sub_, self .stride_, self .offset_, self .nelems_)
!= std::tie(other.sub_, other.stride_, other.offset_, other.nelems_)
;
}

constexpr auto operator< (layout_t const& other) const -> bool {
return std::tie(offset_, nelems_) < std::tie(other.offset_, other.nelems_);
}

constexpr auto rotate() -> layout_t& {return *this;}
constexpr auto unrotate() -> layout_t& {return *this;}

constexpr auto hull_size() const -> size_type {return num_elements();} // not in bytes
};

constexpr auto
operator*(layout_t<0>::index_extension const& extensions_0d, layout_t<0>::extensions_type const& /*zero*/)
-> typename layout_t<1>::extensions_type {
Expand Down
2 changes: 2 additions & 0 deletions pre-push
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,8 @@ fi
# sudo modprobe -r nvidia_uvm
# sudo modprobe nvidia_uvm
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.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
Expand Down
Loading

0 comments on commit b323270

Please sign in to comment.