11#include <promeki/config.h>
12#if PROMEKI_ENABLE_CORE
18PROMEKI_NAMESPACE_BEGIN
38template <
typename T,
size_t NumValues>
class Array {
41 using DataType = std::array<T, NumValues>;
47 constexpr Array() : d{} {}
53 constexpr Array(
const DataType &val) : d(val) {}
59 constexpr Array(DataType &&val) : d(std::move(val)) {}
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)...} {}
83 constexpr size_t size()
const {
return d.size(); }
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{};
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]);
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{};
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);
168 constexpr T &operator[](
size_t index) {
return d[index]; }
178 constexpr const T &operator[](
size_t index)
const {
return d[index]; }
185 constexpr Array<T, NumValues> &operator+=(
const Array<T, NumValues> &other) {
186 for (
size_t i = 0; i < NumValues; ++i) d[i] += other[i];
195 constexpr Array<T, NumValues> &operator-=(
const Array<T, NumValues> &other) {
196 for (
size_t i = 0; i < NumValues; ++i) d[i] -= other[i];
205 constexpr Array<T, NumValues> &operator*=(
const Array<T, NumValues> &other) {
206 for (
size_t i = 0; i < NumValues; ++i) d[i] *= other[i];
215 constexpr Array<T, NumValues> &operator/=(
const Array<T, NumValues> &other) {
216 for (
size_t i = 0; i < NumValues; ++i) d[i] /= other[i];
225 constexpr Array<T, NumValues> &operator+=(
const T &scalar) {
226 for (
size_t i = 0; i < NumValues; ++i) d[i] += scalar;
235 constexpr Array<T, NumValues> &operator-=(
const T &scalar) {
236 for (
size_t i = 0; i < NumValues; ++i) d[i] -= scalar;
245 constexpr Array<T, NumValues> &operator*=(
const T &scalar) {
246 for (
size_t i = 0; i < NumValues; ++i) d[i] *= scalar;
255 constexpr Array<T, NumValues> &operator/=(
const T &scalar) {
256 for (
size_t i = 0; i < NumValues; ++i) d[i] /= scalar;
264 constexpr T sum()
const {
266 for (
size_t i = 0; i < NumValues; ++i) ret += d[i];
274 constexpr double mean()
const {
276 for (
size_t i = 0; i < NumValues; ++i) val += static_cast<double>(d[i]);
277 val /=
static_cast<double>(NumValues);
285 constexpr T *data() {
return d.data(); }
291 constexpr const T *data()
const {
return d.data(); }
298 constexpr bool isZero()
const {
300 for (
size_t i = 0; i < NumValues; i++) {
301 if (d[i] != zero)
return false;
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]);
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) {
329 else if (d[i] > max[i])
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;
351 friend constexpr Array<T, NumValues> operator+(Array<T, NumValues> lhs,
const Array<T, NumValues> &rhs) {
357 friend constexpr Array<T, NumValues> operator-(Array<T, NumValues> lhs,
const Array<T, NumValues> &rhs) {
363 friend constexpr Array<T, NumValues> operator*(Array<T, NumValues> lhs,
const Array<T, NumValues> &rhs) {
369 friend constexpr Array<T, NumValues> operator/(Array<T, NumValues> lhs,
const Array<T, NumValues> &rhs) {
375 friend constexpr Array<T, NumValues> operator+(Array<T, NumValues> lhs,
const T &scalar) {
381 friend constexpr Array<T, NumValues> operator-(Array<T, NumValues> lhs,
const T &scalar) {
387 friend constexpr Array<T, NumValues> operator*(Array<T, NumValues> lhs,
const T &scalar) {
393 friend constexpr Array<T, NumValues> operator/(Array<T, NumValues> lhs,
const T &scalar) {
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;
406 friend constexpr bool operator!=(
const Array<T, NumValues> &lhs,
const Array<T, NumValues> &rhs) {
407 return !(lhs == rhs);
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;
420 friend constexpr bool operator>(
const Array<T, NumValues> &lhs,
const Array<T, NumValues> &rhs) {
return rhs < lhs; }
423 friend constexpr bool operator<=(
const Array<T, NumValues> &lhs,
const Array<T, NumValues> &rhs) {
return !(rhs < lhs); }
426 friend constexpr bool operator>=(
const Array<T, NumValues> &lhs,
const Array<T, NumValues> &rhs) {
return !(lhs < rhs); }