Phyth v0.1.0
A dimensional safe C++ header-only mechanics and electromagnetics simulation library.
Loading...
Searching...
No Matches
Vector.hpp
Go to the documentation of this file.
1#ifndef PHYTH_VECTOR_HPP
2#define PHYTH_VECTOR_HPP
3
5#include "QuantityFuncs.hpp"
6
7#include <array>
8#include <cstddef>
9#include <utility>
10#include <stdexcept>
11#include <ostream>
12#include <type_traits>
13
14namespace Phyth {
15 template<std::size_t N, typename T>
16 struct Vector {
17 static_assert(is_quantity_v<T>, "Vector only supports Quantity types");
18 static_assert(N != 0, "Does not support zero dimensional space");
19
20 std::array<T, N> datas;
21
22 constexpr Vector() = default;
23
24 template<typename... Args,
25 std::enable_if_t<
26 sizeof...(Args) == N &&
27 std::conjunction_v<std::is_convertible<Args, T>...>,
28 int> = 0>
29 constexpr Vector(Args... comps) : datas{comps...} {
30 }
31
32 constexpr T &At(const size_t i) {
33 return datas.at(i);
34 }
35
36 constexpr const T &At(const size_t i) const {
37 return datas.at(i);
38 }
39
40 constexpr T &operator[](const size_t i) {
41 return datas[i];
42 }
43
44 constexpr const T &operator[](const size_t i) const {
45 return datas[i];
46 }
47
48 template<typename U>
49 constexpr auto operator+(const Vector<N, U> &other) const {
50 using ResultScalar = decltype(datas[0] + other.datas[0]);
52 other, std::make_index_sequence<N>{},
53 [](const auto &a, const auto &b) { return a + b; });
54 }
55
56 template<typename U>
57 constexpr auto operator-(const Vector<N, U> &other) const {
58 using ResultScalar = decltype(datas[0] - other.datas[0]);
60 other, std::make_index_sequence<N>{},
61 [](const auto &a, const auto &b) { return a - b; });
62 }
63
64 constexpr auto operator-() const {
65 using ResultScalar = decltype(-datas[0]);
67 std::make_index_sequence<N>{},
68 [](const auto &a) { return -a; });
69 }
70
71 template<typename U,
72 typename = std::enable_if_t<!std::is_same_v<std::decay_t<U>, Vector>> >
73 constexpr auto operator*(U scalar) const {
74 using ResultScalar = decltype(datas[0] * scalar);
76 scalar, std::make_index_sequence<N>{},
77 [](const auto &a, const auto &s) { return a * s; });
78 }
79
80 template<typename U>
81 constexpr auto operator/(U scalar) const {
82 using ResultScalar = decltype(datas[0] / scalar);
84 scalar, std::make_index_sequence<N>{},
85 [](const auto &a, const auto &s) { return a / s; });
86 }
87
88 template<typename U>
89 constexpr Vector &operator+=(const Vector<N, U> &other) {
90 for (std::size_t i = 0; i < N; ++i)
91 datas[i] += other.datas[i];
92 return *this;
93 }
94
95 template<typename U>
96 constexpr Vector &operator-=(const Vector<N, U> &other) {
97 for (std::size_t i = 0; i < N; ++i)
98 datas[i] -= other.datas[i];
99 return *this;
100 }
101
102 template<typename U>
103 constexpr Vector &operator*=(U scalar) {
104 for (std::size_t i = 0; i < N; ++i)
105 datas[i] *= scalar;
106 return *this;
107 }
108
109 template<typename U>
110 constexpr Vector &operator/=(U scalar) {
111 for (std::size_t i = 0; i < N; ++i)
112 datas[i] /= scalar;
113 return *this;
114 }
115
116 constexpr bool operator==(const Vector &other) const {
117 for (std::size_t i = 0; i < N; ++i)
118 if (datas[i] != other.datas[i])
119 return false;
120 return true;
121 }
122
123 constexpr bool operator!=(const Vector &other) const {
124 return !(*this == other);
125 }
126
127 [[nodiscard]] auto LengthSquared() const {
128 using ResultScalar = decltype(datas[0] * datas[0]);
130 for (std::size_t i = 0; i < N; ++i)
131 result += datas[i] * datas[i];
132 return result;
133 }
134
135 [[nodiscard]] auto Length() const {
136 return Utils::sqrt(LengthSquared());
137 }
138
139 [[nodiscard]] auto Normalized() const {
140 auto len = Length();
141 if (len == decltype(len){0}) {
142 throw std::runtime_error("Normalize the zero vector");
143 }
144 using ResultScalar = decltype(datas[0] / len);
146 len, std::make_index_sequence<N>{},
147 [](const auto &a, const auto &l) { return a / l; });
148 }
149
150 template<typename U>
151 [[nodiscard]] constexpr auto Dot(const Vector<N, U> &other) const {
152 using ResultScalar = decltype(datas[0] * other.datas[0]);
154 for (std::size_t i = 0; i < N; ++i)
155 result += datas[i] * other.datas[i];
156 return result;
157 }
158
159 template<typename U>
160 [[nodiscard]] auto Project(const Vector<N, U> &other) const {
161 return Dot(other) / other.LengthSquared() * other;
162 }
163
164 template<typename UnitT>
165 [[nodiscard]] auto As() const {
166 using ResultScalar = decltype(datas[0].template As<UnitT>());
167 return make_as<ResultScalar, UnitT>(std::make_index_sequence<N>{});
168 }
169
170 friend std::ostream &operator<<(std::ostream &os, const Vector &v) {
171 os << "(";
172 for (std::size_t i = 0; i < N; ++i) {
173 if (i > 0) os << ", ";
174 os << v.datas[i];
175 }
176 os << ")";
177 return os;
178 }
179
180 private:
181 template<typename ResultScalar, typename U, std::size_t... I, typename F>
182 constexpr auto make_binary(const Vector<N, U> &other,
183 std::index_sequence<I...>, F f) const {
184 return Vector<N, ResultScalar>(f(datas[I], other.datas[I])...);
185 }
186
187 template<typename ResultScalar, std::size_t... I, typename F>
188 constexpr auto make_unary(std::index_sequence<I...>, F f) const {
189 return Vector<N, ResultScalar>(f(datas[I])...);
190 }
191
192 template<typename ResultScalar, typename U, std::size_t... I, typename F>
193 constexpr auto make_scalar(U scalar,
194 std::index_sequence<I...>, F f) const {
195 return Vector<N, ResultScalar>(f(datas[I], scalar)...);
196 }
197
198 template<typename ResultScalar, typename UnitT, std::size_t... I>
199 constexpr auto make_as(std::index_sequence<I...>) const {
200 return Vector<N, ResultScalar>(datas[I].template As<UnitT>()...);
201 }
202 };
203
204 template<typename>
205 struct is_vector : std::false_type {
206 };
207
208 template<std::size_t N, typename QuantityT>
209 struct is_vector<Vector<N, QuantityT> > : std::true_type {
210 };
211
212 template<typename VecT>
213 inline constexpr auto is_vector_v = is_vector<VecT>::value;
214
215 template<std::size_t N, typename T>
216 struct is_vector_of_n : std::false_type {
217 };
218
219 template<std::size_t N, typename T>
220 struct is_vector_of_n<N, Vector<N, T> > : std::true_type {
221 };
222
223 template<std::size_t N, typename T>
225
226 template<typename T, std::size_t N, typename U,
227 typename = std::enable_if_t<!is_vector_of_n_v<N, T>> >
228 constexpr auto operator*(T scalar, const Vector<N, U> &v) {
229 return v * scalar;
230 }
231}
232
233#endif //PHYTH_VECTOR_HPP
auto sqrt(Quantity< UnitT > q)
Square root of a quantity.
constexpr auto operator*(Quantity< U1 > a, Quantity< U2 > b)
Multiply two quantities.
Definition Quantity.hpp:524
constexpr bool is_vector_of_n_v
Definition Vector.hpp:224
constexpr bool is_unit_v
Definition Unit.hpp:79
constexpr auto is_vector_v
Definition Vector.hpp:213
constexpr Vector & operator/=(U scalar)
Definition Vector.hpp:110
constexpr Vector & operator+=(const Vector< N, U > &other)
Definition Vector.hpp:89
constexpr Vector()=default
auto As() const
Definition Vector.hpp:165
auto Length() const
Definition Vector.hpp:135
constexpr Vector & operator*=(U scalar)
Definition Vector.hpp:103
constexpr auto make_as(std::index_sequence< I... >) const
Definition Vector.hpp:199
constexpr auto make_binary(const Vector< N, U > &other, std::index_sequence< I... >, F f) const
Definition Vector.hpp:182
constexpr T & operator[](const size_t i)
Definition Vector.hpp:40
std::array< T, N > datas
Definition Vector.hpp:20
constexpr bool operator==(const Vector &other) const
Definition Vector.hpp:116
auto Project(const Vector< N, U > &other) const
Definition Vector.hpp:160
friend std::ostream & operator<<(std::ostream &os, const Vector &v)
Definition Vector.hpp:170
constexpr auto make_scalar(U scalar, std::index_sequence< I... >, F f) const
Definition Vector.hpp:193
constexpr Vector & operator-=(const Vector< N, U > &other)
Definition Vector.hpp:96
constexpr auto operator+(const Vector< N, U > &other) const
Definition Vector.hpp:49
constexpr const T & operator[](const size_t i) const
Definition Vector.hpp:44
constexpr bool operator!=(const Vector &other) const
Definition Vector.hpp:123
auto LengthSquared() const
Definition Vector.hpp:127
constexpr auto operator*(U scalar) const
Definition Vector.hpp:73
constexpr Vector(Args... comps)
Definition Vector.hpp:29
constexpr auto Dot(const Vector< N, U > &other) const
Definition Vector.hpp:151
auto Normalized() const
Definition Vector.hpp:139
constexpr auto make_unary(std::index_sequence< I... >, F f) const
Definition Vector.hpp:188
constexpr auto operator-() const
Definition Vector.hpp:64
constexpr const T & At(const size_t i) const
Definition Vector.hpp:36
constexpr auto operator/(U scalar) const
Definition Vector.hpp:81
constexpr auto operator-(const Vector< N, U > &other) const
Definition Vector.hpp:57
constexpr T & At(const size_t i)
Definition Vector.hpp:32