Skip to content

Commit

Permalink
Merge branch 'master' into extensions-adl
Browse files Browse the repository at this point in the history
  • Loading branch information
correaa authored Oct 10, 2024
2 parents 5145ec5 + d314eba commit 85e937a
Show file tree
Hide file tree
Showing 7 changed files with 106 additions and 16 deletions.
2 changes: 1 addition & 1 deletion .gitlab-ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,7 @@ g++ cppcheck cpplint memcheck: # debian-stable: gcc 12 as of Dec 2023
- non-shared
- docker
script:
- apt-get -qq update && apt-get -qq install --no-install-recommends -y --quiet ca-certificates cmake cppcheck cpplint g++ make libboost-timer-dev libboost-serialization-dev libblas-dev libfftw3-dev liblapack-dev libopenmpi-dev pkg-config valgrind
- apt-get -qq update && apt-get -qq install --no-install-recommends -y --quiet ca-certificates cmake cppcheck cpplint g++ make libboost-timer-dev libboost-serialization-dev libblas-dev libfftw3-dev liblapack-dev libmpich-dev pkg-config valgrind
- g++ --version
- cpplint --version
- cppcheck --version
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
-->
# [Boost.] Multi

> **Disclosure: This is not an official or accepted Boost library and is unrelated to the std::mdspan proposal. It is in the process of being proposed for inclusion in Boost.**
> **Disclosure: This is not an official or accepted Boost library and is unrelated to the std::mdspan proposal. It is in the process of being proposed for inclusion in [Boost](https://www.boost.org/).**
_© Alfredo A. Correa, 2018-2024_

Expand Down
75 changes: 75 additions & 0 deletions examples/cai_1d_heat.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
///usr/bin/clang++ -std=c++23 $0 -I../include && ./a.out | gnuplot -persist; exit
#include <boost/multi/array.hpp>

#include <cmath> // for std::exp
#include <iostream>
#include <ranges>

namespace multi = boost::multi;
namespace stv = std::views;

void plot(auto const& x, auto const& f, std::string const& title = "") {
assert(x.size() == f.size());
std::cout << "set title '" << title << "'\n"
<< "plot '-' with linespoints\n";
for(auto i = 0; i < x.size(); ++i) {
std::cout << x[i] << " " << f[i] << "\n";
}
std::cout << 'e' << std::endl
<< "pause 0.1\n";
}

template<class Range, typename T>
auto append(Range const& range, T const& value) {
return stv::iota(typename Range::size_type{}, range.size() + 1) | stv::transform([&](auto i) -> decltype(auto) {return (i<range.size()-1)?range[i]:value;});
}

template<class Range, typename T>
auto prepend(Range const& range, T const& value) {
return stv::iota(typename Range::size_type{}, range.size() + 1) | stv::transform([&](auto i) -> decltype(auto) {return (i==0)?value:range[i-1];});
}

auto main() -> int {

using multi::operator+;

// dx = 0.2;
// x = [0:1:20]*dx;
// f = x.*exp(-x.^2);
// plot(x, f, 'ro');

auto dx = 0.2;
auto x = +(stv::iota(0, 20) | stv::transform([dx](auto i) { return i * dx; }));
auto f = +(x | stv::transform([](auto e) { return e * std::exp(-e * e); }));
plot(x, f);

// f_my_left = [NaN, f(1:end-1)];
// f_my_right = [f(2:end), NaN];
// d2f = (f_my_right - 2*f + f_my_left)/(dx^2);
auto f_my_left = +prepend(f.taked(f.size() - 1), NAN);
auto f_my_right = +append(f.dropped(1), NAN);
auto d2f = +stv::zip_transform([dx2 = dx * dx](auto r, auto m, auto l) { return (r - 2 * m + l) / dx2; }, f_my_right, f, f_my_left);

plot(x, d2f);

// dt = 0.01; D = 1;
// for k=1:100,
// f_my_left = [NaN, f(1:end-1)];
// f_my_right = [f(2:end), NaN];
// d2f = (f_my_right - 2*f + f_my_left)/(dx^2);
// f(2:end-1) = f(2:end-1) + D*dt*d2f(2:end-1);
// plot(x, f, 'ro-'); ylim([0 0.45]); drawnow
// pause(0.1)
// end

auto dt = 0.01;
auto D = 1.0;
for(auto k = 0; k != 100; ++k) {
f_my_left({1, f.size()}) = f.taked(f.size() - 1);
f_my_right({0, f.size() - 1}) = f.dropped(1);

d2f = stv::zip_transform([dx2 = dx * dx](auto r, auto m, auto l) { return (r - 2 * m + l) / dx2; }, f_my_right, f, f_my_left);
f({1, f.size() - 1}) = stv::zip_transform([dt, D, dx2 = dx * dx](auto eff, auto d2) { return eff + D * dt * d2; }, f({1, f.size() - 1}), d2f({1, f.size() - 1}));
plot(x, f, "k=" + std::to_string(k));
}
}
2 changes: 1 addition & 1 deletion include/boost/multi/adaptors/blas/gemm.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -210,7 +210,7 @@ class gemm_iterator {
using reference = gemm_reference<decltype((*b_begin_).extensions())>;
using iterator_category = std::random_access_iterator_tag;

static_assert( std::is_base_of<std::random_access_iterator_tag, typename std::iterator_traits<gemm_iterator>::iterator_category>{} );
// static_assert( std::is_base_of_v<std::random_access_iterator_tag, typename std::iterator_traits<gemm_iterator>::iterator_category> );

auto operator+=(difference_type n) -> gemm_iterator& {a_it_ += n; return *this;}
auto operator-=(difference_type n) -> gemm_iterator& {a_it_ -= n; return *this;}
Expand Down
12 changes: 6 additions & 6 deletions include/boost/multi/adaptors/blas/test/gemv.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -387,12 +387,12 @@ auto main() -> int { // NOLINT(readability-function-cognitive-complexity,bugpro
return array;
}(multi::array<complex, 2>({3, 3}));

using blas::operators::operator*;
using blas::operators::operator-;
using blas::operators::operator^;
BOOST_TEST( (((+(A*B))[0] - B[0])^2) == 0.0 );
BOOST_TEST( (((+(A*B))[1] - B[1])^2) == 0.0 );
BOOST_TEST( (((+(A*B))[2] - B[2])^2) == 0.0 );
// using blas::operators::operator*;
// using blas::operators::operator-;
// using blas::operators::operator^;
// BOOST_TEST( (((+(A*B))[0] - B[0])^2) == 0.0 );
// BOOST_TEST( (((+(A*B))[1] - B[1])^2) == 0.0 );
// BOOST_TEST( (((+(A*B))[2] - B[2])^2) == 0.0 );
}

BOOST_AUTO_TEST_CASE(multi_blas_gemv_context) {
Expand Down
18 changes: 16 additions & 2 deletions include/boost/multi/array.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -229,8 +229,8 @@ struct static_array // NOLINT(fuchsia-multiple-inheritance) : multiple inherita
template<class It, class = typename std::iterator_traits<std::decay_t<It>>::difference_type>
constexpr explicit static_array(It first, It last, allocator_type const& alloc)
: array_alloc{alloc}, ref{
array_alloc::allocate(static_cast<typename multi::allocator_traits<allocator_type>::size_type>(layout_type{index_extension{adl_distance(first, last)} * multi::extensions(*first)}.num_elements())),
index_extension{adl_distance(first, last)} * multi::extensions(*first)} {
array_alloc::allocate(static_cast<typename multi::allocator_traits<allocator_type>::size_type>(layout_type{index_extension(adl_distance(first, last)) * multi::extensions(*first)}.num_elements())),
index_extension(adl_distance(first, last)) * multi::extensions(*first)} {
#if defined(__clang__) && defined(__CUDACC__)
// TODO(correaa) add workaround for non-default constructible type and use adl_alloc_uninitialized_default_construct_n
if constexpr(! std::is_trivially_default_constructible_v<typename static_array::element_type> && ! multi::force_element_trivial_default_construction<typename static_array::element_type> ) {
Expand Down Expand Up @@ -1336,6 +1336,7 @@ struct array : static_array<T, D, Alloc> {
class Range,
class = decltype(std::declval<static_&>().operator=(std::declval<Range&&>())),
std::enable_if_t<!has_data_elements<std::decay_t<Range>>::value, int> = 0,
std::enable_if_t<has_extensions<std::decay_t<Range>>::value, int> = 0,
std::enable_if_t<!std::is_base_of<array, std::decay_t<Range>>{}, int> = 0> // NOLINT(modernize-use-constraints) TODO(correaa)
auto operator=(Range&& other) -> array& { // TODO(correaa) : check that LHS is not read-only?
if(array::extensions() == other.extensions()) {
Expand Down Expand Up @@ -1557,6 +1558,19 @@ array(MatrixRef) -> array<T, D, Alloc>;

template<typename T, dimensionality_type D, typename P> array(subarray<T, D, P>) -> array<T, D>;

template<
class Range,
std::enable_if_t<!has_extensions<Range>::value, int> = 0,
typename V = decltype(*::std::begin(std::declval<Range const&>()))
// typename V = typename std::iterator_traits<decltype(::std::begin(std::declval<Range const&>()))>::value_type
>
array(Range) -> array<V, 1>;

template<class Reference>
auto operator+(Reference&& ref)
->decltype(array(std::forward<Reference>(ref))) {
return array(std::forward<Reference>(ref)); }

#endif // ends defined(__cpp_deduction_guides)

template<class T, std::size_t N>
Expand Down
11 changes: 6 additions & 5 deletions include/boost/multi/detail/adl.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -459,13 +459,14 @@ auto alloc_uninitialized_fill_n(Alloc& alloc, ForwardIt first, Size n, T const&
} // end namespace xtd

class adl_distance_t {
template<class... As> constexpr auto _(priority<1>/**/, As&&... args) const BOOST_MULTI_DECLRETURN( std:: distance(std::forward<As>(args)...))
template<class... As> constexpr auto _(priority<2>/**/, As&&... args) const BOOST_MULTI_DECLRETURN( distance(std::forward<As>(args)...))
template<class T, class... As> constexpr auto _(priority<3>/**/, T&& arg, As&&... args) const BOOST_MULTI_DECLRETURN( std::decay_t<T>:: distance(std::forward<T>(arg), std::forward<As>(args)...))
template<class T, class... As> constexpr auto _(priority<4>/**/, T&& arg, As&&... args) const BOOST_MULTI_DECLRETURN(std::forward<T>(arg).distance(std::forward<As>(args)...))
template<class... As> constexpr auto _(priority<1>/**/, As&&... args) const BOOST_MULTI_DECLRETURN( std:: distance(std::forward<As>(args)...))
template<class... As> constexpr auto _(priority<2>/**/, As&&... args) const BOOST_MULTI_DECLRETURN( distance(std::forward<As>(args)...))
template<class It1, class It2> constexpr auto _(priority<3>/**/, It1 it1, It2 it2 ) const BOOST_MULTI_DECLRETURN(it2 - it1)
template<class T, class... As> constexpr auto _(priority<4>/**/, T&& arg, As&&... args) const BOOST_MULTI_DECLRETURN( std::decay_t<T>:: distance(std::forward<T>(arg), std::forward<As>(args)...))
template<class T, class... As> constexpr auto _(priority<5>/**/, T&& arg, As&&... args) const BOOST_MULTI_DECLRETURN(std::forward<T>(arg).distance(std::forward<As>(args)...))

public:
template<class... As> constexpr auto operator()(As&&... args) const BOOST_MULTI_DECLRETURN(_(priority<4>{}, std::forward<As>(args)...))
template<class... As> constexpr auto operator()(As&&... args) const BOOST_MULTI_DECLRETURN(_(priority<5>{}, std::forward<As>(args)...))
};
inline constexpr adl_distance_t adl_distance;

Expand Down

0 comments on commit 85e937a

Please sign in to comment.