41#ifndef UFO_NUMERIC_VEC_HPP
42#define UFO_NUMERIC_VEC_HPP
45#include <ufo/numeric/math.hpp>
74template <std::
size_t Dim,
class T>
75 requires(Dim <= 4 && std::is_arithmetic_v<T>)
78 using size_type = std::size_t;
80 std::array<T, Dim> fields{};
85 constexpr Vec() noexcept = default;
96 template <
std::convertible_to<T>... Args>
97 requires(sizeof...(Args) <= Dim)
98 explicit(sizeof...(Args) == 1) constexpr
Vec(Args... args) noexcept
99 : fields{
static_cast<T
>(args)...}
113 std::ranges::transform(other, begin(), [](U
const& v) {
return static_cast<T
>(v); });
127 constexpr auto&
operator[](
this auto& self, size_type i)
noexcept
129 return self.fields[i];
136 [[nodiscard]]
constexpr auto&
x(
this auto& self)
noexcept
146 [[nodiscard]]
constexpr auto&
y(
this auto& self)
noexcept
156 [[nodiscard]]
constexpr auto&
z(
this auto& self)
noexcept
166 [[nodiscard]]
constexpr auto&
w(
this auto& self)
noexcept
176 [[nodiscard]]
constexpr auto begin(
this auto& self)
noexcept
178 return self.fields.begin();
185 [[nodiscard]]
constexpr auto end(
this auto& self)
noexcept {
return self.fields.end(); }
191 [[nodiscard]]
constexpr auto data(
this auto& self)
noexcept
193 return self.fields.data();
200 [[nodiscard]]
static constexpr std::size_t
size() noexcept {
return Dim; }
228 std::ranges::transform(*
this, result.
begin(), std::negate{});
237 requires
std::is_integral_v<T>
240 std::ranges::transform(*
this, result.
begin(), std::bit_not{});
257 std::ranges::transform(*
this, rhs, begin(), std::plus{});
268 std::ranges::transform(*
this, rhs, begin(), std::minus{});
279 std::ranges::transform(*
this, rhs, begin(), std::multiplies{});
290 std::ranges::transform(*
this, rhs, begin(), std::divides{});
301 requires std::is_integral_v<T>
303 std::ranges::transform(*
this, rhs, begin(), std::modulus{});
314 requires std::is_integral_v<T>
316 std::ranges::transform(*
this, rhs, begin(), std::bit_and{});
327 requires std::is_integral_v<T>
329 std::ranges::transform(*
this, rhs, begin(), std::bit_or{});
340 requires std::is_integral_v<T>
342 std::ranges::transform(*
this, rhs, begin(), std::bit_xor{});
353 requires std::is_integral_v<T>
355 std::ranges::transform(*
this, rhs, begin(), [](T
a, T
b) {
return a <<
b; });
366 requires std::is_integral_v<T>
368 std::ranges::transform(*
this, rhs, begin(), [](T
a, T
b) {
return a >>
b; });
385 std::ranges::transform(*
this, begin(), [rhs](T v) {
return v + rhs; });
396 std::ranges::transform(*
this, begin(), [rhs](T v) {
return v - rhs; });
407 std::ranges::transform(*
this, begin(), [rhs](T v) {
return v * rhs; });
418 std::ranges::transform(*
this, begin(), [rhs](T v) {
return v / rhs; });
429 requires std::is_integral_v<T>
431 std::ranges::transform(*
this, begin(), [rhs](T v) {
return v % rhs; });
441 requires std::is_integral_v<T>
443 std::ranges::transform(*
this, begin(), [rhs](T v) {
return v & rhs; });
453 requires std::is_integral_v<T>
455 std::ranges::transform(*
this, begin(), [rhs](T v) {
return v | rhs; });
465 requires std::is_integral_v<T>
467 std::ranges::transform(*
this, begin(), [rhs](T v) {
return v ^ rhs; });
477 requires std::is_integral_v<T>
479 std::ranges::transform(*
this, begin(), [rhs](T v) {
return v <<= rhs; });
489 requires std::is_integral_v<T>
491 std::ranges::transform(*
this, begin(), [rhs](T v) {
return v >>= rhs; });
502using Vec1b = Vec<1, bool>;
503using Vec2b = Vec<2, bool>;
504using Vec3b = Vec<3, bool>;
505using Vec4b = Vec<4, bool>;
506using Vec1i = Vec<1, int>;
507using Vec2i = Vec<2, int>;
508using Vec3i = Vec<3, int>;
509using Vec4i = Vec<4, int>;
510using Vec1u = Vec<1, unsigned>;
511using Vec2u = Vec<2, unsigned>;
512using Vec3u = Vec<3, unsigned>;
513using Vec4u = Vec<4, unsigned>;
514using Vec1f = Vec<1, float>;
515using Vec2f = Vec<2, float>;
516using Vec3f = Vec<3, float>;
517using Vec4f = Vec<4, float>;
518using Vec1d = Vec<1, double>;
519using Vec2d = Vec<2, double>;
520using Vec3d = Vec<3, double>;
521using Vec4d = Vec<4, double>;
537template <std::
size_t Dim,
class T>
553template <std::
size_t Dim,
class T>
569template <std::
size_t Dim,
class T>
585template <std::
size_t Dim,
class T>
601template <std::
size_t Dim, std::
integral T>
617template <std::
size_t Dim, std::
integral T>
633template <std::
size_t Dim, std::
integral T>
649template <std::
size_t Dim, std::
integral T>
665template <std::
size_t Dim, std::
integral T>
681template <std::
size_t Dim, std::
integral T>
696template <std::
size_t Dim>
700 std::ranges::transform(lhs, rhs, lhs.begin(), std::logical_and{});
711template <std::
size_t Dim>
715 std::ranges::transform(lhs, rhs, lhs.begin(), std::logical_or{});
733template <std::
size_t Dim,
class T>
748template <std::
size_t Dim,
class T>
763template <std::
size_t Dim,
class T>
778template <std::
size_t Dim,
class T>
794template <std::
size_t Dim, std::
integral T>
809template <std::
size_t Dim, std::
integral T>
824template <std::
size_t Dim, std::
integral T>
839template <std::
size_t Dim, std::
integral T>
854template <std::
size_t Dim, std::
integral T>
869template <std::
size_t Dim, std::
integral T>
884template <std::
size_t Dim,
class T>
899template <std::
size_t Dim,
class T>
902 std::ranges::transform(rhs, rhs.begin(), [lhs](T v) { return lhs - v; });
914template <std::
size_t Dim,
class T>
929template <std::
size_t Dim,
class T>
932 std::ranges::transform(rhs, rhs.begin(), [lhs](T v) { return lhs / v; });
945template <std::
size_t Dim, std::
integral T>
948 std::ranges::transform(rhs, rhs.begin(), [lhs](T v) { return lhs % v; });
960template <std::
size_t Dim, std::
integral T>
975template <std::
size_t Dim, std::
integral T>
990template <std::
size_t Dim, std::
integral T>
1005template <std::
size_t Dim, std::
integral T>
1008 std::ranges::transform(rhs, rhs.begin(), [lhs](T v) { return lhs << v; });
1020template <std::
size_t Dim, std::
integral T>
1023 std::ranges::transform(rhs, rhs.begin(), [lhs](T v) { return lhs >> v; });
1041template <
class T, std::
size_t Dim,
class U>
1058template <
class To, std::
size_t Dim,
class U>
1061 using T =
typename To::value_type;
1063 std::size_t
const D = std::min(res.size(), v.size());
1064 for (std::size_t i{}; D > i; ++i) {
1065 res[i] =
static_cast<T
>(v[i]);
1078template <std::
size_t Dim,
class T>
1081#if defined(__cpp_lib_ranges_zip) && defined(__cpp_lib_fold_left)
1082 return std::ranges::fold_left(std::views::zip_transform(std::multiplies{},
a,
b), T{},
1086 for (std::size_t i{}; Dim > i; ++i) {
1100template <std::
size_t Dim, std::
floating_po
int T>
1103 return std::sqrt(
dot(v, v));
1114template <std::
size_t Dim,
class T>
1115 requires std::floating_point<T>
1131template <std::
size_t Dim,
class T>
1147template <std::
size_t Dim, std::
floating_po
int T>
1161template <std::
size_t Dim,
class T>
1164 if constexpr (std::floating_point<T>) {
1165 return std::abs(
dot(v, v) - T(1)) <= std::numeric_limits<T>::epsilon() * T(8);
1167 return dot(v, v) == T(1);
1182 (
a[0] *
b[1]) - (
a[1] *
b[0])};
1193template <std::
size_t Dim, std::
floating_po
int T>
1197 return v - T(2) *
dot(v, n) * n;
1209template <std::
size_t Dim, std::
floating_po
int T>
1215 Vec<Dim, T> k = T(1) - eta * eta * (T(1) - tmp * tmp);
1216 return k < T(0) ?
Vec<Dim, T>{} : eta * v - (eta * tmp + sqrt(k)) * n;
1227template <std::
size_t Dim,
class T>
1230 std::ranges::transform(v1, v2, v1.begin(), [](T
a, T
b) { return std::min(a, b); });
1241template <std::
size_t Dim,
class T>
1244 return *std::ranges::min_element(v);
1255template <std::
size_t Dim,
class T>
1258 std::ranges::transform(v1, v2, v1.begin(), [](T
a, T
b) { return std::max(a, b); });
1269template <std::
size_t Dim,
class T>
1272 return *std::ranges::max_element(v);
1282template <std::
size_t Dim,
class T>
1285 return static_cast<std::size_t
>(std::ranges::min_element(v) - v.begin());
1295template <std::
size_t Dim,
class T>
1298 return static_cast<std::size_t
>(std::ranges::max_element(v) - v.begin());
1308template <std::
size_t Dim,
class T>
1311#ifdef __cpp_lib_fold_left
1312 return std::ranges::fold_left(v, T{}, std::plus{});
1329template <std::
size_t Dim,
class T>
1332#ifdef __cpp_lib_fold_left
1333 return std::ranges::fold_left(v, T{1}, std::multiplies{});
1350template <std::
size_t Dim,
class T>
1353 std::ranges::transform(v, v.begin(), [](T x) { return std::abs(x); });
1366template <std::
size_t Dim,
class T>
1370#ifdef __cpp_lib_ranges_zip
1371 for (
auto [vi, li, hi_i] : std::views::zip(v, lo, hi)) {
1372 vi = std::clamp(vi, li, hi_i);
1375 for (std::size_t i{}; Dim > i; ++i) {
1376 v[i] = std::clamp(v[i], lo[i], hi[i]);
1389template <std::
size_t Dim, std::
floating_po
int T>
1392 std::ranges::transform(v, v.begin(), [](T x) { return std::ceil(x); });
1403template <std::
size_t Dim, std::
floating_po
int T>
1406 std::ranges::transform(v, v.begin(), [](T x) { return std::floor(x); });
1417template <std::
size_t Dim, std::
floating_po
int T>
1420 std::ranges::transform(v, v.begin(), [](T x) { return std::trunc(x); });
1432template <std::
size_t Dim, std::
floating_po
int T>
1435 std::ranges::transform(v, v.begin(), [](T x) { return std::round(x); });
1447template <std::
size_t Dim,
class T>
1452 std::ranges::transform(v1, v2, res.
begin(), std::equal_to{});
1464template <std::
size_t Dim,
class T>
1469 std::ranges::transform(v1, v2, res.
begin(), std::not_equal_to{});
1481template <std::
size_t Dim,
class T>
1486 std::ranges::transform(v1, v2, res.
begin(), std::less{});
1498template <std::
size_t Dim,
class T>
1503 std::ranges::transform(v1, v2, res.
begin(), std::less_equal{});
1515template <std::
size_t Dim,
class T>
1520 std::ranges::transform(v1, v2, res.
begin(), std::greater{});
1532template <std::
size_t Dim,
class T>
1537 std::ranges::transform(v1, v2, res.
begin(), std::greater_equal{});
1547template <std::
size_t Dim>
1550 return std::ranges::all_of(v, std::identity{});
1559template <std::
size_t Dim>
1562 return std::ranges::any_of(v, std::identity{});
1571template <std::
size_t Dim>
1574 return any(v) && !
all(v);
1583template <std::
size_t Dim>
1586 return std::ranges::none_of(v, std::identity{});
1596template <std::
size_t Dim, std::
floating_po
int T>
1599 return std::ranges::any_of(v, [](T x) {
return std::isnan(x); });
1609template <std::
size_t Dim, std::
floating_po
int T>
1612 return std::ranges::all_of(v, [](T x) {
return std::isfinite(x); });
1623template <std::
size_t Dim, std::
floating_po
int T>
1626 return std::ranges::all_of(v, [](T x) {
return std::isnormal(x); });
1638template <std::
size_t Dim, std::
floating_po
int T>
1642 std::ranges::transform(
a,
b,
a.begin(), [t](T x, T y) { return std::lerp(x, y, t); });
1656template <std::
size_t Dim,
class T,
class U>
1672template <std::
size_t Dim,
class T>
1677 for (
auto [ri, xi, yi, ai] : std::views::zip(res, x, y,
a)) {
1690template <std::
size_t Dim,
class T>
1694 std::ranges::transform(x, res.
begin(), [](T v) { return static_cast<T>(sign(v)); });
1706template <std::
size_t Dim, std::
floating_po
int T>
1709 std::ranges::transform(v, v.begin(), [exp](T x) { return std::ldexp(x, exp); });
1727template <std::
size_t I, std::
size_t Dim,
class T>
1742template <std::
size_t I, std::
size_t Dim,
class T>
1757template <std::
size_t I, std::
size_t Dim,
class T>
1761 return std::move(v[I]);
1782template <std::
size_t Dim,
class T>
1785 static constexpr std::array names = {
'x',
'y',
'z',
'w'};
1786#ifdef __cpp_lib_ranges_enumerate
1787 for (
auto const [i, name] : std::views::enumerate(names)) {
1789 out << name <<
": " << v[i];
1792 for (std::size_t i{}; std::min(Dim, names.size()) > i; ++i) {
1794 out << names[i] <<
": " << v[i];
1801template <std::
size_t Dim,
class T>
1802struct std::tuple_size<
ufo::Vec<Dim, T>> : std::integral_constant<std::size_t, Dim> {
1805template <std::
size_t I, std::
size_t Dim,
class T>
1806struct std::tuple_element<I,
ufo::Vec<Dim, T>> {
1810template <std::
size_t Dim,
class T>
1811 requires std::formattable<T, char>
1812struct std::formatter<
ufo::Vec<Dim, T>> {
1813 constexpr auto parse(std::format_parse_context& ctx) {
return ctx.begin(); }
1817 static constexpr std::array names = {
'x',
'y',
'z',
'w'};
1818 auto out = ctx.out();
1819#ifdef __cpp_lib_ranges_enumerate
1820 for (
auto const [i, name] : std::views::enumerate(names)) {
1821 if (i) out = std::format_to(out,
" ");
1822 out = std::format_to(out,
"{}: {}", name, v[i]);
1825 for (std::size_t i{}; std::min(Dim, names.size()) > i; ++i) {
1826 if (i) out = std::format_to(out,
" ");
1827 out = std::format_to(out,
"{}: {}", names[i], v[i]);
constexpr Vec< Dim, T > cast(Vec< Dim, U > const &v) noexcept
Casts each element of a vector to a new type.
constexpr int sign(T val) noexcept
Returns the sign of a value.
Vec< 4, bool > isnan(Quat< T > const &q) noexcept
Returns a bool vector indicating which components are NaN.
constexpr Vec & operator+=(Vec const &rhs) noexcept
Adds each component of rhs to the corresponding component.
constexpr Vec operator+() const noexcept
Unary identity operator.
constexpr auto & operator[](this auto &self, size_type i) noexcept
Accesses the element at index i.
Quat< T > mix(Quat< T > const &x, Quat< T > const &y, T a)
Spherical or linear interpolation between two quaternions.
constexpr Vec< Cols, T > & get(Mat< Rows, Cols, T > &m) noexcept
Structured-binding accessor — lvalue reference to row I.
constexpr Vec & operator+=(T rhs) noexcept
Adds scalar rhs to every component.
constexpr T dot(Quat< T > const &a, Quat< T > const &b) noexcept
Computes the four-component dot product a.w*b.w + a.x*b.x + a.y*b.y + a.z*b.z.
All vision-related classes and functions.
constexpr Vec< Dim, T > ldexp(Vec< Dim, T > v, int exp) noexcept
Multiplies each component of a floating-point vector by 2^exp.
constexpr Vec< Dim, T > floor(Vec< Dim, T > v) noexcept
Returns the component-wise floor of a floating-point vector.
constexpr Vec< Dim, T > trunc(Vec< Dim, T > v) noexcept
Returns the component-wise truncation toward zero of a floating-point vector.
constexpr T b(Lab< T, Flags > color) noexcept
Returns the un-weighted blue–yellow axis value.
constexpr Vec< Dim, T > operator%(Vec< Dim, T > lhs, Vec< Dim, T > const &rhs) noexcept
Component-wise modulo of two integral vectors.
constexpr bool isnormal(Vec< Dim, T > const &v) noexcept
Returns true if all components of a floating-point vector are normal.
constexpr Vec< Dim, bool > notEqual(Vec< Dim, T > const &v1, Vec< Dim, T > const &v2) noexcept
Returns a bool vector indicating component-wise inequality.
constexpr bool any(Vec< Dim, bool > const &v) noexcept
Returns true if at least one component of a bool vector is true.
constexpr Mat< Rows, Cols, T > operator*(Mat< Rows, Cols, T > lhs, T rhs) noexcept
Multiplies every element of lhs by scalar rhs.
constexpr Vec< Dim, T > ceil(Vec< Dim, T > v) noexcept
Returns the component-wise ceiling of a floating-point vector.
constexpr Mat< Rows, Cols, T > operator/(Mat< Rows, Cols, T > lhs, T rhs) noexcept
Divides every element of lhs by scalar rhs.
constexpr Vec< Dim, T > reflect(Vec< Dim, T > const &v, Vec< Dim, T > const &n) noexcept
Reflects an incident vector about a surface normal.
constexpr T a(Lab< T, Flags > color) noexcept
Returns the un-weighted green–red axis value.
constexpr std::size_t maxIndex(Vec< Dim, T > const &v) noexcept
Returns the index of the largest element in a vector.
constexpr bool some(Vec< Dim, bool > const &v) noexcept
Returns true if some but not all components of a bool vector are true.
constexpr Vec< Dim, T > round(Vec< Dim, T > v) noexcept
Returns the component-wise rounding to nearest integer of a floating-point vector.
constexpr auto distanceSquared(A const &a, B const &b)
Computes the minimum squared distance between two shapes.
constexpr Vec< Dim, bool > greater(Vec< Dim, T > const &v1, Vec< Dim, T > const &v2) noexcept
Returns a bool vector indicating component-wise greater-than.
constexpr T length(Vec< Dim, T > const &v) noexcept
Computes the Euclidean length (magnitude) of a vector.
constexpr Vec< Dim, bool > less(Vec< Dim, T > const &v1, Vec< Dim, T > const &v2) noexcept
Returns a bool vector indicating component-wise less-than.
constexpr Vec< Geometry::dimension(), typename Geometry::value_type > max(Geometry const &g)
Returns the maximum coordinate of the minimum spanning axis-aligned bounding box of a geometry.
constexpr Vec< Dim, bool > operator||(Vec< Dim, bool > lhs, Vec< Dim, bool > const &rhs) noexcept
Component-wise logical OR of two bool vectors.
constexpr Quat< T > normalize(Quat< T > const &q) noexcept
Returns a unit quaternion in the same direction as q.
constexpr Vec< Dim, bool > greaterEqual(Vec< Dim, T > const &v1, Vec< Dim, T > const &v2) noexcept
Returns a bool vector indicating component-wise greater-than-or-equal.
constexpr Vec< Dim, T > abs(Vec< Dim, T > v) noexcept
Returns the component-wise absolute value of a vector.
constexpr bool all(Vec< Dim, bool > const &v) noexcept
Returns true if all components of a bool vector are true.
constexpr Vec< Dim, T > refract(Vec< Dim, T > const &v, Vec< Dim, T > const &n, T eta) noexcept
Computes the refraction vector for an incident ray entering a new medium.
constexpr T product(Vec< Dim, T > const &v) noexcept
Computes the product of all elements in a vector.
constexpr To convert(Vec< Dim, U > const &v) noexcept
Converts a vector to a different Vec type, truncating or zero-padding dimensions.
constexpr Quat< T > cross(Quat< T > const &q1, Quat< T > const &q2) noexcept
Computes the Hamilton cross product of two quaternions.
constexpr Quat< T > lerp(Quat< T > const &x, Quat< T > const &y, T a) noexcept
Normalised linear interpolation (NLERP) between two quaternions.
constexpr Vec< Dim, T > clamp(Vec< Dim, T > v, Vec< Dim, T > const &lo, Vec< Dim, T > const &hi) noexcept
Clamps each component of a vector to the range [lo[i], hi[i]].
constexpr bool isNormalized(Vec< Dim, T > const &v) noexcept
Checks whether a vector has unit length.
constexpr Vec< Dim, bool > operator&&(Vec< Dim, bool > lhs, Vec< Dim, bool > const &rhs) noexcept
Component-wise logical AND of two bool vectors.
constexpr Vec< Dim, bool > lessEqual(Vec< Dim, T > const &v1, Vec< Dim, T > const &v2) noexcept
Returns a bool vector indicating component-wise less-than-or-equal.
constexpr Vec< Dim, T > operator^(Vec< Dim, T > lhs, Vec< Dim, T > const &rhs) noexcept
Component-wise bitwise XOR of two integral vectors.
constexpr Vec< Geometry::dimension(), typename Geometry::value_type > min(Geometry const &g)
Returns the minimum coordinate of the minimum spanning axis-aligned bounding box of a geometry.
constexpr bool isfinite(Vec< Dim, T > const &v) noexcept
Returns true if all components of a floating-point vector are finite.
constexpr std::size_t minIndex(Vec< Dim, T > const &v) noexcept
Returns the index of the smallest element in a vector.
constexpr bool none(Vec< Dim, bool > const &v) noexcept
Returns true if no component of a bool vector is true.
constexpr Vec< Dim, bool > equal(Vec< Dim, T > const &v1, Vec< Dim, T > const &v2) noexcept
Returns a bool vector indicating component-wise equality.
constexpr T sum(Vec< Dim, T > const &v) noexcept
Computes the sum of all elements in a vector.
constexpr auto distance(A const &a, B const &b)
Computes the minimum distance between two shapes.
A fixed-size arithmetic vector of up to 4 dimensions.
constexpr Vec & operator%=(T rhs) noexcept
Computes the remainder of every component divided by scalar rhs (integral types only).
constexpr Vec & operator%=(Vec const &rhs) noexcept
Computes the remainder of each component divided by the corresponding component of rhs (integral type...
constexpr Vec & operator-=(Vec const &rhs) noexcept
Subtracts each component of rhs from the corresponding component.
constexpr Vec & operator-=(T rhs) noexcept
Subtracts scalar rhs from every component.
constexpr auto & y(this auto &self) noexcept
Accesses the second component (y).
constexpr Vec & operator|=(Vec const &rhs) noexcept
Bitwise ORs each component with the corresponding component of rhs (integral types only).
constexpr Vec & operator/=(T rhs) noexcept
Divides every component by scalar rhs.
constexpr Vec & operator&=(T rhs) noexcept
Bitwise ANDs every component with scalar rhs (integral types only).
constexpr Vec & operator|=(T rhs) noexcept
Bitwise ORs every component with scalar rhs (integral types only).
constexpr Vec & operator<<=(T rhs) noexcept
Left-shifts every component by scalar rhs (integral types only).
static constexpr std::size_t size() noexcept
Returns the number of dimensions.
constexpr Vec & operator&=(Vec const &rhs) noexcept
Bitwise ANDs each component with the corresponding component of rhs (integral types only).
constexpr auto & z(this auto &self) noexcept
Accesses the third component (z).
constexpr auto end(this auto &self) noexcept
Returns a past-the-end iterator.
constexpr bool operator==(Vec const &) const =default
Compares two vectors for equality (component-wise).
constexpr auto & x(this auto &self) noexcept
Accesses the first component (x).
constexpr Vec & operator>>=(Vec const &rhs) noexcept
Right-shifts each component by the corresponding component of rhs (integral types only).
constexpr Vec & operator*=(Vec const &rhs) noexcept
Multiplies each component by the corresponding component of rhs.
constexpr auto & w(this auto &self) noexcept
Accesses the fourth component (w).
constexpr Vec & operator/=(Vec const &rhs) noexcept
Divides each component by the corresponding component of rhs.
constexpr Vec & operator^=(Vec const &rhs) noexcept
Bitwise XORs each component with the corresponding component of rhs (integral types only).
constexpr Vec & operator*=(T rhs) noexcept
Multiplies every component by scalar rhs.
constexpr Vec operator-() const noexcept
Unary negation operator.
constexpr Vec & operator>>=(T rhs) noexcept
Right-shifts every component by scalar rhs (integral types only).
constexpr Vec & operator<<=(Vec const &rhs) noexcept
Left-shifts each component by the corresponding component of rhs (integral types only).
constexpr auto data(this auto &self) noexcept
Returns a pointer to the underlying element array.
constexpr Vec & operator^=(T rhs) noexcept
Bitwise XORs every component with scalar rhs (integral types only).
constexpr Vec() noexcept=default
Default constructor; initializes all elements to zero.
constexpr auto begin(this auto &self) noexcept
Returns an iterator to the first element.
constexpr Vec operator~() const noexcept
Bitwise NOT operator (integral types only).