pbpt
Loading...
Searching...
No Matches
vector.hpp
Go to the documentation of this file.
1#pragma once
2
3#include <algorithm>
4#include <array>
5#include <concepts>
6#include <stdexcept>
7#include <type_traits>
8#include <iostream>
9#include <functional>
10#include <vector>
11
12#include "global.hpp"
13#include "function.hpp"
14
19
20namespace pbpt::math {
21
33template<typename T, int N>
34requires (N > 0) && std::is_floating_point_v<T>
35class Vector {
36private:
37 std::array<T, N> m_data{};
38
39public:
40 // --- 静态工厂函数 (Static Factory Functions) ---
41
46 static constexpr Vector filled(T value) noexcept {
47 Vector vec;
48 vec.m_data.fill(value);
49 return vec;
50 }
51
56 static constexpr Vector zeros() noexcept { return filled(0.0); }
57
62 static constexpr Vector ones() noexcept { return filled(1.0); }
63
64 // --- 构造函数 (Constructors) ---
65
69 constexpr Vector() noexcept = default;
70
79 template<std::convertible_to<T>... Args>
80 requires(sizeof...(Args) == N)
81 constexpr explicit Vector(Args&&... args) noexcept {
82 m_data = {static_cast<T>(args)...};
83 }
84
85 // --- 访问器 (Accessors) ---
86
88 constexpr T& x() noexcept requires(N > 0) { return m_data[0]; }
90 constexpr T& y() noexcept requires(N > 1) { return m_data[1]; }
92 constexpr T& z() noexcept requires(N > 2) { return m_data[2]; }
94 constexpr T& w() noexcept requires(N > 3) { return m_data[3]; }
95
97 constexpr const T& x() const noexcept requires(N > 0) { return m_data[0]; }
99 constexpr const T& y() const noexcept requires(N > 1) { return m_data[1]; }
101 constexpr const T& z() const noexcept requires(N > 2) { return m_data[2]; }
103 constexpr const T& w() const noexcept requires(N > 3) { return m_data[3]; }
104
106 constexpr int dims() const noexcept { return N; }
107
108 // --- 下标访问 (Subscript Access) ---
109
117 constexpr const T& operator[](int index) const {
118 if (index < 0 || index >= N) {
119 if (std::is_constant_evaluated()) {
120 throw "Compile-time error: Index out of range";
121 } else {
122 throw std::out_of_range("Index out of range");
123 }
124 }
125 return m_data[index];
126 }
127
135 constexpr T& operator[](int index) {
136 if (index < 0 || index >= N) {
137 if (std::is_constant_evaluated()) {
138 throw "Compile-time error: Index out of range";
139 } else {
140 throw std::runtime_error("Index out of range");
141 }
142 }
143 return m_data[index];
144 }
145
153 constexpr const T& at(int index) const {
154 if (index < 0 || index >= N) {
155 if (std::is_constant_evaluated()) {
156 throw "Compile-time error: Index out of range";
157 } else {
158 throw std::out_of_range("Index out of range");
159 }
160 }
161 return m_data[index];
162 }
163
164 // --- 一元运算符 (Unary Operators) ---
165
170 constexpr Vector operator-() const noexcept {
171 Vector result{};
172 for (int i = 0; i < N; i++) result[i] = -m_data[i];
173 return result;
174 }
175
176 // --- 复合赋值运算符 (Compound Assignment Operators) ---
177
179 constexpr Vector& operator+=(const Vector& rhs) noexcept {
180 for (int i = 0; i < N; i++) m_data[i] += rhs[i];
181 return *this;
182 }
183
184 constexpr Vector& operator-=(const Vector& rhs) noexcept {
185 for (int i = 0; i < N; i++) m_data[i] -= rhs[i];
186 return *this;
187 }
188
189 constexpr Vector& operator*=(const T& rhs) noexcept {
190 for (int i = 0; i < N; i++) m_data[i] *= rhs;
191 return *this;
192 }
193
197 constexpr bool operator==(const Vector& rhs) const noexcept {
198 for (int i = 0; i < N; i++) {
199 if (!is_equal(m_data[i], rhs[i])) return false;
200 }
201 return true;
202 }
203
205 constexpr bool operator!=(const Vector& rhs) const noexcept {
206 return !(*this == rhs);
207 }
208
215 constexpr bool is_normalized() const {
216 return is_equal(length(), 1.0);
217 }
218
225 constexpr bool is_zero() const {
226 for (int i = 0; i < N; i++) {
227 if (!is_equal(m_data[i], 0.0)) return false;
228 }
229 return true;
230 }
231
232
239 constexpr bool has_nan() const {
240 for (int i = 0; i < N; i++) {
241 if (std::isnan(m_data[i])) return true;
242 }
243 return false;
244 }
245
249 template<std::convertible_to<T> U>
250 constexpr Vector operator/=(const U& value) const noexcept {
251 if (value == 0) {
252 if (std::is_constant_evaluated()) {
253 throw "Compile-time error: Division by zero";
254 } else {
255 throw std::runtime_error("Division by zero");
256 }
257 }
258 Float inv = 1.0 / value;
259 for (int i = 0; i < N; i++) m_data[i] *= inv;
260 return *this;
261 }
262
263 // --- 向量数学运算 (Vector Math Operations) ---
264
271 constexpr T length_squared() const noexcept {
272 T result = 0;
273 for (int i = 0; i < N; i++)
274 result += m_data[i] * m_data[i];
275 return result;
276 }
277
283 constexpr T length() const {
285 }
286
294 constexpr Vector normalized() const {
295 Vector result = *this;
296 T len = length();
297 if (len == 0) {
298 if (std::is_constant_evaluated()) {
299 throw "Compile-time error: Cannot normalize a zero vector";
300 } else {
301 throw std::runtime_error("Cannot normalize a zero vector");
302 }
303 }
304 return result * (1.0 / len);
305 }
306
313 constexpr Vector& normalize() {
314 T len = length();
315 if (len == 0) {
316 if (std::is_constant_evaluated()) {
317 throw "Compile-time error: Cannot normalize a zero vector";
318 } else {
319 throw std::runtime_error("Cannot normalize a zero vector");
320 }
321 }
322 return *this *= (1.0 / len);
323 }
324
330 constexpr T dot(const Vector& rhs) const noexcept {
331 T result = 0;
332 for (int i = 0; i < N; i++) result += m_data[i] * rhs.m_data[i];
333 return result;
334 }
335
342 constexpr Vector cross(const Vector& rhs) const noexcept requires(N == 3) {
343 return Vector(
344 y() * rhs.z() - z() * rhs.y(),
345 z() * rhs.x() - x() * rhs.z(),
346 x() * rhs.y() - y() * rhs.x()
347 );
348 }
349
350 constexpr T product() const noexcept {
351 T result = 1;
352 for (int i = 0; i < N; i++) result *= m_data[i];
353 return result;
354 }
355
360 void apply(const std::function<void(T&, int)>& func) {
361 for (int i = 0; i < N; ++i) func(m_data[i], i);
362 }
363
365 constexpr Vector operator+(const Vector<T, N>& rhs) const noexcept {
366 auto result = *this;
367 result += rhs;
368 return result;
369 }
370
372 constexpr Vector operator-(const Vector<T, N>& rhs) const noexcept {
373 auto result = *this;
374 result -= rhs;
375 return result;
376 }
377
379 template<std::convertible_to<T> U>
380 constexpr Vector operator*(U value) const noexcept {
381 auto result = *this;
382 result *= static_cast<T>(value);
383 return result;
384 }
385
387 template<std::convertible_to<T> U>
388 friend constexpr Vector operator*(U lhs, const Vector<T, N>& rhs) noexcept {
389 return rhs * static_cast<T>(lhs);
390 }
391
395 constexpr Vector operator*(const Vector<T, N>& rhs) const noexcept {
396 Vector<T, N> result{};
397 for (int i = 0; i < N; i++) result[i] = (*this)[i] * rhs[i];
398 return result;
399 }
400
404 template <std::convertible_to<T> U>
405 constexpr Vector operator/(U rhs) const {
406 Vector result = *this;
407 result /= static_cast<T>(rhs);
408 return result;
409 }
410
418 friend std::ostream& operator<<(std::ostream& os, const Vector& vec) {
419 os << "Vec" << N << "(";
420 for (int i = 0; i < N; ++i) {
421 os << vec[i] << (i == N - 1 ? "" : ", ");
422 }
423 os << ')';
424 return os;
425 }
426
431 constexpr int max_dim() const {
432 return std::max_element(m_data.begin(), m_data.end()) - m_data.begin();
433 }
434
439 constexpr T max() const {
440 return *std::max_element(m_data.begin(), m_data.end());
441 }
442
447 constexpr int min_dim() const {
448 return std::min_element(m_data.begin(), m_data.end()) - m_data.begin();
449 }
450
455 constexpr T min() const {
456 return *std::min_element(m_data.begin(), m_data.end());
457 }
458
465 template<typename ...Args>
466 requires (sizeof...(Args) == N)
467 constexpr Vector permuted(Args ...args) const {
468 Vector result;
469 int i = 0;
470 ((result[i++] = (*this)[args]), ...);
471 return result;
472 }
473
480 template<typename ...Args>
481 requires (sizeof...(Args) == N)
482 constexpr Vector& permute(Args ...args) {
483 *this = permuted(args...);
484 return *this;
485 }
486
487
488};
489
496
497template<typename T, int N>
498constexpr inline std::vector<Vector<T, N>> get_orthogonal_bases(const Vector<T, N>& base) {
499 if constexpr (base.is_zero()) {
500 if (std::is_constant_evaluated()) {
501 throw "Base vector is zero, orthogonal bases are undefined.";
502 } else {
503 throw std::invalid_argument("Base vector is zero, orthogonal bases are undefined.");
504 }
505 }
506 //TODO
507 return {};
508}
509
516template<typename T>
517constexpr inline std::vector<Vector<T, 2>> get_orthogonal_bases(const Vector<T, 2>& base) {
518 if (base.is_zero()) {
519 if (std::is_constant_evaluated()) {
520 throw "Base vector is zero, orthogonal bases are undefined.";
521 } else {
522 throw std::invalid_argument("Base vector is zero, orthogonal bases are undefined.");
523 }
524 }
525 Vector<T, 2> u, v;
526 u = base.normalized();
527 v = Vector<T, 2>(-u.y(), u.x());
528 return {u, v};
529}
530
537template<typename T>
538constexpr inline std::vector<Vector<T, 3>> get_orthogonal_bases(const Vector<T, 3>& base) {
539 if (base.is_zero()) {
540 if (std::is_constant_evaluated()) {
541 throw "Base vector is zero, orthogonal bases are undefined.";
542 } else {
543 throw std::invalid_argument("Base vector is zero, orthogonal bases are undefined.");
544 }
545 }
546
547 Vector<T, 3> u, v, w;
548 u = base.normalized();
549 if (std::abs(u.x()) > std::abs(u.y())) {
550 T inv_len = T(1) / std::sqrt(u.x() * u.x() + u.z() * u.z());
551 v = Vector<T, 3>(-u.z() * inv_len, T(0), u.x() * inv_len);
552 } else {
553 T inv_len = T(1) / std::sqrt(u.y() * u.y() + u.z() * u.z());
554 v = Vector<T, 3>(T(0), u.z() * inv_len, -u.y() * inv_len);
555 }
556 w = u.cross(v);
557 return {u, v, w};
558}
559
560// --- 类型别名 (Type Aliases) ---
561
568
569template <typename T, int N>
570class Normal : public Vector<T, N> {
571public:
572 using Vector<T, N>::Vector;
573 constexpr Normal(const Vector<T, N>& vec) : Vector<T, N>(vec.normalized()) {}
574};
575
582
583
584} // namespace math
Definition vector.hpp:570
A template class for N-dimensional mathematical vectors.
Definition vector.hpp:35
constexpr T & operator[](int index)
Provides mutable access to the vector's components by index.
Definition vector.hpp:135
constexpr Vector operator-(const Vector< T, N > &rhs) const noexcept
Subtracts one vector from another component-wise.
Definition vector.hpp:372
constexpr int max_dim() const
Returns the dimension with the maximum value.
Definition vector.hpp:431
static constexpr Vector zeros() noexcept
Creates a vector with all components set to zero.
Definition vector.hpp:56
constexpr const T & at(int index) const
Provides const access to the vector's components by index.
Definition vector.hpp:153
constexpr Vector operator*(U value) const noexcept
Multiplies a vector by a scalar.
Definition vector.hpp:380
constexpr bool operator!=(const Vector &rhs) const noexcept
operator!=
Definition vector.hpp:205
constexpr T & x() noexcept
Accesses the first component (x-axis).
Definition vector.hpp:88
constexpr const T & x() const noexcept
Const access to the first component (x-axis).
Definition vector.hpp:97
constexpr Vector & operator+=(const Vector &rhs) noexcept
Adds another vector to this one component-wise.
Definition vector.hpp:179
constexpr T & z() noexcept
Accesses the third component (z-axis).
Definition vector.hpp:92
constexpr Vector & normalize()
Normalizes this vector in-place, making its length 1.
Definition vector.hpp:313
constexpr T & w() noexcept
Accesses the fourth component (w-axis).
Definition vector.hpp:94
constexpr Vector() noexcept=default
Default constructor. Initializes all components to zero.
friend std::ostream & operator<<(std::ostream &os, const Vector &vec)
Stream insertion operator for printing the vector.
Definition vector.hpp:418
constexpr bool operator==(const Vector &rhs) const noexcept
operator== ,compare two vector component by component
Definition vector.hpp:197
constexpr bool is_normalized() const
Check if the vector is normalized.
Definition vector.hpp:215
constexpr T dot(const Vector &rhs) const noexcept
Calculates the dot product of this vector and another.
Definition vector.hpp:330
constexpr Vector cross(const Vector &rhs) const noexcept
Calculates the cross product of this vector and another.
Definition vector.hpp:342
constexpr Vector normalized() const
Returns a new vector that is a normalized version of this one.
Definition vector.hpp:294
constexpr Float length() const
Definition vector.hpp:283
constexpr T length_squared() const noexcept
Calculates the squared length (magnitude) of the vector.
Definition vector.hpp:271
constexpr Vector operator-() const noexcept
Negates the vector.
Definition vector.hpp:170
constexpr const T & y() const noexcept
Const access to the second component (y-axis).
Definition vector.hpp:99
constexpr T min() const
Returns the minimum value in the vector.
Definition vector.hpp:455
constexpr T & y() noexcept
Accesses the second component (y-axis).
Definition vector.hpp:90
constexpr const T & z() const noexcept
Const access to the third component (z-axis).
Definition vector.hpp:101
constexpr const T & operator[](int index) const
Provides const access to the vector's components by index.
Definition vector.hpp:117
constexpr Vector operator/=(const U &value) const noexcept
Divides this vector by a scalar.
Definition vector.hpp:250
friend constexpr Vector operator*(U lhs, const Vector< T, N > &rhs) noexcept
Multiplies a scalar by a vector.
Definition vector.hpp:388
constexpr Vector permuted(Args ...args) const
Returns a new vector with the specified dimensions permuted.
Definition vector.hpp:467
constexpr Vector operator/(U rhs) const
Divides a vector by a scalar.
Definition vector.hpp:405
constexpr bool is_zero() const
Check if all components of the vector are zero.
Definition vector.hpp:225
constexpr Vector & operator-=(const Vector &rhs) noexcept
Subtracts another vector from this one component-wise.
Definition vector.hpp:184
constexpr Vector & operator*=(const T &rhs) noexcept
Multiplies this vector by a scalar.
Definition vector.hpp:189
constexpr int dims() const noexcept
Returns the number of dimensions of the vector.
Definition vector.hpp:106
constexpr Vector operator*(const Vector< T, N > &rhs) const noexcept
Multiplies two vectors component-wise (Hadamard product).
Definition vector.hpp:395
constexpr bool has_nan() const
Check if any component of the vector is NaN (Not a Number).
Definition vector.hpp:239
constexpr Vector operator+(const Vector< T, N > &rhs) const noexcept
Adds two vectors component-wise.
Definition vector.hpp:365
static constexpr Vector ones() noexcept
Creates a vector with all components set to one.
Definition vector.hpp:62
constexpr T max() const
Returns the maximum value in the vector.
Definition vector.hpp:439
constexpr const T & w() const noexcept
Const access to the fourth component (w-axis).
Definition vector.hpp:103
constexpr int min_dim() const
Returns the dimension with the minimum value.
Definition vector.hpp:447
void apply(const std::function< void(T &, int)> &func)
Applies a function to each element of the vector.
Definition vector.hpp:360
constexpr Vector & permute(Args ...args)
Permutes the dimensions of the vector.
Definition vector.hpp:482
static constexpr Vector filled(T value) noexcept
Creates a vector with all components set to a single scalar value.
Definition vector.hpp:46
Provides basic, constexpr-aware mathematical functions.
Defines the primary floating-point type alias for the math library.
The namespace for math library implementation.
Definition bounding_box.hpp:9
constexpr T sqrt(T x)
Calculates the square root of a number with constexpr support.
Definition function.hpp:177
float Float
The primary floating-point type used throughout the math library.
Definition global.hpp:29
Normal< Float, 2 > Normal2
A 2-dimensional vector of type Float.
Definition vector.hpp:577
Vector< Float, 3 > Vec3
A 3-dimensional vector of type Float.
Definition vector.hpp:565
Vector< Float, 2 > Vec2
A 2-dimensional vector of type Float.
Definition vector.hpp:563
constexpr bool is_equal(T a, T b)
Compares two floating-point values for equality.
Definition function.hpp:287
Normal< Float, 3 > Normal3
A 3-dimensional vector of type Float.
Definition vector.hpp:579
Normal< Float, 4 > Normal4
A 4-dimensional vector of type Float.
Definition vector.hpp:581
Vector< Float, 4 > Vec4
A 4-dimensional vector of type Float.
Definition vector.hpp:567
constexpr std::vector< Vector< T, N > > get_orthogonal_bases(const Vector< T, N > &base)
Returns orthogonal bases for a given vector.
Definition vector.hpp:498