29#include <boost/qvm/deduce_vec.hpp>
30#include <boost/qvm/vec_traits.hpp>
40#include <initializer_list>
50template <
typename T, std::
size_t N>
class Vector :
public Array<T, N> {
56 using Base::operator[];
69 template <
class U>
struct is_vector : std::false_type {};
70 template <
class U, std::
size_t Np>
80 constexpr void copy_init(T
const *
values)
noexcept {
81 for (std::size_t i{0}; i !=
N; ++i) {
91 template <
class Range>
93 not std::is_same_v<std::remove_cvref_t<Range>, T[
N]>)
97#if __cpp_lib_containers_ranges
98 template <std::ranges::input_range Range>
104 if constexpr (
N != 0) {
105 copy_init(std::cbegin(v));
111 throw std::length_error(
112 "Construction of Vector from Container of wrong length.");
114 if constexpr (
N != 0) {
115 copy_init(v.begin());
119 template <
typename InputIterator>
124 throw std::length_error(
125 "Construction of Vector from Container of wrong length.");
133 for (std::size_t i = 0
u; i !=
N; ++i) {
144 return std::span<T, N>(
const_cast<T *
>(
begin()),
size());
147 constexpr operator std::span<T, N>()
const {
return as_span(); }
152 std::ranges::transform(*
this,
ret.begin(),
153 [](T
const &
e) { return static_cast<U>(e); });
158 constexpr T
norm2()
const {
return (*
this) * (*this); }
168 auto const l =
norm();
170 for (std::size_t i = 0
u; i <
N; ++i)
196template <std::
size_t N,
typename T,
typename U,
typename Op>
201 using R =
decltype(std::declval<T>() + std::declval<U>());
205 std::transform(std::begin(a), std::end(a), std::begin(b), std::begin(
ret),
211template <std::
size_t N,
typename T,
typename Op>
213 for (std::size_t i = 0
u; i <
N; ++i) {
214 if (
not op(a[i], b[i])) {
222template <std::
size_t N,
typename T>
224 return detail::all_of(a, b, std::less<T>());
227template <std::
size_t N,
typename T>
229 return detail::all_of(a, b, std::greater<T>());
232template <std::
size_t N,
typename T>
234 return detail::all_of(a, b, std::less_equal<T>());
237template <std::
size_t N,
typename T>
239 return detail::all_of(a, b, std::greater_equal<T>());
242template <std::
size_t N,
typename T>
244 return detail::all_of(a, b, std::equal_to<T>());
247template <std::
size_t N,
typename T>
252template <std::
size_t N,
typename T,
typename U>
254 return detail::binary_op(a, b, std::plus<>());
257template <std::
size_t N,
typename T>
259 std::ranges::transform(a, b, std::begin(a), std::plus<T>());
263template <std::
size_t N,
typename T,
typename U>
265 return detail::binary_op(a, b, std::minus<>());
268template <std::
size_t N,
typename T>
271 std::ranges::transform(a, std::begin(
ret), std::negate<T>());
275template <std::
size_t N,
typename T>
277 std::ranges::transform(a, b, std::begin(a), std::minus<T>());
282template <std::
size_t N,
typename T,
class U>
283 requires(std::is_arithmetic_v<U>)
285 using R =
decltype(a * std::declval<T>());
287 std::ranges::transform(b, std::begin(
ret), [a](T
const &v) {
return a * v; });
291template <std::
size_t N,
typename T,
class U>
292 requires(std::is_arithmetic_v<U>)
294 using R =
decltype(std::declval<T>() * b);
296 std::ranges::transform(a, std::begin(
ret), [b](T
const &v) {
return b * v; });
300template <std::
size_t N,
typename T>
302 std::ranges::transform(b, std::begin(b), [a](T
const &v) {
return a * v; });
307template <std::
size_t N,
typename T,
class U>
309 using R =
decltype(std::declval<T>() / b);
311 std::ranges::transform(a, std::begin(
ret), [b](T
const &v) {
return v / b; });
315template <std::
size_t N,
typename T,
class U>
317 using R =
decltype(a / std::declval<T>());
319 std::ranges::transform(b, std::begin(
ret), [a](T
const &v) {
return a / v; });
323template <std::
size_t N,
typename T>
325 std::ranges::transform(a, std::begin(a), [b](T
const &v) {
return v / b; });
330template <
class T>
using is_vector = Vector<int, 1>::is_vector<T>;
334template <std::
size_t N,
typename T,
class U>
335 requires(
not(detail::is_vector<T>::value
or detail::is_vector<U>::value))
337 using R =
decltype(std::declval<T>() * std::declval<U>());
341 for (std::size_t i = 0
u; i <
N; ++i) {
347template <std::
size_t N,
typename T,
class U>
348 requires(std::is_integral_v<T>
and std::is_integral_v<U>)
350 using R =
decltype(std::declval<T>() % std::declval<U>());
352 std::ranges::transform(a, b, std::begin(
ret), std::modulus<>());
359 using R =
decltype(
sqrt(std::declval<T>()));
361 std::ranges::transform(a,
ret.
begin(), [](T
const &v) { return sqrt(v); });
367 return {a[1] * b[2] - a[2] * b[1], a[2] * b[0] - a[0] * b[2],
368 a[0] * b[1] - a[1] * b[0]};
373 return std::accumulate(v.
cbegin(), v.
cend(), T{1}, std::multiplies<T>());
376template <
class T,
class U, std::
size_t N>
378 using R =
decltype(std::declval<T>() * std::declval<U>());
379 auto constexpr proj = std::identity{};
387template <
typename T,
typename U>
388 requires(
not(detail::is_vector<T>::value
and detail::is_vector<U>::value))
393template <
class T,
class U, std::
size_t N>
395 using R =
decltype(std::declval<T>() / std::declval<U>());
396 auto constexpr proj = std::identity{};
398 std::ranges::transform(a, b, std::begin(
ret), std::divides<>(),
proj,
proj);
404template <
typename T,
typename U>
405 requires(
not(detail::is_vector<T>::value
and detail::is_vector<U>::value))
412 return {T{1}, T{0}, T{0}};
414 return {T{0}, T{1}, T{0}};
416 return {T{0}, T{0}, T{1}};
417 throw std::domain_error(
"coordinate out of range");
432template <std::
size_t I,
class T, std::
size_t N>
437template <std::
size_t I,
class T, std::
size_t N>
444template <std::
size_t I,
class T, std::
size_t N>
445struct std::tuple_element<
I,
Utils::Vector<T, N>> {
446 static_assert(
I <
N,
"Utils::Vector index must be in range");
450template <
class T, std::
size_t N>
451struct std::tuple_size<
Utils::Vector<T, N>>
452 : std::integral_constant<std::size_t, N> {};
458 static constexpr std::size_t dim =
N;
461 template <std::
size_t I>
466 template <std::
size_t I>
467 static constexpr inline scalar_type
Array implementation with CUDA support.
#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.
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
DEVICE_QUALIFIER constexpr size_type size() const noexcept
constexpr std::span< T, N > as_span() const
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
cudaStream_t stream[1]
CUDA streams for parallel computing on CPU and GPU.
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, N > & operator-=(Vector< T, N > &a, Vector< T, N > const &b)
constexpr bool operator<(Vector< T, N > const &a, Vector< T, N > const &b)
constexpr bool operator>=(Vector< T, N > const &a, Vector< T, N > const &b)
constexpr bool operator>(Vector< T, N > const &a, Vector< T, N > const &b)
Vector< T, 3 > vector_product(Vector< T, 3 > const &a, Vector< T, 3 > const &b)
auto & operator+=(Vector< T, N > &a, Vector< T, N > const &b)
T & get(Array< T, N > &a) noexcept
auto operator/(Vector< T, N > const &a, U const &b)
constexpr bool operator==(Vector< T, N > const &a, Vector< T, N > const &b)
constexpr bool operator!=(Vector< T, N > const &a, Vector< T, N > const &b)
constexpr bool operator<=(Vector< T, N > const &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)