xcal
基于 C++23 的现代图形渲染引擎
载入中...
搜索中...
未找到
vec.hpp
浏览该文件的文档.
1
16#pragma once
17#ifndef VEC_H
18#define VEC_H
19
24#ifdef _MSVC_VER
25#include <vcruntime_typeinfo.h>
26#endif
27
28#include <assert.h>
29
30#include <cmath>
31#include <concepts>
32#include <cstddef>
33#include <type_traits>
34
35#include "../utils/compiling.hpp"
36#include "./declaration.hpp"
37
44namespace xcmath {
45template <typename _Tp, size_t _length>
46 requires(_length > 0 && std::is_default_constructible_v<_Tp>)
47class vec;
55template <class T>
56concept Vec = requires(T a) {
57 typename T::DataType;
58 typename T::ItemType;
59 std::is_same_v<typename T::template Self<typename T::DataType>, T>;
60 T::datatype;
61 T::itemtype;
62 { T::dim } -> std::same_as<const size_t&>;
63 { T::length } -> std::same_as<const size_t&>;
64 { a[T::length - 1] } -> std::same_as<typename T::ItemType&>;
65};
66
75template <class vec, class _Item>
76concept VecItem = requires {
77 requires(Vec<vec>);
78 requires(std::convertible_to<typename vec::ItemType, _Item>);
79};
86template <class Arg, class... Args>
87constexpr size_t VecConstructPackSize =
94template <class Arg>
95inline constexpr size_t VecConstructPackSize<Arg> = []() -> size_t {
96 if constexpr (Vec<Arg>)
97 return Arg::length;
98 else
99 return 1;
100}();
108template <class _Tp>
109struct VecInfo {
110#ifdef _MSVC_VER
111 static constexpr size_t Dim = []() -> size_t {
112 if constexpr (Vec<_Tp>) return VecInfo<_Tp::ItemType>::Dim + 1;
113 return 0;
114 }();
115 static constexpr auto Zero = []() {
116 if constexpr (Vec<_Tp>)
118 else
119 return _Tp{};
120 }();
121 using DataType = decltype(Zero);
122#else
123
124 static constexpr size_t dim = []() -> size_t {
125 if constexpr (Vec<_Tp>) return VecInfo<typename _Tp::ItemType>::dim + 1;
126 return 0;
127 }();
128
129 static constexpr auto Zero = []() {
130 if constexpr (Vec<_Tp>)
132 else
133 return _Tp{};
134 }();
135 using DataType = decltype([]() {
136 if constexpr (Vec<_Tp>)
138 else
139 return _Tp{};
140 }());
141
142#endif
143 template <class _Sl, class... _Sls>
144 static constexpr auto SubVecZero = []() constexpr {
145 if constexpr (sizeof...(_Sls))
146 return int{};
147 else
148 return std::declval<float>();
149 }();
150 template <class _Sl, class... _Sls>
151 using SubVec = decltype(SubVecZero<_Sl, _Sls...>);
152};
159template <class T, size_t len, size_t... lens>
165 using Type = vec<typename __batchHelper<T, lens...>::Type, len>;
166};
173template <class T, size_t len>
174struct __batchHelper<T, len> {
180};
181
188template <class T, size_t... lens>
189using batch = __batchHelper<T, lens...>::Type;
204template <typename _Tp, size_t _length>
205 requires(_length > 0 && std::is_default_constructible_v<_Tp>)
206class vec {
207 protected:
212 _Tp data[_length];
213
214 public:
218 using ItemType = _Tp;
219
224 static constexpr size_t dim = VecInfo<ItemType>::dim + 1;
225
232 template <class __Tp, size_t __len, size_t... __lens>
233 struct __subVecHelper {};
234
235 template <size_t __len, size_t... __lens>
236 struct __subVecHelper<size_t, __len, __lens...> {
237 using Type = vec<typename ItemType::template SubVec<__lens...>, __len>;
238 };
239 template <size_t __len>
240 struct __subVecHelper<size_t, __len> {
242 };
243
244 template <size_t __len, size_t... __lens>
245 using SubVec = __subVecHelper<size_t, __len, __lens...>::Type;
246
247 // template <size_t __len>
248 // using SubVec<__len> = vec<ItemType, __len>;
249
250 template <class _T>
252
256 constexpr static auto datatype = TypeName<DataType>;
257
261 constexpr static auto itemtype = TypeName<ItemType>;
262
266 constexpr static auto length = _length;
267
273 constexpr vec()
274 requires(std::is_default_constructible_v<_Tp>)
275 : data{_Tp{}} {}
276
287 template <class _Tp1, class... _T>
288 requires(std::is_convertible_v<_Tp1, _Tp> &&
289 (std::is_convertible_v<_T, _Tp> && ...))
290 constexpr vec(const _Tp1& arg1, const _T&... args) {
291 size_t i = 0;
292 data[0] = arg1;
293 ((data[++i] = args), ...);
294 }
295
304 template <typename... _Args>
305 requires((VecConstructPackSize<_Args...> <= _length &&
306 VecConstructPackSize<_Args...> > 1) &&
308 std::is_convertible_v<_Args, ItemType>) &&
309 ...))
310 constexpr explicit vec(const _Args&... args) {
311 size_t n = 0;
312 (([&]<class _Arg>(_Arg _arg) {
313 if constexpr (std::is_convertible_v<_Arg, ItemType>)
314 data[n++] = _arg;
315 else {
316 for (auto& i : _arg) data[n++] = i;
317 }
318 }(args)),
319 ...);
320 }
321
327 template <class T>
328 requires(std::is_convertible_v<T, ItemType>)
329 constexpr explicit vec(const T& fill_value) {
330 for (size_t i = 0; i < length; i++) {
331 data[i] = fill_value;
332 }
333 }
334
340 constexpr vec(const vec<_Tp, _length>& other) {
341 for (size_t i = 0; i < _length; i++) {
342 data[i] = other[i];
343 }
344 }
345
352 constexpr vec(vec<_Tp, _length>&& o) {
353 for (size_t i = 0; i < _length; i++) {
354 data[i] = o[i];
355 }
356 }
357
358 constexpr vec(const std::initializer_list<ItemType>& list) {
359 size_t i = 0;
360 for (auto it : list) {
361 assert(i < _length);
362 data[i++] = it;
363 }
364 }
365
371 constexpr const _Tp* begin() const { return data; }
372
378 constexpr const _Tp* end() const { return data + length; }
379
386 constexpr _Tp& operator[](size_t index) { return data[index]; }
387
394 constexpr const _Tp& operator[](size_t index) const {
395 assert(index < length);
396 return data[index];
397 }
398
406 for (size_t i = 0; i < _length; i++) {
407 data[i] = o[i];
408 }
409 return *this;
410 }
411
419 for (size_t i = 0; i < _length; i++) {
420 data[i] = o[i];
421 }
422 return *this;
423 }
424
431 template <size_t... idx, class... _Ss>
432 requires(sizeof...(_Ss) < dim)
433 constexpr SubVec<sizeof...(idx), (_Ss::length, ...)> operator()(
434 Slice<idx...>, _Ss... ns) const {
435 return {(data[idx](ns...))...};
436 }
437
444 template <size_t... idx>
445 constexpr vec<ItemType, sizeof...(idx)> operator()(Slice<idx...> s) const {
446 return {data[idx]...};
447 }
448
454 constexpr _Tp& x()
455 requires(_length < 5)
456 {
457 return this->data[0];
458 }
459
465 constexpr _Tp& y()
466 requires(_length < 5 && _length > 1)
467 {
468 return this->data[1];
469 }
470
476 constexpr _Tp& z()
477 requires(_length < 5 && _length > 2)
478 {
479 return this->data[2];
480 }
481
487 constexpr _Tp& w()
488 requires(_length < 5 && _length > 3)
489 {
490 return this->data[3];
491 }
492
498 constexpr const _Tp& x() const
499 requires(_length < 5)
500 {
501 return this->data[0];
502 }
503
509 constexpr const _Tp& y() const
510 requires(_length < 5 && _length > 1)
511 {
512 return this->data[1];
513 }
514
520 constexpr const _Tp& z() const
521 requires(_length < 5 && _length > 2)
522 {
523 return this->data[2];
524 }
525
531 constexpr const _Tp& w() const
532 requires(_length < 5 && _length > 3)
533 {
534 return this->data[3];
535 }
536
537 constexpr const vec<_Tp, 2>& xy() const
538 requires(_length < 5 && _length > 1)
539 {
540 return *reinterpret_cast<const vec<_Tp, 2>*>(data);
541 }
542 constexpr vec<_Tp, 2>& xy()
543 requires(_length < 5 && _length > 1)
544 {
545 return *reinterpret_cast<vec<_Tp, 2>*>(data);
546 }
547
548 constexpr const vec<_Tp, 2>& yz() const
549 requires(_length < 5 && _length > 2)
550 {
551 return *reinterpret_cast<const vec<_Tp, 2>*>(data + 1);
552 }
553 constexpr vec<_Tp, 2>& yz()
554 requires(_length < 5 && _length > 2)
555 {
556 return *reinterpret_cast<vec<_Tp, 2>*>(data + 1);
557 }
558
559 constexpr const vec<_Tp, 2>& zw() const
560 requires(_length < 5 && _length > 3)
561 {
562 return *reinterpret_cast<const vec<_Tp, 2>*>(data + 2);
563 }
564 constexpr vec<_Tp, 2>& zw()
565 requires(_length < 5 && _length > 3)
566 {
567 return *reinterpret_cast<vec<_Tp, 2>*>(data + 2);
568 }
569
570 constexpr const vec<_Tp, 3>& xyz() const
571 requires(_length < 5 && _length > 2)
572 {
573 return *reinterpret_cast<const vec<_Tp, 3>*>(data);
574 }
575 constexpr vec<_Tp, 3>& xyz()
576 requires(_length < 5 && _length > 2)
577 {
578 return *reinterpret_cast<vec<_Tp, 3>*>(data);
579 }
580 constexpr const vec<_Tp, 3>& yzw() const
581 requires(_length < 5 && _length > 2)
582 {
583 return *reinterpret_cast<const vec<_Tp, 3>*>(data + 1);
584 }
585 constexpr vec<_Tp, 3>& yzw()
586 requires(_length < 5 && _length > 2)
587 {
588 return *reinterpret_cast<vec<_Tp, 3>*>(data + 1);
589 }
590
591 constexpr vec<_Tp, 2> xz() const
592 requires(_length < 5 && _length > 2)
593 {
594 return {data[0], data[2]};
595 }
596 constexpr vec<_Tp, 2> xw() const
597 requires(_length < 5 && _length > 3)
598 {
599 return {data[0], data[3]};
600 }
601 constexpr vec<_Tp, 2> yw() const
602 requires(_length < 5 && _length > 3)
603 {
604 return {data[1], data[3]};
605 }
606
617 constexpr vec<_Tp, _length> cross(const vec<_Tp, _length>& other) const {
619 res[0] = data[1] * other[2] - data[2] * other[1];
620 res[1] = data[2] * other[0] - data[0] * other[2];
621 res[2] = data[0] * other[1] - data[1] * other[0];
622 return res;
623 }
624
631 constexpr _Tp dot(const vec<_Tp, _length>& other) const {
632 _Tp res = _Tp{};
633 for (size_t i = 0; i < _length; i++) {
634 res += data[i] * other[i];
635 }
636 return res;
637 }
638
645 constexpr vec<_Tp, _length> normalize() const {
647 auto disten = distance({});
648 for (size_t i = 0; i < _length; i++) {
649 res[i] = data[i] / disten;
650 }
651 return res;
652 }
653
660 constexpr _Tp distance(const vec<_Tp, _length>& other) const {
661 _Tp res = _Tp{};
662 for (size_t i = 0; i < _length; i++) {
663 res += (data[i] - other[i]) * (data[i] - other[i]);
664 }
665 return std::sqrt(res);
666 }
667
673 constexpr _Tp mod() const {
674 _Tp res = _Tp{};
675 for (size_t i = 0; i < _length; i++) {
676 res += data[i] * data[i];
677 }
678 return sqrt(res);
679 }
680
687 constexpr _Tp angle(const vec<_Tp, _length>& other) const {
688 _Tp cos_theta = dot(other) / (mod() * other.mod());
689 return std::acos(cos_theta);
690 }
691
697 constexpr bool any() const
698 requires(std::is_convertible_v<DataType, bool>)
699 {
700 if constexpr (std::is_convertible_v<ItemType, bool>) {
701 for (size_t i = 0; i < _length; i++)
702 if (data[i]) {
703 return true;
704 }
705 return false;
706 } else if constexpr (Vec<ItemType>) {
707 for (size_t i = 0; i < _length; i++) {
708 if (data[i].any()) {
709 return true;
710 }
711 }
712 return false;
713 }
714 }
715
721 constexpr bool every() const
722 requires(std::is_convertible_v<DataType, bool>)
723 {
724 if constexpr (std::is_convertible_v<ItemType, bool>) {
725 for (size_t i = 0; i < _length; i++)
726 if (!data[i]) {
727 return false;
728 }
729 return true;
730 } else if constexpr (Vec<ItemType>) {
731 for (size_t i = 0; i < _length; i++) {
732 if (!data[i].every()) {
733 return false;
734 }
735 }
736 return true;
737 }
738 }
739
748 constexpr inline bool all() const
749 requires(std::is_convertible_v<DataType, bool>)
750 {
751 return every();
752 }
753
754 template <typename _OTp>
755 requires(std::is_convertible_v<ItemType, _OTp>)
756 constexpr inline operator Self<_OTp>() const {
757 Self<_OTp> ret;
758 for (size_t i = 0; i < _length; i++)
759 ret[i] = static_cast<_OTp>(data(i));
760 return ret;
761 }
762
768 auto operator-() const {
769 Self<decltype(-data[0])> res;
770 for (size_t i = 0; i < _length; i++) {
771 res[i] = -data[i];
772 }
773 return res;
774 }
775
781 auto operator+() const {
782 Self<decltype(+data[0])> res;
783 for (size_t i = 0; i < _length; i++) {
784 res[i] = +data[i];
785 }
786 return res;
787 }
788
794 auto operator--() {
795 auto tmp = *this;
796 for (size_t i = 0; i < _length; i++) {
797 data[i]--;
798 }
799 return tmp;
800 }
801
807 auto& operator--(int) {
808 for (size_t i = 0; i < _length; i++) {
809 --data[i];
810 }
811 return *this;
812 }
813
819 auto operator++() {
820 auto tmp = *this;
821 for (size_t i = 0; i < _length; i++) {
822 data[i]++;
823 }
824 return tmp;
825 }
826
832 auto& operator++(int) {
833 for (size_t i = 0; i < _length; i++) {
834 --data[i];
835 }
836 return *this;
837 }
838
846#define __VEC_OP_VEC_ON_EQ_LENGTH(op) \
847 template <class _OTp> \
848 requires(dim == VecInfo<_OTp>::dim) \
849 auto operator op(const _OTp& o) const { \
850 Self<decltype(data[0] op o[0])> res; \
851 auto length = (_length > _OTp::length) ? _OTp::length : _length; \
852 for (size_t i = 0; i < length; i++) { \
853 res[i] = data[i] op o[i]; \
854 } \
855 return res; \
856 }
871#undef __VEC_OP_VEC_ON_EQ_LENGTH
872
880#define __VEC_OP_ITEM_ON_OP_ABLE(op) \
881 template <class _OTp> \
882 requires(VecInfo<_OTp>::dim == 0 || dim == VecInfo<_OTp>::dim + 1) \
883 inline constexpr auto operator op(const _OTp& o) const { \
884 Self<decltype(data[0] op o)> res; \
885 for (size_t i = 0; i < _length; i++) { \
886 res[i] = data[i] op o; \
887 } \
888 return res; \
889 }
904#undef __VEC_OP_ITEM_ON_OP_ABLE
905};
906
907#define __ITEM_OP_VEC_ON_OP_ENABLE(op) \
908 template <class _OTp, Vec _Tp> \
909 requires(VecInfo<_OTp>::dim == 0 || \
910 (VecInfo<_OTp>::dim == _Tp::dim - 1)) \
911 inline constexpr auto operator op(const _OTp& other, const _Tp& o) { \
912 typename _Tp::template Self<decltype(other op o[0])> res; \
913 for (size_t i = 0; i < _Tp::length; i++) res[i] = other op o[i]; \
914 return res; \
915 }
916
928#undef __ITEM_OP_VEC_ON_OP_ENABLE
929} // namespace xcmath
930#endif // VEC_H
Vector class template
Definition vec.hpp:206
constexpr vec< _Tp, 2 > xw() const
Definition vec.hpp:596
constexpr bool every() const
Check if all elements satisfy a condition
Definition vec.hpp:721
constexpr const _Tp & z() const
Get the item at index 2 (const version)
Definition vec.hpp:520
constexpr const _Tp & operator[](size_t index) const
Access element at specified index (const version)
Definition vec.hpp:394
typename VecInfo< ItemType >::DataType DataType
Type of data stored in the vector
Definition vec.hpp:223
constexpr vec()
Construct a zero-initialized vector Notw: _Tp must be default constructible
Definition vec.hpp:273
constexpr const vec< _Tp, 3 > & xyz() const
Definition vec.hpp:570
constexpr _Tp angle(const vec< _Tp, _length > &other) const
Compute angle with another vector
Definition vec.hpp:687
constexpr const _Tp * begin() const
Get pointer to the beginning of the data array
Definition vec.hpp:371
constexpr vec< _Tp, _length > & operator=(const vec< _Tp, _length > &o)
Copy assignment operator
Definition vec.hpp:405
constexpr _Tp dot(const vec< _Tp, _length > &other) const
Compute Euclidean inner product
Definition vec.hpp:631
constexpr _Tp & x()
Get the item at index 0
Definition vec.hpp:454
constexpr bool all() const
Check universal quantification of components
Definition vec.hpp:748
constexpr vec(const T &fill_value)
Uniform value constructor
Definition vec.hpp:329
auto operator+() const
Unary plus operator
Definition vec.hpp:781
_Tp ItemType
Type of elements in the vector
Definition vec.hpp:218
constexpr const _Tp * end() const
Get pointer to the end of the data array
Definition vec.hpp:378
auto operator-() const
Component-wise additive inverse
Definition vec.hpp:768
constexpr const vec< _Tp, 3 > & yzw() const
Definition vec.hpp:580
constexpr vec(const std::initializer_list< ItemType > &list)
Definition vec.hpp:358
constexpr _Tp distance(const vec< _Tp, _length > &other) const
Compute distance to another vector
Definition vec.hpp:660
constexpr vec< _Tp, 2 > yw() const
Definition vec.hpp:601
constexpr vec(const vec< _Tp, _length > &other)
Copy constructor
Definition vec.hpp:340
constexpr vec< _Tp, 3 > & yzw()
Definition vec.hpp:585
__subVecHelper< size_t, __len, __lens... >::Type SubVec
Definition vec.hpp:245
constexpr vec< _Tp, 3 > & xyz()
Definition vec.hpp:575
constexpr _Tp & w()
Get the item at index 3
Definition vec.hpp:487
constexpr vec(const _Tp1 &arg1, const _T &... args)
Construct from component values
Definition vec.hpp:290
constexpr const _Tp & y() const
Get the item at index 1 (const version)
Definition vec.hpp:509
constexpr vec< _Tp, 2 > & yz()
Definition vec.hpp:553
auto & operator--(int)
Post-decrement operator
Definition vec.hpp:807
constexpr vec< _Tp, 2 > & zw()
Definition vec.hpp:564
constexpr const vec< _Tp, 2 > & zw() const
Definition vec.hpp:559
auto operator--()
Pre-decrement operator
Definition vec.hpp:794
constexpr const _Tp & x() const
Get the item at index 0 (const version)
Definition vec.hpp:498
constexpr vec< _Tp, 2 > & xy()
Definition vec.hpp:542
constexpr const vec< _Tp, 2 > & xy() const
Definition vec.hpp:537
constexpr _Tp mod() const
Calculate Euclidean norm (magnitude)
Definition vec.hpp:673
constexpr const vec< _Tp, 2 > & yz() const
Definition vec.hpp:548
constexpr vec< _Tp, _length > cross(const vec< _Tp, _length > &other) const
Compute 3D cross product
Definition vec.hpp:617
auto operator++()
Pre-increment operator
Definition vec.hpp:819
constexpr vec< _Tp, _length > & operator=(vec< _Tp, _length > &&o)
Move assignment operator
Definition vec.hpp:418
constexpr _Tp & y()
Get the item at index 1
Definition vec.hpp:465
constexpr _Tp & operator[](size_t index)
Access element at specified index
Definition vec.hpp:386
constexpr vec< _Tp, _length > normalize() const
Create unit vector in same direction
Definition vec.hpp:645
constexpr vec(vec< _Tp, _length > &&o)
Move constructor
Definition vec.hpp:352
constexpr _Tp & z()
Get the item at index 2
Definition vec.hpp:476
auto & operator++(int)
Post-increment operator
Definition vec.hpp:832
constexpr const _Tp & w() const
Get the item at index 3 (const version)
Definition vec.hpp:531
constexpr vec< _Tp, 2 > xz() const
Definition vec.hpp:591
constexpr bool any() const
Check if any element satisfies a condition
Definition vec.hpp:697
constexpr vec(const _Args &... args)
Construct from mixed scalars and vectors
Definition vec.hpp:310
Type requirement concept for vector types
Definition vec.hpp:56
Concept for valid vector component types
Definition vec.hpp:76
Declaration of vector, matrix, quaternion, and complex classes
Compiler-specific type information handling for MSVC
Definition complex.hpp:12
constexpr size_t VecConstructPackSize
Metafunction computing total size of vector constructor arguments
Definition vec.hpp:87
constexpr size_t VecConstructPackSize< Arg >
Metafunction computing total size of vector constructor arguments
Definition vec.hpp:95
Metaclassfor constructing a vector from a pack of arguments
Definition vec.hpp:160
vec< typename __batchHelper< T, lens... >::Type, len > Type
Type of the vector constructed from the arguments
Definition vec.hpp:165
Compile-time index sequence for vector slicing operations
static constexpr size_t dim
Definition vec.hpp:124
static constexpr auto Zero
Definition vec.hpp:129
else return _Tp
Definition vec.hpp:139
static constexpr auto SubVecZero
Definition vec.hpp:144
decltype(SubVecZero< _Sl, _Sls... >) SubVec
Definition vec.hpp:151
decltype([]() { if constexpr(Vec< _Tp >) return VecInfo< typename _Tp::ItemType >::Zero DataType
Definition vec.hpp:137
Metafunction for type transformation
Definition vec.hpp:233
#define __VEC_OP_VEC_ON_EQ_LENGTH(op)
Macro generating component-wise vector operations
Definition vec.hpp:846
#define __VEC_OP_ITEM_ON_OP_ABLE(op)
Macro generating vector-scalar operations
Definition vec.hpp:880
#define __ITEM_OP_VEC_ON_OP_ENABLE(op)
Definition vec.hpp:907