utility 2026.1.9
A comprehensive C++ utilities library tailored for the development of modern desktop and extended reality (XR) applications.
Loading...
Searching...
No Matches
vector.hpp
1/*
2 Copyright (c) 2026 ETIB Corporation
3
4 Permission is hereby granted, free of charge, to any person obtaining a copy of
5 this software and associated documentation files (the "Software"), to deal in
6 the Software without restriction, including without limitation the rights to
7 use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
8 of the Software, and to permit persons to whom the Software is furnished to do
9 so, subject to the following conditions:
10
11 The above copyright notice and this permission notice shall be included in all
12 copies or substantial portions of the Software.
13
14 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20 SOFTWARE.
21 */
22
23#pragma once
24
25#include <cmath>
26#include <stdexcept>
27#include <string>
28#include <type_traits>
29#include <utility>
30#include <ostream>
31
32#include <glm/exponential.hpp>
33#include <glm/geometric.hpp>
34#include <glm/vector_relational.hpp>
35
36#include <glm/vec2.hpp>
37#include <glm/vec3.hpp>
38#include <glm/vec4.hpp>
39
40// Basic macros for component access - can be used for readability in client
41// code
42#define VEC_X 0
43#define VEC_Y 1
44#define VEC_Z 2
45#define VEC_W 3
46
47namespace utility::math
48{
49
50 using glm::cross;
51 using glm::distance;
52 using glm::dot;
53 using glm::faceforward;
54 using glm::length;
55 using glm::normalize;
56 using glm::reflect;
57 using glm::refract;
58
59 using glm::exp;
60 using glm::exp2;
61 using glm::inversesqrt;
62 using glm::log;
63 using glm::log2;
64 using glm::pow;
65 using glm::sqrt;
66
71 template<typename Type>
73 std::is_floating_point_v<Type> || std::is_integral_v<Type>;
74
80 template<CanBeVectorComponent VectorComponentType,
81 std::size_t VectorDimension>
82 class Vector: public glm::vec<VectorDimension, VectorComponentType>
83 {
84 public:
88 Vector(void)
89 : glm::vec<VectorDimension, VectorComponentType>(0)
90 {
91 }
92
97 explicit Vector(const glm::vec<VectorDimension, VectorComponentType> &v)
98 : glm::vec<VectorDimension, VectorComponentType>(v)
99 {
100 }
101
108 Vector(std::initializer_list<VectorComponentType> values)
109 {
110 if (values.size() != VectorDimension) {
111 throw std::invalid_argument("Vector requires exactly "
112 + std::to_string(VectorDimension)
113 + " components");
114 }
115 const auto it = values.begin();
116 for (std::size_t i = 0; i < VectorDimension; ++i) {
117 (*this)[i] = *(it + i);
118 }
119 }
120
125 explicit Vector(VectorComponentType value)
126 : glm::vec<VectorDimension, VectorComponentType>(value)
127 {
128 }
129
134 Vector(const Vector &other) = default;
135
140 Vector(Vector &&other) noexcept = default;
141
145 ~Vector(void) = default;
146
152 Vector &operator=(const Vector &other) = default;
153
159 Vector &operator=(Vector &&other) noexcept = default;
160
166 Vector operator+(const Vector &rhs) const noexcept
167 {
168 return Vector(
169 static_cast<const glm::vec<VectorDimension, VectorComponentType>
170 &>(*this)
171 + static_cast<
172 const glm::vec<VectorDimension, VectorComponentType> &>(
173 rhs));
174 }
175
181 Vector &operator+=(const Vector &rhs) noexcept
182 {
183 *static_cast<glm::vec<VectorDimension, VectorComponentType> *>(
184 this) +=
185 static_cast<
186 const glm::vec<VectorDimension, VectorComponentType> &>(
187 rhs);
188 return *this;
189 }
190
196 Vector operator-(const Vector &rhs) const noexcept
197 {
198 return Vector(
199 static_cast<const glm::vec<VectorDimension, VectorComponentType>
200 &>(*this)
201 - static_cast<
202 const glm::vec<VectorDimension, VectorComponentType> &>(
203 rhs));
204 }
205
211 Vector &operator-=(const Vector &rhs) noexcept
212 {
213 *static_cast<glm::vec<VectorDimension, VectorComponentType> *>(
214 this) -=
215 static_cast<
216 const glm::vec<VectorDimension, VectorComponentType> &>(
217 rhs);
218 return *this;
219 }
220
226 Vector operator*(VectorComponentType scalar) const noexcept
227 {
228 return Vector(
229 static_cast<const glm::vec<VectorDimension, VectorComponentType>
230 &>(*this)
231 * scalar);
232 }
233
239 Vector &operator*=(VectorComponentType scalar) noexcept
240 {
241 *static_cast<glm::vec<VectorDimension, VectorComponentType> *>(
242 this) *= scalar;
243 return *this;
244 }
245
252 Vector operator/(VectorComponentType scalar) const
253 {
254 if (scalar == VectorComponentType { 0 }) {
255 throw std::invalid_argument("Vector division by zero");
256 }
257 return Vector(
258 static_cast<const glm::vec<VectorDimension, VectorComponentType>
259 &>(*this)
260 / scalar);
261 }
262
269 Vector &operator/=(VectorComponentType scalar)
270 {
271 if (scalar == VectorComponentType { 0 }) {
272 throw std::invalid_argument("Vector division by zero");
273 }
274 *static_cast<glm::vec<VectorDimension, VectorComponentType> *>(
275 this) /= scalar;
276 return *this;
277 }
278
284 Vector operator*(const Vector &rhs) const noexcept
285 {
286 return Vector(
287 static_cast<const glm::vec<VectorDimension, VectorComponentType>
288 &>(*this)
289 * static_cast<
290 const glm::vec<VectorDimension, VectorComponentType> &>(
291 rhs));
292 }
293
299 Vector &operator*=(const Vector &rhs) noexcept
300 {
301 *static_cast<glm::vec<VectorDimension, VectorComponentType> *>(
302 this) *=
303 static_cast<
304 const glm::vec<VectorDimension, VectorComponentType> &>(
305 rhs);
306 return *this;
307 }
308
315 Vector operator/(const Vector &rhs) const
316 {
317 for (std::size_t i = 0; i < VectorDimension; ++i) {
318 if (rhs[i] == VectorComponentType { 0 }) {
319 throw std::invalid_argument("Vector division by zero");
320 }
321 }
322 return Vector(
323 static_cast<const glm::vec<VectorDimension, VectorComponentType>
324 &>(*this)
325 / static_cast<
326 const glm::vec<VectorDimension, VectorComponentType> &>(
327 rhs));
328 }
329
337 {
338 for (std::size_t i = 0; i < VectorDimension; ++i) {
339 if (rhs[i] == VectorComponentType { 0 }) {
340 throw std::invalid_argument("Vector division by zero");
341 }
342 }
343 *static_cast<glm::vec<VectorDimension, VectorComponentType> *>(
344 this) /=
345 static_cast<
346 const glm::vec<VectorDimension, VectorComponentType> &>(
347 rhs);
348 return *this;
349 }
350
359 bool operator==(const Vector &rhs) const noexcept
360 {
361 return static_cast<
362 const glm::vec<VectorDimension, VectorComponentType> &>(
363 *this)
364 == static_cast<
365 const glm::vec<VectorDimension, VectorComponentType> &>(
366 rhs);
367 }
368
378 bool equalsEpsilon(const Vector &rhs,
379 VectorComponentType epsilon = VectorComponentType {
380 1e-5 }) const
381 {
382 for (std::size_t i = 0; i < VectorDimension; ++i) {
383 if (std::abs((*this)[i] - rhs[i]) > epsilon) {
384 return false;
385 }
386 }
387 return true;
388 }
389
395 bool operator!=(const Vector &rhs) const noexcept
396 {
397 return !(*this == rhs);
398 }
399
404 Vector operator-() const noexcept
405 {
406 return Vector(
407 -static_cast<
408 const glm::vec<VectorDimension, VectorComponentType> &>(
409 *this));
410 }
411
419 friend Vector operator*(VectorComponentType scalar, const Vector &vec)
420 {
421 return vec * scalar;
422 }
423 };
424
425 template<CanBeVectorComponent VectorComponentType,
426 std::size_t VectorDimension>
427 VectorComponentType
428 dot(const Vector<VectorComponentType, VectorDimension> &lhs,
429 const Vector<VectorComponentType, VectorDimension> &rhs)
430 {
431 return glm::dot(
432 static_cast<const glm::vec<VectorDimension, VectorComponentType> &>(
433 lhs),
434 static_cast<const glm::vec<VectorDimension, VectorComponentType> &>(
435 rhs));
436 }
437
438 template<CanBeVectorComponent VectorComponentType>
439 Vector<VectorComponentType, 3>
440 cross(const Vector<VectorComponentType, 3> &lhs,
441 const Vector<VectorComponentType, 3> &rhs)
442 {
443 return Vector<VectorComponentType, 3>(glm::cross(
444 static_cast<const glm::vec<3, VectorComponentType> &>(lhs),
445 static_cast<const glm::vec<3, VectorComponentType> &>(rhs)));
446 }
447
448 template<CanBeVectorComponent VectorComponentType,
449 std::size_t VectorDimension>
450 Vector<VectorComponentType, VectorDimension>
451 normalize(const Vector<VectorComponentType, VectorDimension> &vector)
452 {
453 return Vector<VectorComponentType, VectorDimension>(glm::normalize(
454 static_cast<const glm::vec<VectorDimension, VectorComponentType> &>(
455 vector)));
456 }
457
461 using Vector2F = Vector<float, 2>;
462
466 using Vector2D = Vector<double, 2>;
467
471 using Vector2I = Vector<int, 2>;
472
476 using Vector2UI = Vector<unsigned int, 2>;
477
481 using Vector3F = Vector<float, 3>;
482
486 using Vector3D = Vector<double, 3>;
487
491 using Vector3I = Vector<int, 3>;
492
496 using Vector3UI = Vector<unsigned int, 3>;
497
501 using Vector4F = Vector<float, 4>;
502
506 using Vector4D = Vector<double, 4>;
507
511 using Vector4I = Vector<int, 4>;
512
516 using Vector4UI = Vector<unsigned int, 4>;
517
524 std::ostream &operator<<(std::ostream &stream, const Vector2F &vector);
525
532 std::ostream &operator<<(std::ostream &stream, const Vector2D &vector);
533
540 std::ostream &operator<<(std::ostream &stream, const Vector2I &vector);
541
548 std::ostream &operator<<(std::ostream &stream, const Vector2UI &vector);
549
556 std::ostream &operator<<(std::ostream &stream, const Vector3F &vector);
557
564 std::ostream &operator<<(std::ostream &stream, const Vector3D &vector);
565
572 std::ostream &operator<<(std::ostream &stream, const Vector3I &vector);
573
580 std::ostream &operator<<(std::ostream &stream, const Vector3UI &vector);
581
588 std::ostream &operator<<(std::ostream &stream, const Vector4F &vector);
589
596 std::ostream &operator<<(std::ostream &stream, const Vector4D &vector);
597
604 std::ostream &operator<<(std::ostream &stream, const Vector4I &vector);
605
612 std::ostream &operator<<(std::ostream &stream, const Vector4UI &vector);
613
614} // namespace utility::math
3D vector class inheriting from glm::vec3.
Definition vector.hpp:83
Vector(std::initializer_list< VectorComponentType > values)
Construct from initializer list of float values.
Definition vector.hpp:108
Vector & operator*=(VectorComponentType scalar) noexcept
Scalar multiplication assignment.
Definition vector.hpp:239
bool operator==(const Vector &rhs) const noexcept
Equality comparison.
Definition vector.hpp:359
Vector(VectorComponentType value)
Construct by filling all components with the same float value.
Definition vector.hpp:125
~Vector(void)=default
Default destructor for Vector.
Vector(Vector &&other) noexcept=default
Move constructor.
Vector operator-(const Vector &rhs) const noexcept
Vector subtraction.
Definition vector.hpp:196
Vector & operator=(Vector &&other) noexcept=default
Move assignment operator.
Vector operator/(VectorComponentType scalar) const
Scalar division.
Definition vector.hpp:252
Vector(const glm::vec< VectorDimension, VectorComponentType > &v)
Construct from a GLM vector.
Definition vector.hpp:97
Vector & operator+=(const Vector &rhs) noexcept
Vector addition assignment.
Definition vector.hpp:181
Vector operator*(VectorComponentType scalar) const noexcept
Scalar multiplication.
Definition vector.hpp:226
bool operator!=(const Vector &rhs) const noexcept
Inequality comparison.
Definition vector.hpp:395
Vector(void)
Default constructor initializing vector values to zero.
Definition vector.hpp:88
Vector operator*(const Vector &rhs) const noexcept
Element-wise multiplication.
Definition vector.hpp:284
bool equalsEpsilon(const Vector &rhs, VectorComponentType epsilon=VectorComponentType { 1e-5 }) const
Approximate equality using an epsilon threshold.
Definition vector.hpp:378
Vector operator-() const noexcept
Unary negation.
Definition vector.hpp:404
Vector & operator*=(const Vector &rhs) noexcept
Element-wise multiplication assignment.
Definition vector.hpp:299
Vector & operator=(const Vector &other)=default
Copy assignment operator.
Vector operator/(const Vector &rhs) const
Element-wise division.
Definition vector.hpp:315
Vector & operator-=(const Vector &rhs) noexcept
Vector subtraction assignment.
Definition vector.hpp:211
Vector(const Vector &other)=default
Copy constructor.
Vector & operator/=(VectorComponentType scalar)
Scalar division assignment.
Definition vector.hpp:269
friend Vector operator*(VectorComponentType scalar, const Vector &vec)
Friend function for scalar multiplication with scalar on the left.
Definition vector.hpp:419
Vector & operator/=(const Vector &rhs)
Element-wise division assignment.
Definition vector.hpp:336
Vector operator+(const Vector &rhs) const noexcept
Vector addition.
Definition vector.hpp:166
Concept to constrain vector component type.
Definition vector.hpp:72