14 #include <type_traits>
29 template <
typename T, std::
size_t N>
31 static_assert(N > 1,
"Are you fucking kidding me?");
43 template <
typename... Ts>
45 : data{
static_cast<T
>(vals)...} {
46 static_assert(
sizeof...(Ts) == N,
"Number of constructor arguments do not "
47 "match the template parameter N!");
51 : data{
static_cast<T
>(0)} {
57 struct VectorImpl<T, 2> {
66 VectorImpl(T x, T y) : x(x), y(y) {}
67 VectorImpl() : VectorImpl(0, 0) {}
72 struct VectorImpl<T, 3> {
82 VectorImpl(T x, T y, T z) : x(x), y(y), z(z) {}
83 VectorImpl() : VectorImpl(0, 0, 0) {}
88 struct VectorImpl<T, 4> {
99 VectorImpl(T x, T y, T z, T w) : x(x), y(y), z(z), w(w) {}
100 VectorImpl() : VectorImpl(0, 0, 0, 0) {}
113 constexpr std::size_t vecMin(std::size_t a, std::size_t b) {
114 return (a > b) ? b : a;
118 constexpr
double vecPI = 3.14159265359;
123 template <
typename T, std::
size_t N>
137 template <
typename T, std::
size_t N>
144 template <
typename U>
146 for(
int i = 0; i < N; ++i) {
147 this->data[i] =
static_cast<T
>(other.data[i]);
156 static constexpr std::size_t size = N;
159 T& operator[] (std::size_t index) {
161 throw std::out_of_range(
"Invalid subscript");
163 return this->data[index];
166 T operator[] (std::size_t index)
const {
168 throw std::out_of_range(
"Invalid subscript");
170 return this->data[index];
175 template <
typename OT>
176 Vector<T, N>& operator+=(
const Vector<OT, N>& v) {
177 for(
int i = 0; i < N; ++i) {
178 this->data[i] += v.data[i];
183 template <
typename OT>
184 Vector<T, N>& operator-=(
const Vector<OT, N>& v) {
185 for(
int i = 0; i < N; ++i) {
186 this->data[i] -= v.data[i];
191 template <
typename S>
192 Vector<T, N>& operator*=(S scalar) {
193 for(
int i = 0; i < N; ++i) {
194 this->data[i] *= scalar;
199 template <
typename S>
200 Vector<T, N>& operator/=(S scalar) {
201 for(
int i = 0; i < N; ++i) {
202 this->data[i] /= scalar;
209 Vector<T, N> operator+()
const {
213 Vector<T, N> operator-()
const {
214 Vector<T, N> out(*
this);
215 for(
int i = 0; i < N; ++i) {
216 out.data[i] = -out.data[i];
223 bool operator==(
const Vector<T, N>& other)
const {
224 for(
int i = 0; i < N; ++i) {
225 if(this->data[i] != other.data[i])
231 bool operator!=(
const Vector<T, N>& other)
const {
232 return !(*
this == other);
236 bool operator<(const Vector<T, N>& other)
const {
237 for(
int i = 0; i < N; ++i) {
238 if(this->data[i] < other.data[i])
240 if(this->data[i] > other.data[i])
246 bool operator>(
const Vector<T, N>& other)
const {
247 return (other < *
this);
250 bool operator<=(const Vector<T, N>& other)
const {
251 return (*
this < other || *
this == other);
254 bool operator>=(
const Vector<T, N>& other)
const {
255 return (other < *
this || *
this == other);
260 T lengthSquared()
const {
262 for(
int i = 0; i < N; ++i) {
263 out += this->data[i] * this->data[i];
268 template <
typename Tout = decltype(sqrt(T(0)))>
269 Tout length()
const {
270 return static_cast<Tout
>(sqrt(lengthSquared()));
273 auto phi() const -> decltype(atan2(T(0), T(0))) {
274 static_assert(N >= 2,
"You cannot calculate phi of a vector which "
275 "dimension is lower than 2!");
276 auto phi = atan2(this->data[1], this->data[0]);
277 return (phi < 0) ? (phi + 2*internal::vecPI) : phi;
280 auto theta() const -> decltype(acos(T(0))) {
281 static_assert(N >= 3,
"You cannot calculate theta of a vector which "
282 "dimension is lower than 3!");
283 return acos(this->data[2] / length());
286 T linearSize()
const {
287 T out = this->data[0];
288 for(
int i = 1; i < N; ++i) {
289 out *= this->data[i];
296 Vector<T, N>& normalize() {
297 auto lensq = lengthSquared();
299 (*this) /= sqrt(lensq);
303 Vector<T, N> normalized()
const {
304 return Vector<T, N>(*this).normalize();
307 template <
typename To>
308 Vector<T, N>& scale(
const Vector<To, N>& o) {
309 for(
int i = 0; i < N; ++i) {
310 this->data[i] *= o.data[i];
315 template <
typename To>
316 Vector<T, N> scaled(
const Vector<To, N>& o) {
317 return Vector<T, N>(*this).scale(o);
320 template <
typename Ta>
321 Vector<T, N>& rotate(Ta phi, Ta theta) {
322 *
this = rotated(phi, theta);
326 template <
typename Ta>
327 Vector<T, N> rotated(Ta phi, Ta theta)
const {
329 cos(theta) * cos(phi) * this->x
330 - cos(theta) * sin(phi) * this->y
331 + sin(theta) * this->z,
333 + cos(phi) * this->y,
334 -sin(theta) * cos(phi) * this->x
335 + sin(theta) * sin(phi) * this->y
336 + cos(theta) * this->z
340 template <
typename To>
341 Vector<T, N>& reflect(
const Vector<To, N>& normal) {
342 *
this -= normal * 2 * dot(*
this, normal);
346 template <
typename To>
347 auto reflected(
const Vector<To, N>& normal)
348 const -> Vector<decltype(T(0) - To(0)), N> {
349 return Vector<decltype(T(0) - To(0)), N>(*this).reflect(normal);
359 template <
typename T1,
typename T2, std::
size_t N>
360 auto operator+(
const Vector<T1, N>& v1,
const Vector<T2, N>& v2)
361 -> Vector<decltype(T1(0) + T2(0)), N> {
362 Vector<decltype(T1(0) + T2(0)), N> out(v1);
366 template <
typename T1,
typename T2, std::
size_t N>
367 auto operator-(
const Vector<T1, N>& v1,
const Vector<T2, N>& v2)
368 -> Vector<decltype(T1(0) - T2(0)), N> {
369 Vector<decltype(T1(0) - T2(0)), N> out(v1);
373 template <
typename T1,
typename T2, std::
size_t N>
374 auto operator*(
const Vector<T1, N>& v, T2 scalar)
375 -> Vector<decltype(T1(0) * T2(0)), N> {
376 Vector<decltype(T1(0) * T2(0)), N> out(v);
377 return out *= scalar;
380 template <
typename T1,
typename T2, std::
size_t N>
381 auto operator*(T2 scalar,
const Vector<T1, N>& v)
382 -> Vector<decltype(T1(0) * T2(0)), N> {
383 Vector<decltype(T1(0) * T2(0)), N> out(v);
384 return out *= scalar;
387 template <
typename T1,
typename T2, std::
size_t N>
388 auto operator/(
const Vector<T1, N>& v, T2 scalar)
389 -> Vector<decltype(T1(0) / T2(0)), N> {
390 Vector<decltype(T1(0) / T2(0)), N> out(v);
391 return out *= scalar;
394 template <
typename T1,
typename T2, std::
size_t N>
395 auto operator/(T2 scalar,
const Vector<T1, N>& v)
396 -> Vector<decltype(T1(0) / T2(0)), N> {
397 Vector<decltype(T1(0) / T2(0)), N> out(v);
398 return out *= scalar;
403 template <
typename T1,
typename T2, std::
size_t N>
404 auto dot(
const Vector<T1, N>& lh,
const Vector<T2, N>& rh)
405 -> decltype(T1(0) + T2(0)) {
406 decltype(T1(0) + T2(0)) out = 0;
407 for(
int i = 0; i < N; ++i) {
408 out += lh.data[i] * rh.data[i];
413 template <
typename T1,
typename T2>
414 auto cross(
const Vector<T1, 3>& lh,
const Vector<T2, 3>& rh)
415 -> Vector<decltype(T1(0) * T2(0)), 3> {
416 return Vector<decltype(T1(0) + T2(0)), 3>(lh.y * rh.z - lh.z * rh.y,
417 lh.z * rh.x - lh.x * rh.z,
418 lh.x * rh.y - lh.y * rh.x);
422 template <
typename T1,
typename T2, std::
size_t N>
423 auto distance(
const Vector<T1, N>& a,
const Vector<T2, N>& b)
424 -> decltype((a - b).length()) {
425 return (a - b).length();
428 template <
typename T1,
typename T2, std::
size_t N>
429 auto angle(
const Vector<T1, N>& a,
const Vector<T2, N>& b)
430 -> decltype(acos(a.length() * b.length())) {
431 return acos(dot(a, b) / (a.length() * b.length()));
436 template <
typename Tdst,
typename Tsrc, std::
size_t N>
437 Vector<Tdst, N> vector_cast(
const Vector<Tsrc, N>& in) {
439 for(
int i = 0; i < N; ++i) {
440 out.data[i] =
static_cast<Tdst
>(in.data[i]);
445 template <std::
size_t Ndst, std::
size_t Nsrc,
typename T>
446 Vector<T, Ndst> vector_cast(
const Vector<T, Nsrc>& in) {
448 for(
int i = 0; i < internal::vecMin(Ndst, Nsrc); ++i) {
449 out.data[i] = in.data[i];
454 template <
typename Tdst, std::
size_t Ndst,
typename Tsrc, std::
size_t Nsrc>
455 Vector<Tdst, Ndst> vector_cast(
const Vector<Tsrc, Nsrc>& in) {
456 Vector<Tdst, Ndst> out;
457 for(
int i = 0; i < internal::vecMin(Ndst, Nsrc); ++i) {
458 out.data[i] =
static_cast<Tdst
>(in.data[i]);
468 template <
typename T>
469 using Vec2 = Vector<T, 2>;
470 using Vec2f = Vector<float, 2>;
471 using Vec2i = Vector<int, 2>;
473 template <
typename T>
474 using Vec3 = Vector<T, 3>;
475 using Vec3f = Vector<float, 3>;
476 using Vec3i = Vector<int, 3>;
478 template <
typename T>
479 using Vec4 = Vector<T, 4>;
480 using Vec4f = Vector<float, 4>;
481 using Vec4i = Vector<int, 4>;
488 template <
typename T, std::
size_t N>
489 class VectorIterator :
public Vector<T, N> {
492 Vector<T, N> m_target;
494 template <
typename Tf, std::
size_t Nf>
495 friend typename Vector<Tf, Nf>::iterator begin(Vector<Tf, Nf> v);
496 template <
typename Tf, std::
size_t Nf>
497 friend typename Vector<Tf, Nf>::iterator end(Vector<Tf, Nf> v);
499 using iterator = void;
501 VectorIterator(Vector<T, N> v) : m_target(v) {}
504 this->data[0] = m_target.data[0];
520 Vector<T, N> operator*()
const {
521 return static_cast<Vector<T, N>
>(*this);
524 VectorIterator& operator++() {
525 for(
int i = N - 1; i > 0; --i) {
526 if(++this->data[i] < m_target.data[i])
535 VectorIterator<T, N> operator++(
int) {
536 VectorIterator<T, N> pre(*
this);
542 template <
typename T, std::
size_t N>
543 typename Vector<T, N>::iterator begin(Vector<T, N> v) {
544 static_assert(!std::is_floating_point<T>::value,
545 "You cannot obtain a iterator of an floating pointer vector type!");
549 template <
typename T, std::
size_t N>
550 typename Vector<T, N>::iterator end(Vector<T, N> v) {
551 static_assert(!std::is_floating_point<T>::value,
552 "You cannot obtain a iterator of an floating pointer vector type!");
553 typename Vector<T, N>::iterator out(v);
Represents a vector with arbitrary dimension and type of elements.
Definition: VectorCore.hpp:138
Specialized helper base struct for Vector.
Definition: VectorCore.hpp:30
VectorIterator< T, N > iterator
iterator type
Definition: VectorCore.hpp:152
Definition: VectorCore.hpp:124
int type
type of the vector's elements
Definition: VectorCore.hpp:154