ESPResSo
Extensible Simulation Package for Research on Soft Matter Systems
Loading...
Searching...
No Matches
Array.hpp
Go to the documentation of this file.
1/*
2 * Copyright (C) 2010-2026 The ESPResSo project
3 *
4 * This file is part of ESPResSo.
5 *
6 * ESPResSo is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, either version 3 of the License, or
9 * (at your option) any later version.
10 *
11 * ESPResSo is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program. If not, see <http://www.gnu.org/licenses/>.
18 */
19
20#pragma once
21
22/**
23 * @file
24 *
25 * @brief Array implementation with CUDA support.
26 */
27
28#include "device_qualifier.hpp"
30
31#include <boost/serialization/access.hpp>
32
33#include <cassert>
34#include <cstddef>
35#include <iterator>
36#include <ostream>
37#include <stdexcept>
38#include <tuple>
39#include <type_traits>
40#include <utility>
41
42namespace Utils {
43namespace detail {
44
45template <typename T, std::size_t N> struct Storage {
46 T m_data[N] = {};
47
48private:
49 friend boost::serialization::access;
50 template <typename Archive>
51 void serialize(Archive &ar, const unsigned int /* version */) {
52 ar & m_data;
53 }
54};
55
56template <typename T> struct Storage<T, 0> {};
57
58struct ArrayFormatterStream {
59 std::ostream &stream;
60 char const *separator;
61 ArrayFormatterStream(std::ostream &s, char const *sep)
62 : stream(s), separator(sep) {}
63};
65struct ArrayFormatter {
66 char const *separator;
67 friend ArrayFormatterStream operator<<(std::ostream &os,
68 ArrayFormatter const &fmt) {
69 return {os, fmt.separator};
70 }
71};
73/**
74 * @brief Alias to create prvalue C-style arrays.
75 *
76 * This type is necessary when converting arrays from one type to another type
77 * within functions marked as @c noexcept. The @c std::initializer_list<T>
78 * type doesn't include the backing array length as part of the type,
79 * and is therefore not strictly equivalent.
80 */
81template <typename T, std::size_t N> using carray_alias = T const[N];
82
83} // namespace detail
84
85template <typename T, std::size_t N> struct Array {
86 using value_type = T;
87 using size_type = std::size_t;
88 using difference_type = std::ptrdiff_t;
90 using const_reference = const value_type &;
92 using const_iterator = const value_type *;
94 using const_pointer = const value_type *;
95
96 detail::Storage<T, N> m_storage;
97
99 if (i >= N) {
100 DEVICE_THROW(std::out_of_range("Array access out of bounds."));
101 }
102 return m_storage.m_data[i];
103 }
104
106 if (i >= N) {
107 DEVICE_THROW(std::out_of_range("Array access out of bounds."));
108 }
109 return m_storage.m_data[i];
110 }
111
113 DEVICE_ASSERT(i < N);
114 return m_storage.m_data[i];
115 }
116
118 operator[](size_type i) const noexcept {
119 DEVICE_ASSERT(i < N);
120 return m_storage.m_data[i];
121 }
122
123 DEVICE_QUALIFIER constexpr reference front() { return *begin(); }
124
125 DEVICE_QUALIFIER constexpr const_reference front() const { return *cbegin(); }
126
127 DEVICE_QUALIFIER constexpr reference back() { return *(end() - 1); }
128
130 return *(cend() - 1);
131 }
132
134 return &m_storage.m_data[0];
135 }
136
138 return &m_storage.m_data[0];
139 }
140
142 return &m_storage.m_data[0];
143 }
144
146 return &m_storage.m_data[0];
147 }
148
150 return &m_storage.m_data[0];
151 }
152
154 return &m_storage.m_data[N];
155 }
156
158 return &m_storage.m_data[N];
159 }
160
162 return &m_storage.m_data[N];
163 }
164
165 DEVICE_QUALIFIER constexpr bool empty() const noexcept { return size() == 0; }
166
168
170
171 DEVICE_QUALIFIER void fill(const value_type &value) {
172 for (size_type i = 0; i != size(); ++i) {
173 m_storage.m_data[i] = value;
174 }
175 }
176
177 static constexpr detail::ArrayFormatter formatter(char const *sep = " ") {
178 return {sep};
179 }
180
181private:
182 friend boost::serialization::access;
183 template <typename Archive>
184 void serialize(Archive &ar, const unsigned int /* version */) {
185 ar & m_storage;
186 }
187
188 static std::ostream &format(std::ostream &out, Array const &a,
189 char const *const sep) {
190 if (not a.empty())
191 out << a[0];
192
193 for (auto it = std::next(a.begin()); it != a.end(); ++it)
194 out << sep << *it;
195
196 return out;
197 }
198
199 friend std::ostream &operator<<(std::ostream &out, Array const &a) {
200 return format(out, a, ", ");
201 }
202
203 friend std::ostream &operator<<(detail::ArrayFormatterStream const &fmt,
204 Array const &a) {
205 return format(fmt.stream, a, fmt.separator);
206 }
207};
208
209template <std::size_t I, class T, std::size_t N>
210T &get(Array<T, N> &a) noexcept {
211 return a[I];
212}
213
214template <std::size_t I, class T, std::size_t N>
215T const &get(Array<T, N> const &a) noexcept {
216 return a[I];
217}
218
219} // namespace Utils
220
221template <std::size_t I, class T, std::size_t N>
222struct std::tuple_element<I, Utils::Array<T, N>> {
223 static_assert(I < N, "Utils::Array index must be in range");
224 using type = T;
225};
226
227template <class T, std::size_t N>
228struct std::tuple_size<Utils::Array<T, N>>
229 : std::integral_constant<std::size_t, N> {};
230
231UTILS_ARRAY_BOOST_MPI_T(Utils::detail::Storage, N)
232UTILS_ARRAY_BOOST_BIT_S(Utils::detail::Storage, N)
233UTILS_ARRAY_BOOST_CLASS(Utils::detail::Storage, N, object_serializable)
234UTILS_ARRAY_BOOST_TRACK(Utils::detail::Storage, N, track_never)
#define UTILS_ARRAY_BOOST_MPI_T(Container, N)
Mark array types as MPI data types.
Definition array.hpp:50
#define UTILS_ARRAY_BOOST_BIT_S(Container, N)
Mark array types as MPI bitwise serializable.
Definition array.hpp:63
#define UTILS_ARRAY_BOOST_CLASS(Container, N, ImplementationLevel)
Redefinition of BOOST_CLASS_IMPLEMENTATION for array types.
Definition array.hpp:78
#define UTILS_ARRAY_BOOST_TRACK(Container, N, TrackingLevel)
Redefinition of BOOST_CLASS_TRACKING for array types.
Definition array.hpp:97
cudaStream_t stream[1]
CUDA streams for parallel computing on CPU and GPU.
#define DEVICE_ASSERT(A)
#define DEVICE_QUALIFIER
#define DEVICE_THROW(E)
T & get(Array< T, N > &a) noexcept
Definition Array.hpp:210
void serialize(Archive &ar, std::tuple< T... > &pack, unsigned int const)
Serialize std::tuple.
DEVICE_QUALIFIER constexpr const_reference operator[](size_type i) const noexcept
Definition Array.hpp:118
DEVICE_QUALIFIER constexpr reference at(size_type i)
Definition Array.hpp:98
value_type * iterator
Definition Array.hpp:91
static constexpr detail::ArrayFormatter formatter(char const *sep=" ")
Definition Array.hpp:177
DEVICE_QUALIFIER constexpr bool empty() const noexcept
Definition Array.hpp:165
DEVICE_QUALIFIER constexpr reference back()
Definition Array.hpp:127
value_type * pointer
Definition Array.hpp:93
DEVICE_QUALIFIER constexpr pointer data() noexcept
Definition Array.hpp:133
DEVICE_QUALIFIER constexpr const_reference front() const
Definition Array.hpp:125
DEVICE_QUALIFIER constexpr const_reference at(size_type i) const
Definition Array.hpp:105
DEVICE_QUALIFIER constexpr size_type max_size() const noexcept
Definition Array.hpp:169
DEVICE_QUALIFIER constexpr iterator begin() noexcept
Definition Array.hpp:141
DEVICE_QUALIFIER constexpr const_pointer data() const noexcept
Definition Array.hpp:137
DEVICE_QUALIFIER constexpr const_iterator cbegin() const noexcept
Definition Array.hpp:149
const value_type & const_reference
Definition Array.hpp:90
detail::Storage< T, N > m_storage
Definition Array.hpp:96
DEVICE_QUALIFIER constexpr reference operator[](size_type i) noexcept
Definition Array.hpp:112
friend std::ostream & operator<<(std::ostream &out, Array const &a)
Definition Array.hpp:199
DEVICE_QUALIFIER constexpr const_iterator cend() const noexcept
Definition Array.hpp:161
DEVICE_QUALIFIER constexpr size_type size() const noexcept
Definition Array.hpp:167
DEVICE_QUALIFIER constexpr reference front()
Definition Array.hpp:123
const value_type * const_pointer
Definition Array.hpp:94
DEVICE_QUALIFIER constexpr const_reference back() const
Definition Array.hpp:129
friend std::ostream & operator<<(detail::ArrayFormatterStream const &fmt, Array const &a)
Definition Array.hpp:203
DEVICE_QUALIFIER constexpr iterator end() noexcept
Definition Array.hpp:153
DEVICE_QUALIFIER void fill(const value_type &value)
Definition Array.hpp:171
const value_type * const_iterator
Definition Array.hpp:92
DEVICE_QUALIFIER constexpr const_iterator begin() const noexcept
Definition Array.hpp:145
std::size_t size_type
Definition Array.hpp:87
DEVICE_QUALIFIER constexpr const_iterator end() const noexcept
Definition Array.hpp:157
value_type & reference
Definition Array.hpp:89
std::ptrdiff_t difference_type
Definition Array.hpp:88