Not Enough Math
Lightweight zero-dependency C++ math library
Loading...
Searching...
No Matches
vec.hpp
Go to the documentation of this file.
1#pragma once
2
3#include "utils.hpp"
4#include "err.hpp"
5
6#include <type_traits>
7#include <cstddef>
8#include <limits>
9
10#define TEST_VEC_TRAITS(VecType) \
11 static_assert(sizeof(VecType) == sizeof(VecType::ITEM_TYPE) * VecType::ITEM_COUNT, \
12 #VecType " size mismatch! Possible unexpected padding."); \
13 static_assert(std::is_standard_layout_v<VecType>, \
14 #VecType " is not Standard Layout. This breaks C-compatibility/offsetof."); \
15 \
16 static_assert(std::is_trivially_copyable_v<VecType>, \
17 #VecType " is not trivially copyable. This hurts pass-by-value performance."); \
18 static_assert(std::is_trivially_destructible_v<VecType>, \
19 #VecType " has a non-trivial destructor. This prevents it from being in a union."); \
20 \
21 static_assert(alignof(VecType) >= alignof(VecType::ITEM_TYPE), \
22 #VecType " alignment is weaker than its scalar component."); \
23 \
24 static_assert(std::is_default_constructible_v<VecType>, \
25 #VecType " should be default constructible for array allocations."); \
26 static_assert(std::is_trivially_copy_constructible_v<VecType>, \
27 #VecType " copy constructor is not trivial."); \
28 static_assert(std::is_trivially_move_constructible_v<VecType>, \
29 #VecType " move constructor is not trivial (math types should be POD-like).");
30
31namespace nem
32{
33 template<typename _T, size_t _N>
34 struct storage
35 {
36 using ITEM_TYPE = _T;
37 static constexpr size_t ITEM_COUNT = _N;
38
40 };
41
42 template<typename _T>
43 struct storage<_T, 2>
44 {
45 using ITEM_TYPE = _T;
46 static constexpr size_t ITEM_COUNT = 2;
47
48 union
49 {
51 struct { ITEM_TYPE x, y; };
52 struct { ITEM_TYPE u, v; };
53 struct { ITEM_TYPE s, t; };
54 struct { ITEM_TYPE min, max; };
55 struct { ITEM_TYPE width, height; };
56 };
57 };
58
59 template<typename _T>
60 struct storage<_T, 3>
61 {
62 using ITEM_TYPE = _T;
63 static constexpr size_t ITEM_COUNT = 3;
64
65 union
66 {
68 struct { ITEM_TYPE x, y, z; };
69 struct { ITEM_TYPE r, g, b; };
70 };
71 };
72
73 template<typename _T>
74 struct storage<_T, 4>
75 {
76 using ITEM_TYPE = _T;
77 static constexpr size_t ITEM_COUNT = 4;
78
79 union
80 {
82 struct { ITEM_TYPE x, y, z, w; };
83 struct { ITEM_TYPE r, g, b, a; };
84 struct { ITEM_TYPE min1, min2, max1, max2; };
85 };
86 };
87
88 template <typename _T, size_t _N>
89 requires (_N > 1)
90 struct vec : storage<_T, _N>
91 {
92 using ITEM_TYPE = _T;
93 static constexpr size_t ITEM_COUNT = _N;
94
95 vec() = default;
96 vec(ITEM_TYPE scalar)
97 {
98 for (int i = 0; i < ITEM_COUNT; ++i)
99 {
100 this->data[i] = scalar;
101 }
102 }
103
104 template <typename... Args>
105 requires (sizeof...(Args) == ITEM_COUNT) && ((std::is_same_v<Args, ITEM_TYPE> || nem::is_subset_of_v<Args, ITEM_TYPE>) && ...)
106 vec(Args... args)
107 {
108 int i = 0;
109 ((this->data[i++] = args), ...);
110 }
111
112 constexpr ITEM_TYPE& operator[](size_t index) { return this->data[index]; }
113 constexpr const ITEM_TYPE& operator[](size_t index) const { return this->data[index]; }
114
115 static constexpr vec NaN() { return vec(std::numeric_limits<ITEM_TYPE>::quiet_NaN()); }
116
117 vec& operator+=(const vec& rhs)
118 {
119 for (size_t i = 0; i < ITEM_COUNT; ++i)
120 {
121 (*this)[i] += rhs[i];
122 }
123 return *this;
124 }
125
126 vec& operator-=(const vec& rhs)
127 {
128 for (size_t i = 0; i < ITEM_COUNT; ++i)
129 {
130 (*this)[i] -= rhs[i];
131 }
132 return *this;
133 }
134
135 vec& operator*=(const vec& rhs)
136 {
137 for (size_t i = 0; i < ITEM_COUNT; ++i)
138 {
139 (*this)[i] *= rhs[i];
140 }
141 return *this;
142 }
143
145 {
146 for (size_t i = 0; i < ITEM_COUNT; ++i)
147 {
148 (*this)[i] *= scalar;
149 }
150 return *this;
151 }
152
153 vec& operator/=(const vec& rhs)
154 {
155 for (size_t i = 0; i < ITEM_COUNT; ++i)
156 {
157 (*this)[i] /= rhs[i];
158 }
159 return *this;
160 }
161
163 {
164 if constexpr (std::is_floating_point_v<ITEM_TYPE>)
165 {
166 const ITEM_TYPE fac = (ITEM_TYPE)1.0 / scalar;
167 for (size_t i = 0; i < ITEM_COUNT; ++i)
168 {
169 (*this)[i] *= fac;
170 }
171 }
172 else
173 {
174 for (size_t i = 0; i < ITEM_COUNT; ++i)
175 {
176 (*this)[i] /= scalar;
177 }
178 }
179 return *this;
180 }
181
182 friend vec operator+(vec lhs, const vec& rhs)
183 {
184 lhs += rhs;
185 return lhs;
186 }
187
188 friend vec operator-(vec lhs, const vec& rhs)
189 {
190 lhs -= rhs;
191 return lhs;
192 }
193
194 friend vec operator*(vec lhs, const vec& rhs)
195 {
196 lhs *= rhs;
197 return lhs;
198 }
199
200 friend vec operator*(vec vec, ITEM_TYPE scalar)
201 {
202 vec *= scalar;
203 return vec;
204 }
205
206 friend vec operator*(ITEM_TYPE scalar, vec vec)
207 {
208 vec *= scalar;
209 return vec;
210 }
211
212 friend vec operator/(vec lhs, const vec& rhs)
213 {
214 lhs /= rhs;
215 return lhs;
216 }
217
218 friend vec operator/(vec vec, ITEM_TYPE scalar)
219 {
220 vec /= scalar;
221 return vec;
222 }
223
224 friend vec operator/(ITEM_TYPE scalar, vec vec)
225 {
226 for (size_t i = 0; i < ITEM_COUNT; ++i)
227 {
228 // TODO: zero division safety
229 vec[i] = scalar / vec[i];
230 }
231 return vec;
232 }
233
234 // unary minus
235 friend vec operator-(vec value)
236 {
237 for (size_t i = 0; i < ITEM_COUNT; ++i)
238 {
239 value[i] = -value[i];
240 }
241 return value;
242 }
243
244 // unary plus
245 friend vec operator+(vec value)
246 {
247 for (size_t i = 0; i < ITEM_COUNT; ++i)
248 {
249 value[i] = +value[i];
250 }
251 return value;
252 }
253 };
254
264
274
275 namespace color
276 {
277 static constexpr float ALPHA_TRANSPARENT = 0.f;
278 static constexpr float ALPHA_OPAQUE = 1.f;
279
280 static NEM_INLINE float4 rgb(float r, float g, float b) { return float4(r, g, b, ALPHA_OPAQUE); }
281 static NEM_INLINE float4 rgba(float r, float g, float b, float a) { return float4(r, g, b, a); }
286
287 static NEM_INLINE float4 clear = rgba(0.f, 0.f, 0.f, ALPHA_TRANSPARENT);
288 static NEM_INLINE float4 white = rgb(1.f, 1.f, 1.f);
289 static NEM_INLINE float4 black = rgb(0.f, 0.f, 0.f);
290 static NEM_INLINE float4 red = rgb(1.f, 0.f, 0.f);
291 static NEM_INLINE float4 green = rgb(0.f, 1.f, 0.f);
292 static NEM_INLINE float4 blue = rgb(0.f, 0.f, 1.f);
293 static NEM_INLINE float4 cyan = rgb(0.f, 1.f, 1.f);
294 static NEM_INLINE float4 yellow = rgb(1.f, 1.f, 0.f);
295 };
296}
297
298#ifdef TEST_VEC_CLASS
299#undef TEST_VEC_CLASS
300#endif
301
302#ifdef TEST_VEC_TRAITS
303#undef TEST_VEC_TRAITS
304#endif
#define NEM_INLINE
Definition config.hpp:12
static float4 red
Definition vec.hpp:290
static float4 rgba(float r, float g, float b, float a)
Definition vec.hpp:281
static float4 black
Definition vec.hpp:289
static float4 yellow
Definition vec.hpp:294
static float4 opaque(float3 rgb)
Definition vec.hpp:282
static float4 white
Definition vec.hpp:288
static float4 cyan
Definition vec.hpp:293
static constexpr float ALPHA_TRANSPARENT
Definition vec.hpp:277
static float4 blue
Definition vec.hpp:292
static float4 transparent(float3 rgb)
Definition vec.hpp:284
static float4 clear
Definition vec.hpp:287
static float4 rgb(float r, float g, float b)
Definition vec.hpp:280
static float4 green
Definition vec.hpp:291
static constexpr float ALPHA_OPAQUE
Definition vec.hpp:278
Definition config.hpp:16
constexpr bool is_subset_of_v
Definition config.hpp:180
nem::vec< float, 4 > float4
Definition vec.hpp:260
ITEM_TYPE max
Definition vec.hpp:54
ITEM_TYPE height
Definition vec.hpp:55
ITEM_TYPE max1
Definition vec.hpp:84
_T ITEM_TYPE
Definition vec.hpp:36
static constexpr size_t ITEM_COUNT
Definition vec.hpp:37
ITEM_TYPE data[ITEM_COUNT]
Definition vec.hpp:39
vec & operator*=(const vec &rhs)
Definition vec.hpp:135
vec(Args... args)
Definition vec.hpp:106
vec & operator/=(ITEM_TYPE scalar)
Definition vec.hpp:162
vec()=default
friend vec operator/(ITEM_TYPE scalar, vec vec)
Definition vec.hpp:224
static constexpr vec NaN()
Definition vec.hpp:115
friend vec operator*(vec lhs, const vec &rhs)
Definition vec.hpp:194
friend vec operator/(vec vec, ITEM_TYPE scalar)
Definition vec.hpp:218
vec & operator/=(const vec &rhs)
Definition vec.hpp:153
friend vec operator+(vec lhs, const vec &rhs)
Definition vec.hpp:182
vec & operator*=(ITEM_TYPE scalar)
Definition vec.hpp:144
constexpr ITEM_TYPE & operator[](size_t index)
Definition vec.hpp:112
friend vec operator/(vec lhs, const vec &rhs)
Definition vec.hpp:212
friend vec operator-(vec lhs, const vec &rhs)
Definition vec.hpp:188
_T ITEM_TYPE
Definition vec.hpp:92
vec & operator+=(const vec &rhs)
Definition vec.hpp:117
friend vec operator*(ITEM_TYPE scalar, vec vec)
Definition vec.hpp:206
vec(ITEM_TYPE scalar)
Definition vec.hpp:96
vec & operator-=(const vec &rhs)
Definition vec.hpp:126
constexpr const ITEM_TYPE & operator[](size_t index) const
Definition vec.hpp:113
friend vec operator-(vec value)
Definition vec.hpp:235
friend vec operator+(vec value)
Definition vec.hpp:245
friend vec operator*(vec vec, ITEM_TYPE scalar)
Definition vec.hpp:200
#define TEST_VEC_TRAITS(VecType)
Definition vec.hpp:10