libpromeki 1.0.0-alpha
PROfessional MEdia toolKIt
 
Loading...
Searching...
No Matches
array.h
Go to the documentation of this file.
1
8#pragma once
9
10
11#include <promeki/config.h>
12#if PROMEKI_ENABLE_CORE
13#include <cstddef>
14#include <array>
15#include <type_traits>
16#include <promeki/namespace.h>
17
18PROMEKI_NAMESPACE_BEGIN
19
38template <typename T, size_t NumValues> class Array {
39 public:
41 using DataType = std::array<T, NumValues>;
42
47 constexpr Array() : d{} {}
48
53 constexpr Array(const DataType &val) : d(val) {}
54
59 constexpr Array(DataType &&val) : d(std::move(val)) {}
60
72 template <typename... Args, typename = std::enable_if_t<sizeof...(Args) == NumValues &&
73 (std::is_convertible_v<Args, T> && ...)>>
74 constexpr Array(Args... args) : d{static_cast<T>(args)...} {}
75
77 ~Array() = default;
78
83 constexpr size_t size() const { return d.size(); }
84
96 template <typename U, size_t OtherNumValues> constexpr Array(const Array<U, OtherNumValues> &other) {
97 static_assert(std::is_convertible_v<T, T>, "Incompatible types");
98 static_assert(OtherNumValues <= NumValues, "Incompatible sizes");
99 for (size_t i = 0; i < NumValues; ++i) {
100 d[i] = i < OtherNumValues ? other[i] : T{};
101 }
102 }
103
113 template <typename U> constexpr Array<T, NumValues> &operator=(const Array<U, NumValues> &other) {
114 static_assert(std::is_assignable_v<T &, U>, "Incompatible types");
115 for (size_t i = 0; i < NumValues; ++i) {
116 d[i] = static_cast<T>(other[i]);
117 }
118 return *this;
119 }
120
133 template <typename U, size_t OtherNumValues>
134 constexpr Array<T, NumValues> &operator=(const Array<U, OtherNumValues> &other) {
135 static_assert(std::is_assignable_v<T &, U>, "Incompatible types");
136 static_assert(OtherNumValues <= NumValues, "Incompatible sizes");
137 for (size_t i = 0; i < NumValues; ++i) {
138 d[i] = i < OtherNumValues ? static_cast<T>(other[i]) : T{};
139 }
140 return *this;
141 }
142
152 template <typename U> constexpr Array<T, NumValues> &operator=(U value) {
153 static_assert(std::is_assignable_v<T &, U>, "Incompatible types");
154 for (size_t i = 0; i < NumValues; ++i) {
155 d[i] = static_cast<T>(value);
156 }
157 return *this;
158 }
159
168 constexpr T &operator[](size_t index) { return d[index]; }
169
178 constexpr const T &operator[](size_t index) const { return d[index]; }
179
185 constexpr Array<T, NumValues> &operator+=(const Array<T, NumValues> &other) {
186 for (size_t i = 0; i < NumValues; ++i) d[i] += other[i];
187 return *this;
188 }
189
195 constexpr Array<T, NumValues> &operator-=(const Array<T, NumValues> &other) {
196 for (size_t i = 0; i < NumValues; ++i) d[i] -= other[i];
197 return *this;
198 }
199
205 constexpr Array<T, NumValues> &operator*=(const Array<T, NumValues> &other) {
206 for (size_t i = 0; i < NumValues; ++i) d[i] *= other[i];
207 return *this;
208 }
209
215 constexpr Array<T, NumValues> &operator/=(const Array<T, NumValues> &other) {
216 for (size_t i = 0; i < NumValues; ++i) d[i] /= other[i];
217 return *this;
218 }
219
225 constexpr Array<T, NumValues> &operator+=(const T &scalar) {
226 for (size_t i = 0; i < NumValues; ++i) d[i] += scalar;
227 return *this;
228 }
229
235 constexpr Array<T, NumValues> &operator-=(const T &scalar) {
236 for (size_t i = 0; i < NumValues; ++i) d[i] -= scalar;
237 return *this;
238 }
239
245 constexpr Array<T, NumValues> &operator*=(const T &scalar) {
246 for (size_t i = 0; i < NumValues; ++i) d[i] *= scalar;
247 return *this;
248 }
249
255 constexpr Array<T, NumValues> &operator/=(const T &scalar) {
256 for (size_t i = 0; i < NumValues; ++i) d[i] /= scalar;
257 return *this;
258 }
259
264 constexpr T sum() const {
265 T ret{};
266 for (size_t i = 0; i < NumValues; ++i) ret += d[i];
267 return ret;
268 }
269
274 constexpr double mean() const {
275 double val = 0.0;
276 for (size_t i = 0; i < NumValues; ++i) val += static_cast<double>(d[i]);
277 val /= static_cast<double>(NumValues);
278 return val;
279 }
280
285 constexpr T *data() { return d.data(); }
286
291 constexpr const T *data() const { return d.data(); }
292
298 constexpr bool isZero() const {
299 const T zero{};
300 for (size_t i = 0; i < NumValues; i++) {
301 if (d[i] != zero) return false;
302 }
303 return true;
304 }
305
312 constexpr Array<T, NumValues> lerp(const Array<T, NumValues> &other, double v) const {
313 Array<T, NumValues> ret;
314 for (size_t i = 0; i < d.size(); ++i) ret[i] = ((1.0 - v) * d[i]) + (v * other.d[i]);
315 return ret;
316 }
317
324 constexpr Array<T, NumValues> clamp(const Array<T, NumValues> &min, const Array<T, NumValues> &max) const {
325 Array<T, NumValues> ret;
326 for (size_t i = 0; i < d.size(); ++i) {
327 if (d[i] < min[i])
328 ret[i] = min[i];
329 else if (d[i] > max[i])
330 ret[i] = max[i];
331 else
332 ret[i] = d[i];
333 }
334 return ret;
335 }
336
343 constexpr bool isBetween(const Array<T, NumValues> &min, const Array<T, NumValues> &max) const {
344 for (size_t i = 0; i < d.size(); ++i) {
345 if (d[i] < min[i] || d[i] > max[i]) return false;
346 }
347 return true;
348 }
349
351 friend constexpr Array<T, NumValues> operator+(Array<T, NumValues> lhs, const Array<T, NumValues> &rhs) {
352 lhs += rhs;
353 return lhs;
354 }
355
357 friend constexpr Array<T, NumValues> operator-(Array<T, NumValues> lhs, const Array<T, NumValues> &rhs) {
358 lhs -= rhs;
359 return lhs;
360 }
361
363 friend constexpr Array<T, NumValues> operator*(Array<T, NumValues> lhs, const Array<T, NumValues> &rhs) {
364 lhs *= rhs;
365 return lhs;
366 }
367
369 friend constexpr Array<T, NumValues> operator/(Array<T, NumValues> lhs, const Array<T, NumValues> &rhs) {
370 lhs /= rhs;
371 return lhs;
372 }
373
375 friend constexpr Array<T, NumValues> operator+(Array<T, NumValues> lhs, const T &scalar) {
376 lhs += scalar;
377 return lhs;
378 }
379
381 friend constexpr Array<T, NumValues> operator-(Array<T, NumValues> lhs, const T &scalar) {
382 lhs -= scalar;
383 return lhs;
384 }
385
387 friend constexpr Array<T, NumValues> operator*(Array<T, NumValues> lhs, const T &scalar) {
388 lhs *= scalar;
389 return lhs;
390 }
391
393 friend constexpr Array<T, NumValues> operator/(Array<T, NumValues> lhs, const T &scalar) {
394 lhs /= scalar;
395 return lhs;
396 }
397
399 friend constexpr bool operator==(const Array<T, NumValues> &lhs, const Array<T, NumValues> &rhs) {
400 for (size_t i = 0; i < NumValues; ++i)
401 if (lhs[i] != rhs[i]) return false;
402 return true;
403 }
404
406 friend constexpr bool operator!=(const Array<T, NumValues> &lhs, const Array<T, NumValues> &rhs) {
407 return !(lhs == rhs);
408 }
409
411 friend constexpr bool operator<(const Array<T, NumValues> &lhs, const Array<T, NumValues> &rhs) {
412 for (size_t i = 0; i < NumValues; ++i) {
413 if (lhs[i] < rhs[i]) return true;
414 if (rhs[i] < lhs[i]) return false;
415 }
416 return false;
417 }
418
420 friend constexpr bool operator>(const Array<T, NumValues> &lhs, const Array<T, NumValues> &rhs) { return rhs < lhs; }
421
423 friend constexpr bool operator<=(const Array<T, NumValues> &lhs, const Array<T, NumValues> &rhs) { return !(rhs < lhs); }
424
426 friend constexpr bool operator>=(const Array<T, NumValues> &lhs, const Array<T, NumValues> &rhs) { return !(lhs < rhs); }
427
428 protected:
429 DataType d;
430};
431
432PROMEKI_NAMESPACE_END
433
434#endif // PROMEKI_ENABLE_CORE