File: mdspantest.cc

package info (click to toggle)
dune-common 2.11.0-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 6,048 kB
  • sloc: cpp: 54,403; python: 4,136; sh: 1,657; makefile: 17
file content (135 lines) | stat: -rw-r--r-- 4,615 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
// vi: set et ts=4 sw=2 sts=2:
// SPDX-FileCopyrightInfo: Copyright © DUNE Project contributors, see file LICENSE.md in module root
// SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception
#include <config.h>

#include <array>
#include <type_traits>
#include <vector>

#include <dune/common/test/testsuite.hh>
#include <dune/common/std/default_accessor.hh>
#include <dune/common/std/extents.hh>
#include <dune/common/std/layout_left.hh>
#include <dune/common/std/layout_right.hh>
#include <dune/common/std/mdspan.hh>

template <class Tensor>
void checkAccess(Dune::TestSuite& testSuite, Tensor tensor)
{
  Dune::TestSuite subTestSuite("checkAccess");

  if constexpr(Tensor::rank() == 0) {
    subTestSuite.check(tensor[std::array<int,0>{}] == 42.0);
#if __cpp_multidimensional_subscript >= 202110L
    subTestSuite.check(tensor[] == 42.0);
#endif
  }
  else if constexpr(Tensor::rank() == 1) {
    for (int i = 0; i < tensor.extent(0); ++i) {
      subTestSuite.check(tensor[std::array{i}] == 42.0);
      subTestSuite.check(tensor[i] == 42.0);
    }
  }
  else if constexpr(Tensor::rank() == 2) {
    for (int i = 0; i < tensor.extent(0); ++i) {
      for (int j = 0; j < tensor.extent(1); ++j) {
        subTestSuite.check(tensor[std::array{i,j}] == 42.0);
#if __cpp_multidimensional_subscript >= 202110L
        subTestSuite.check(tensor[i,j] == 42.0);
#endif
      }
    }
  }
  else if constexpr(Tensor::rank() == 3) {
    for (int i = 0; i < tensor.extent(0); ++i) {
      for (int j = 0; j < tensor.extent(1); ++j) {
        for (int k = 0; k < tensor.extent(2); ++k) {
          subTestSuite.check(tensor[std::array{i,j,k}] == 42.0);
#if __cpp_multidimensional_subscript >= 202110L
          subTestSuite.check(tensor[i,j,k] == 42.0);
#endif
        }
      }
    }
  }

  testSuite.subTest(subTestSuite);
}

template <class A, class M>
void test_accessor (Dune::TestSuite& testSuite, std::string name, const M& mapping)
{
  Dune::TestSuite subTestSuite(name);
  using Span = Dune::Std::mdspan<typename A::element_type, typename M::extents_type, typename M::layout_type, A>;

  std::vector<double> coefficients(mapping.required_span_size(), 42.0);
  auto dh = coefficients.data();

  // construction
  if constexpr(Span::rank() == 0 || Span::rank_dynamic() == 0)
    Span span1{dh};
  Span span2{dh, mapping.extents()};
  Span span3{dh, mapping};
  Span span4{dh, mapping, A{}};

  // construction with explicitly listed extents
  const typename M::extents_type& e = mapping.extents();
  if constexpr(Span::rank() == 1)
    Span span5{dh, e.extent(0)};
  else if constexpr(Span::rank() == 2)
    Span span5{dh, e.extent(0), e.extent(1)};
  else if constexpr(Span::rank() == 3)
    Span span5{dh, e.extent(0), e.extent(1), e.extent(2)};

  // converting constructor
  using OtherExtents = Dune::Std::dextents<std::size_t, Span::rank()>;
  using OtherSpan = Dune::Std::mdspan<typename A::element_type, OtherExtents, typename M::layout_type, A>;
  OtherSpan otherSpan(span4);

  checkAccess(subTestSuite, span2);
  testSuite.subTest(subTestSuite);
}


template <class L, class E>
void test_layout (Dune::TestSuite& testSuite, std::string name, const E& extent)
{
  using Mapping = typename L::template mapping<E>;
  Mapping mapping(extent);

  Dune::TestSuite subTestSuite(name);
  test_accessor<Dune::Std::default_accessor<double>>(subTestSuite, "default_accessor<double>", mapping);
  test_accessor<Dune::Std::default_accessor<const double>>(subTestSuite, "default_accessor<const double>", mapping);
  testSuite.subTest(subTestSuite);
}


template <class E, class... Args>
void test_extents (Dune::TestSuite& testSuite, std::string name, Args&&... args)
{
  E extent{std::forward<Args>(args)...};

  Dune::TestSuite subTestSuite(name);
  test_layout<Dune::Std::layout_left>(subTestSuite, "layout_left", extent);
  test_layout<Dune::Std::layout_right>(subTestSuite, "layout_right", extent);
  testSuite.subTest(subTestSuite);
}

int main(int argc, char** argv)
{
  Dune::TestSuite testSuite;

  // definition of some extents
  test_extents<Dune::Std::extents<int>>(testSuite, "rank=0");
  test_extents<Dune::Std::extents<int,7>>(testSuite, "rank=1");
  test_extents<Dune::Std::extents<int,7,7>>(testSuite, "rank=2");
  test_extents<Dune::Std::extents<int,7,7,7>>(testSuite, "rank=3");

  test_extents<Dune::Std::dextents<int,1>>(testSuite, "rank=1", 7);
  test_extents<Dune::Std::dextents<int,2>>(testSuite, "rank=2", 7,7);
  test_extents<Dune::Std::dextents<int,3>>(testSuite, "rank=3", 7,7,7);

  return testSuite.exit();
}