9#include <initializer_list>
29template <
typename T1,
typename T2>
41template <
typename T1,
typename T2>
44 using type = std::complex<typename std::common_type_t<T1, T2>>;
56template <
typename T1,
typename T2>
59 using type = std::complex<typename std::common_type_t<T1, T2>>;
70template <
typename T1,
typename T2>
73 using type = std::complex<typename std::common_type_t<T1, T2>>;
84template <
typename T1,
typename T2>
97concept complex_type = std::is_same_v<std::decay_t<T>, std::complex<typename T::value_type>> &&
98 std::is_arithmetic_v<typename T::value_type>;
147template <vector_type T, std::
size_t Length>
148class vector :
private std::array<T, Length> {
152 using std::array<T, Length>::begin;
153 using std::array<T, Length>::end;
154 using std::array<T, Length>::cbegin;
155 using std::array<T, Length>::cend;
156 using std::array<T, Length>::rbegin;
157 using std::array<T, Length>::rend;
158 using std::array<T, Length>::crbegin;
159 using std::array<T, Length>::crend;
160 using std::array<T, Length>::empty;
161 using std::array<T, Length>::size;
162 using std::array<T, Length>::operator[];
169 [[nodiscard]]
constexpr vector() : std::array<T, Length>() {
170 std::fill(begin(), end(), T{});
179 [[nodiscard]]
constexpr vector(std::initializer_list<T>
const &list) : std::array<T, Length>() {
180 if (list.size() > Length) {
181 throw std::out_of_range(
"Initializer list size must match vector Length");
183 std::copy(list.begin(), list.end(), begin());
194 [[nodiscard]]
constexpr vector(T
const value) : std::array<T, Length>() {
195 std::fill(begin(), end(), value);
209 template <vector_type U>
212 std::transform(cbegin(), cend(), other.cbegin(), result.begin(),
213 [](
auto const &a,
auto const &b) { return common_type_t<T, U>(a) + common_type_t<T, U>(b); });
229 template <
typename U>
230 [[nodiscard]]
constexpr auto add(U
const scalar)
const {
232 std::transform(cbegin(), cend(), result.begin(),
233 [scalar](
auto const &a) { return common_type_t<T, U>(a) + common_type_t<T, U>(scalar); });
247 template <vector_type U>
262 template <vector_type U>
263 [[nodiscard]]
constexpr auto operator+(U
const scalar)
const {
279 template <vector_type U>
294 template <vector_type U>
296 std::transform(cbegin(), cend(), other.cbegin(), begin(),
311 template <vector_type U>
313 std::transform(cbegin(), cend(), begin(),
328 template <vector_type U>
343 template <vector_type U>
344 [[nodiscard]]
constexpr auto subtract(U
const scalar)
const {
358 template <vector_type U>
373 template <vector_type U>
374 [[nodiscard]]
constexpr auto operator-(U
const scalar)
const {
390 template <vector_type U>
405 template <vector_type U>
407 std::transform(cbegin(), cend(), other.cbegin(), begin(),
422 template <vector_type U>
424 std::transform(cbegin(), cend(), begin(),
446 template <
typename U>
448 return std::transform_reduce(
450 [](
auto const &a,
auto const &b) { return common_type_t<T, U>(a) * common_type_t<T, U>(b); });
464 template <vector_type U>
466 static_assert(Length == 3,
"Cross product is only allowed for 3D vectors.");
469 cross[0] = (*this)[1] * other[2] - (*this)[2] * other[1];
470 cross[1] = (*this)[2] * other[0] - (*this)[0] * other[2];
471 cross[2] = (*this)[0] * other[1] - (*this)[1] * other[0];
486 template <vector_type U>
487 [[nodiscard]]
constexpr auto scale(U
const scalar)
const {
489 std::transform(cbegin(), cend(), result.begin(),
490 [scalar](
auto const &el) { return common_type_t<T, U>(el) * common_type_t<T, U>(scalar); });
504 template <vector_type U>
518 template <vector_type U>
519 [[nodiscard]]
constexpr auto operator*(U
const scalar)
const {
520 return scale(scalar);
535 template <vector_type U>
549 template <vector_type U>
551 std::transform(cbegin(), cend(), begin(),
565 template <vector_type U>
566 [[nodiscard]]
constexpr auto operator/(U
const scalar)
const {
567 return scale(1 / scalar);
582 template <vector_type U>
596 template <vector_type U>
598 std::transform(cbegin(), cend(), begin(),
630 [[nodiscard]]
constexpr auto norm()
const {
631 if constexpr (is_complex_v<T>) {
632 return std::sqrt(std::transform_reduce(cbegin(), cend(), 0.0, std::plus<>(), [](
const auto &val) {
633 return std::norm(val);
636 return std::sqrt(
dot(*
this));
652 throw std::logic_error(
"zero norm results in divide by zero");
666 return std::equal(cbegin(), cend(), other.cbegin());
690 template <vector_type AsType>
694 std::transform(cbegin(), cend(), result.begin(), [](T el) {
695 if constexpr (std::is_same_v<T, std::complex<typename T::value_type>>) {
696 return static_cast<AsType>(el.real() * el.real() + el.imag() * el.imag());
698 return static_cast<AsType>(el);
712 [[nodiscard]]
constexpr std::string
view(
int precision = 20)
const {
713 bool f_is_first =
false;
714 std::stringstream ss;
716 ss << std::setprecision(precision) <<
"[";
718 for (
auto const &el : *
this) {
Represents a mathematical vector in n-dimensional space.
Definition vector.hpp:148
constexpr auto operator-(U const scalar) const
Subtracts a scalar from each element of the vector using the - operator.
Definition vector.hpp:374
constexpr auto norm() const
Computes the Euclidean magnitude (Length) of the vector.
Definition vector.hpp:630
constexpr auto & operator-=(vector< U, Length > const &other)
Performs element-wise subtraction of another vector using the -= operator.
Definition vector.hpp:406
constexpr std::string view(int precision=20) const
Converts the vector to a string representation.
Definition vector.hpp:712
constexpr auto operator+(U const scalar) const
Adds a scalar to each element of the vector using the + operator.
Definition vector.hpp:263
constexpr auto dot(vector< U, Length > const &other) const
Calculates the dot product of two vectors.
Definition vector.hpp:447
constexpr auto & operator+=(vector< U, Length > const &other)
Performs element-wise addition of two vectors using the += operator.
Definition vector.hpp:295
constexpr auto & operator-=(U const scalar)
Subtracts a scalar from each element of the vector using the -= operator.
Definition vector.hpp:423
constexpr auto is_equal(vector< T, Length > const &other) const
Compares two vectors for equality.
Definition vector.hpp:665
constexpr auto operator+(vector< U, Length > const &other) const
Adds two vectors element-wise using the + operator.
Definition vector.hpp:248
T value_type
Definition vector.hpp:151
constexpr vector()
Default constructor that initialises all elements of the vector to zero.
Definition vector.hpp:169
constexpr auto to_normalized() const
Normalizes the vector.
Definition vector.hpp:649
constexpr auto add(U const scalar) const
Adds a scalar to each element of the vector and returns the result.
Definition vector.hpp:230
vector< AsType, Length > constexpr const as_type() const
Converts the vector elements to a different type, handling complex numbers.
Definition vector.hpp:691
friend std::ostream & operator<<(std::ostream &os, vector const &other)
Stream insertion operator for vectors.
Definition vector.hpp:742
friend constexpr auto operator*(U const scalar, vector< T, Length > const &vec)
Scales a vector by a scalar.
Definition vector.hpp:536
constexpr auto operator/(U const scalar) const
Scales the vector by the inverse of a scalar using the / operator.
Definition vector.hpp:566
constexpr auto operator==(vector< T, Length > const &other) const
Equality operator for vectors.
Definition vector.hpp:677
constexpr auto subtract(U const scalar) const
Subtracts a scalar from each element of the vector.
Definition vector.hpp:344
constexpr auto cross(vector< U, Length > const &other) const
Calculates the cross product of two 3D vectors.
Definition vector.hpp:465
constexpr auto operator-() const
Negates the vector.
Definition vector.hpp:610
constexpr auto & operator+=(U const scalar)
Adds a scalar to each element of the vector using the += operator.
Definition vector.hpp:312
constexpr auto operator-(vector< U, Length > const &other) const
Subtracts another vector from this vector using the - operator.
Definition vector.hpp:359
friend constexpr auto operator-(U const scalar, vector< T, Length > const &vec)
Subtracts a scalar to a vector.
Definition vector.hpp:391
friend constexpr auto operator+(U const scalar, vector< T, Length > const &vec)
Adds a scalar to a vector.
Definition vector.hpp:280
friend constexpr auto operator/(U const scalar, vector< T, Length > const &vec)
Performs inverse scaling of a vector by a scalar.
Definition vector.hpp:583
constexpr auto & operator/=(U const scalar)
Scales the vector in place using the /= operator.
Definition vector.hpp:597
constexpr vector(std::initializer_list< T > const &list)
Constructor that initializes the vector using an initializer list.
Definition vector.hpp:179
constexpr auto operator*(vector< U, Length > const &other) const
Calculates the dot product using the * operator.
Definition vector.hpp:505
constexpr auto operator*(U const scalar) const
Scales the vector using the * operator.
Definition vector.hpp:519
constexpr vector(T const value)
Constructor that initialises all elements of the vector to a given value.
Definition vector.hpp:194
constexpr auto subtract(vector< U, Length > const &other) const
Subtracts another vector from this vector.
Definition vector.hpp:329
constexpr auto add(vector< U, Length > const &other) const
Adds two vectors element-wise and returns the result.
Definition vector.hpp:210
constexpr auto & operator*=(U const scalar)
Scales the vector in place using the *= operator.
Definition vector.hpp:550
constexpr auto scale(U const scalar) const
Scales the vector by a given scalar.
Definition vector.hpp:487
Concept that ensures the type is a complex number type.
Definition vector.hpp:97
Concept that ensures the type is either arithmetic or a complex type.
Definition vector.hpp:110
Definition utilities.hpp:3
typename common_type< T1, T2 >::type common_type_t
Helper alias template for the common_type structure, similar to std::common_type_t.
Definition vector.hpp:85
constexpr bool is_complex_v
Helper variable template for is_complex.
Definition vector.hpp:141
std::complex< typename std::common_type_t< T1, T2 > > type
The resulting type is std::complex with the common type of T1 and T2.
Definition vector.hpp:44
std::complex< typename std::common_type_t< T1, T2 > > type
The resulting type is std::complex with the common type of T1 and T2.
Definition vector.hpp:59
std::complex< typename std::common_type_t< T1, T2 > > type
The resulting type is std::complex with the common type of T1 and T2.
Definition vector.hpp:73
Customised common_type implementation that handles cases where one or both types may be arithmetic or...
Definition vector.hpp:30
Trait to determine if a type is a std::complex type.
Definition vector.hpp:121