29#include <boost/qvm/deduce_vec.hpp>
30#include <boost/qvm/vec_traits.hpp>
41#include <initializer_list>
51template <
typename T, std::
size_t N>
class Vector :
public Array<T, N> {
57 using Base::operator[];
70 template <
class U>
struct is_vector : std::false_type {};
71 template <
class U, std::
size_t Np>
78 void swap(
Vector &rhs) { std::ranges::swap_ranges(*
this, rhs); }
81 constexpr void copy_init(T
const *values)
noexcept {
82 for (std::size_t i{0}; i != N; ++i) {
83 (*this)[i] = values[i];
92 template <
class Range>
93 requires(not is_vector<std::remove_cvref_t<Range>>::value and
94 not std::is_same_v<std::remove_cvref_t<Range>, T[N]>)
95 explicit constexpr Vector(Range &&rng)
96 :
Vector(std::begin(rng), std::end(rng)) {}
98#if __cpp_lib_containers_ranges
99 template <std::ranges::input_range Range>
100 Vector(std::from_range_t, Range &&rng)
104 explicit constexpr Vector(T
const (&v)[N]) noexcept :
Base() {
105 if constexpr (N != 0) {
106 copy_init(std::cbegin(v));
114 throw std::length_error(
115 "Construction of Vector from Container of wrong length.");
117 if constexpr (N != 0) {
118 copy_init(v.begin());
122 template <
typename InputIterator>
124 if (std::distance(first, last) == N) {
125 std::copy_n(first, N,
begin());
127 throw std::length_error(
128 "Construction of Vector from Container of wrong length.");
136 for (std::size_t i = 0u; i != N; ++i) {
146 constexpr std::span<const T, N>
as_span() const noexcept {
147 return std::span<const T, N>(
begin(), N);
150 constexpr operator std::span<const T, N>() const noexcept {
157 std::ranges::transform(*
this, ret.
begin(),
158 [](T
const &e) { return static_cast<U>(e); });
163 constexpr T
norm2()
const {
return (*
this) * (*this); }
173 auto const l =
norm();
188 auto const l =
norm();
189 return (l != T(0)) ? (*this) / l : *
this;
209template <std::
size_t N,
typename T,
typename U,
typename Op>
214 using R =
decltype(std::declval<T>() + std::declval<U>());
218 std::transform(std::begin(a), std::end(a), std::begin(b), std::begin(ret),
225#define ESPRESSO_VECTOR_COMPARISON(op) \
226 template <std::size_t N, typename T> \
228 operator op(Vector<T, N> const &a, Vector<T, N> const &b) noexcept( \
229 noexcept(std::declval<T const &>() op std::declval<T const &>())) { \
230 for (std::size_t i = 0u; i < N; ++i) { \
231 if (not(a[i] op b[i])) { \
243#undef ESPRESSO_VECTOR_COMPARISON
245template <std::
size_t N,
typename T,
typename U>
247 return detail::binary_op(a, b, std::plus<>());
250template <std::
size_t N,
typename T>
253 std::ranges::transform(a, b, std::begin(a), std::plus<T>());
257template <std::
size_t N,
typename T,
typename U>
259 return detail::binary_op(a, b, std::minus<>());
262template <std::
size_t N,
typename T>
265 std::ranges::transform(a, std::begin(ret), std::negate<T>());
269template <std::
size_t N,
typename T>
272 std::ranges::transform(a, b, std::begin(a), std::minus<T>());
277template <std::
size_t N,
typename T,
class U>
278 requires(std::is_arithmetic_v<U>)
280 using R =
decltype(a * std::declval<T>());
282 std::ranges::transform(b, std::begin(ret), [a](T
const &v) {
return a * v; });
286template <std::
size_t N,
typename T,
class U>
287 requires(std::is_arithmetic_v<U>)
289 using R =
decltype(std::declval<T>() * b);
291 std::ranges::transform(a, std::begin(ret), [b](T
const &v) {
return b * v; });
295template <std::
size_t N,
typename T>
297 std::ranges::transform(b, std::begin(b), [a](T
const &v) {
return a * v; });
302template <std::
size_t N,
typename T,
class U>
304 using R =
decltype(std::declval<T>() / b);
306 std::ranges::transform(a, std::begin(ret), [b](T
const &v) {
return v / b; });
310template <std::
size_t N,
typename T,
class U>
312 using R =
decltype(a / std::declval<T>());
314 std::ranges::transform(b, std::begin(ret), [a](T
const &v) {
return a / v; });
318template <std::
size_t N,
typename T>
320 std::ranges::transform(a, std::begin(a), [b](T
const &v) {
return v / b; });
325template <
class T>
using is_vector = Vector<int, 1>::is_vector<T>;
329template <std::
size_t N,
typename T,
class U>
330 requires(not(detail::is_vector<T>::value or detail::is_vector<U>::value))
332 using R =
decltype(std::declval<T>() * std::declval<U>());
336 for (std::size_t i = 0u; i < N; ++i) {
342template <std::
size_t N,
typename T,
class U>
343 requires(std::is_integral_v<T> and std::is_integral_v<U>)
345 using R =
decltype(std::declval<T>() % std::declval<U>());
347 std::ranges::transform(a, b, std::begin(ret), std::modulus<>());
354 using R =
decltype(
sqrt(std::declval<T>()));
356 std::ranges::transform(a, ret.
begin(), [](T
const &v) { return sqrt(v); });
363 T v[3] = {a[1] * b[2] - a[2] * b[1], a[2] * b[0] - a[0] * b[2],
364 a[0] * b[1] - a[1] * b[0]};
370 return std::accumulate(v.
cbegin(), v.
cend(), T{1}, std::multiplies<T>());
373template <
class T,
class U, std::
size_t N>
375 using R =
decltype(std::declval<T>() * std::declval<U>());
376 auto constexpr proj = std::identity{};
378 std::ranges::transform(a, b, ret.
begin(), std::multiplies<>(), proj, proj);
384template <
typename T,
typename U>
385 requires(not(detail::is_vector<T>::value and detail::is_vector<U>::value))
390template <
class T,
class U, std::
size_t N>
392 using R =
decltype(std::declval<T>() / std::declval<U>());
393 auto constexpr proj = std::identity{};
395 std::ranges::transform(a, b, std::begin(ret), std::divides<>(), proj, proj);
401template <
typename T,
typename U>
402 requires(not(detail::is_vector<T>::value and detail::is_vector<U>::value))
409 return {T{1}, T{0}, T{0}};
411 return {T{0}, T{1}, T{0}};
413 return {T{0}, T{0}, T{1}};
414 throw std::domain_error(
"coordinate out of range");
429template <std::
size_t I,
class T, std::
size_t N>
434template <std::
size_t I,
class T, std::
size_t N>
441template <std::
size_t I,
class T, std::
size_t N>
442struct std::tuple_element<I,
Utils::Vector<T, N>> {
443 static_assert(I < N,
"Utils::Vector index must be in range");
447template <
class T, std::
size_t N>
448struct std::tuple_size<
Utils::Vector<T, N>>
449 : std::integral_constant<std::size_t, N> {};
455 static constexpr std::size_t dim = N;
458 template <std::
size_t I>
463 template <std::
size_t I>
464 static constexpr inline scalar_type
479template <
typename T>
struct deduce_vec<
Utils::Vector<T, 3>, 3> {
Array implementation with CUDA support.
#define ESPRESSO_VECTOR_COMPARISON(op)
#define UTILS_ARRAY_BOOST_MPI_T(Container, N)
Mark array types as MPI data types.
#define UTILS_ARRAY_BOOST_BIT_S(Container, N)
Mark array types as MPI bitwise serializable.
#define UTILS_ARRAY_BOOST_CLASS(Container, N, ImplementationLevel)
Redefinition of BOOST_CLASS_IMPLEMENTATION for array types.
#define UTILS_ARRAY_BOOST_TRACK(Container, N, TrackingLevel)
Redefinition of BOOST_CLASS_TRACKING for array types.
Compiler-attribute macros shared across ESPResSo headers.
#define ESPRESSO_ATTR_ALWAYS_INLINE
Vector() noexcept=default
constexpr Vector(T const (&v)[N]) noexcept
DEVICE_QUALIFIER constexpr iterator begin() noexcept
Vector normalized() const
DEVICE_QUALIFIER constexpr const_iterator cbegin() const noexcept
std::vector< T > as_vector() const
Vector(InputIterator first, InputIterator last)
constexpr Vector(std::initializer_list< T > v)
DEVICE_QUALIFIER constexpr const_iterator cend() const noexcept
constexpr std::span< const T, N > as_span() const noexcept
DEVICE_QUALIFIER constexpr iterator end() noexcept
static DEVICE_QUALIFIER constexpr Vector< T, N > broadcast(typename Base::value_type const &value) noexcept
Create a vector that has all entries set to the same value.
constexpr Vector(Range &&rng)
constexpr T norm2() const
constexpr Vector(Array< T, N > const &array) noexcept
auto operator+(Vector< T, N > const &a, Vector< U, N > const &b)
Vector< T, 3 > unit_vector(unsigned int i)
T product(Vector< T, N > const &v)
Vector< T, 3 > vector_product(Vector< T, 3 > const &a, Vector< T, 3 > const &b)
T & get(Array< T, N > &a) noexcept
auto operator/(Vector< T, N > const &a, U const &b)
ESPRESSO_ATTR_ALWAYS_INLINE auto & operator+=(Vector< T, N > &a, Vector< T, N > const &b)
ESPRESSO_ATTR_ALWAYS_INLINE Vector< T, N > & operator-=(Vector< T, N > &a, Vector< T, N > const &b)
auto hadamard_division(Vector< T, N > const &a, Vector< U, N > const &b)
auto & operator*=(Vector< T, N > &b, T const &a)
auto hadamard_product(Vector< T, N > const &a, Vector< U, N > const &b)
auto operator-(Vector< T, N > const &a, Vector< U, N > const &b)
auto sqrt(Vector< T, N > const &a)
auto & operator/=(Vector< T, N > &a, T const &b)
DEVICE_QUALIFIER constexpr reference at(size_type i)
DEVICE_QUALIFIER constexpr bool empty() const noexcept
DEVICE_QUALIFIER constexpr reference back()
DEVICE_QUALIFIER constexpr pointer data() noexcept
DEVICE_QUALIFIER constexpr size_type max_size() const noexcept
DEVICE_QUALIFIER constexpr iterator begin() noexcept
DEVICE_QUALIFIER constexpr const_iterator cbegin() const noexcept
DEVICE_QUALIFIER constexpr const_iterator cend() const noexcept
DEVICE_QUALIFIER constexpr size_type size() const noexcept
DEVICE_QUALIFIER constexpr reference front()
DEVICE_QUALIFIER constexpr iterator end() noexcept
DEVICE_QUALIFIER void fill(const value_type &value)
Meta function to turn a Vector<T, 1> into T.
static constexpr scalar_type read_element(::Utils::Vector< T, N > const &v)
static scalar_type & write_element_idx(std::size_t i, ::Utils::Vector< T, N > &v)
static constexpr scalar_type & write_element(::Utils::Vector< T, N > &v)
static scalar_type read_element_idx(std::size_t i, ::Utils::Vector< T, N > const &v)