AutoPas  3.0.0
Loading...
Searching...
No Matches
ArrayMath.h
Go to the documentation of this file.
1
8#pragma once
9
10#include <array>
11#include <cmath>
12#include <numeric>
13#include <sstream>
14
16#include "autopas/utils/Math.h"
17
27template <class T, std::size_t SIZE>
28[[nodiscard]] constexpr std::array<T, SIZE> add(const std::array<T, SIZE> &a, const std::array<T, SIZE> &b) {
29 std::array<T, SIZE> result{};
30 for (std::size_t d = 0; d < SIZE; ++d) {
31 result[d] = a[d] + b[d];
32 }
33 return result;
34}
35
44template <class T, std::size_t SIZE>
45[[nodiscard]] constexpr std::array<T, SIZE> sub(const std::array<T, SIZE> &a, const std::array<T, SIZE> &b) {
46 std::array<T, SIZE> result{};
47 for (std::size_t d = 0; d < SIZE; ++d) {
48 result[d] = a[d] - b[d];
49 }
50 return result;
51}
52
61template <class T, std::size_t SIZE>
62[[nodiscard]] constexpr std::array<T, SIZE> min(const std::array<T, SIZE> &a, const std::array<T, SIZE> &b) {
63 std::array<T, SIZE> result{};
64 for (std::size_t d = 0; d < SIZE; ++d) {
65 result[d] = std::min<T>(a[d], b[d]);
66 }
67 return result;
68}
69
78template <class T, std::size_t SIZE>
79[[nodiscard]] constexpr bool less(const std::array<T, SIZE> &a, const std::array<T, SIZE> &b) {
80 bool result = true;
81 for (std::size_t d = 0; d < SIZE; ++d) {
82 result = result and (a[d] < b[d]);
83 }
84 return result;
85}
86
95template <class T, std::size_t SIZE>
96[[nodiscard]] constexpr std::array<T, SIZE> max(const std::array<T, SIZE> &a, const std::array<T, SIZE> &b) {
97 std::array<T, SIZE> result{};
98 for (std::size_t d = 0; d < SIZE; ++d) {
99 result[d] = std::max<T>(a[d], b[d]);
100 }
101 return result;
102}
103
112template <class T, std::size_t SIZE>
113[[nodiscard]] constexpr std::array<T, SIZE> mul(const std::array<T, SIZE> &a, const std::array<T, SIZE> &b) {
114 std::array<T, SIZE> result{};
115 for (std::size_t d = 0; d < SIZE; ++d) {
116 result[d] = a[d] * b[d];
117 }
118 return result;
119}
120
129template <class T, std::size_t SIZE>
130[[nodiscard]] constexpr std::array<T, SIZE> div(const std::array<T, SIZE> &a, const std::array<T, SIZE> &b) {
131 std::array<T, SIZE> result{};
132 for (std::size_t d = 0; d < SIZE; ++d) {
133 result[d] = a[d] / b[d];
134 }
135 return result;
136}
137
146template <class T, std::size_t SIZE>
147[[nodiscard]] constexpr std::array<T, SIZE> addScalar(const std::array<T, SIZE> &a, T s) {
148 std::array<T, SIZE> result{};
149 for (std::size_t d = 0; d < SIZE; ++d) {
150 result[d] = a[d] + s;
151 }
152 return result;
153}
154
163template <class T, std::size_t SIZE>
164[[nodiscard]] constexpr std::array<T, SIZE> subScalar(const std::array<T, SIZE> &a, T s) {
165 std::array<T, SIZE> result{};
166 for (std::size_t d = 0; d < SIZE; ++d) {
167 result[d] = a[d] - s;
168 }
169 return result;
170}
171
180template <class T, std::size_t SIZE>
181[[nodiscard]] constexpr std::array<T, SIZE> mulScalar(const std::array<T, SIZE> &a, T s) {
182 std::array<T, SIZE> result{};
183 for (std::size_t d = 0; d < SIZE; ++d) {
184 result[d] = a[d] * s;
185 }
186 return result;
187}
188
197template <class T, std::size_t SIZE>
198[[nodiscard]] constexpr std::array<T, SIZE> divScalar(const std::array<T, SIZE> &a, T s) {
199 std::array<T, SIZE> result{};
200 for (std::size_t d = 0; d < SIZE; ++d) {
201 result[d] = a[d] / s;
202 }
203 return result;
204}
205
214template <class T, std::size_t SIZE>
215[[nodiscard]] constexpr std::array<T, SIZE> divScalar(T s, const std::array<T, SIZE> &a) {
216 std::array<T, SIZE> result{};
217 for (std::size_t d = 0; d < SIZE; ++d) {
218 result[d] = s / a[d];
219 }
220 return result;
221}
222
232template <class T, std::size_t SIZE>
233[[nodiscard]] constexpr T dot(const std::array<T, SIZE> &a, const std::array<T, SIZE> &b) {
234 T result = 0.;
235 for (std::size_t i = 0; i < SIZE; i++) {
236 result += a[i] * b[i];
237 }
238 return result;
239}
240
248template <class T>
249[[nodiscard]] constexpr std::array<T, 3> cross(const std::array<T, 3> &a, const std::array<T, 3> &b) {
250 return {
251 a[1] * b[2] - a[2] * b[1],
252 a[2] * b[0] - a[0] * b[2],
253 a[0] * b[1] - a[1] * b[0],
254 };
255}
256
264template <class T, std::size_t SIZE>
265[[nodiscard]] constexpr T L2Norm(const std::array<T, SIZE> &a) {
266 return std::sqrt(dot(a, a));
267}
268
275template <class T>
276[[nodiscard]] constexpr typename T::value_type prod(const T &a) {
277 return std::accumulate(a.cbegin(), a.cend(), static_cast<typename T::value_type>(1), std::multiplies<>());
278}
279
287template <class T, std::size_t SIZE>
288[[nodiscard]] constexpr std::array<T, SIZE> abs(const std::array<T, SIZE> &a) {
289 std::array<T, SIZE> result{};
290 for (std::size_t d = 0; d < SIZE; ++d) {
291 result[d] = std::abs(a[d]);
292 }
293 return result;
294}
295
303template <class T, std::size_t SIZE>
304[[nodiscard]] constexpr std::array<T, SIZE> normalize(const std::array<T, SIZE> &a) {
305 return mulScalar(a, static_cast<T>(1) / L2Norm(a));
306}
307
315template <class T, std::size_t SIZE>
316[[nodiscard]] constexpr std::array<T, SIZE> ceil(const std::array<T, SIZE> &a) {
317 std::array<T, SIZE> result{};
318 for (std::size_t d = 0; d < SIZE; ++d) {
319 result[d] = std::ceil(a[d]);
320 }
321 return result;
322}
323
333template <typename target_T = int, typename float_T, std::size_t SIZE>
334[[nodiscard]] constexpr std::array<target_T, SIZE> floorAndCast(const std::array<float_T, SIZE> &a) {
335 std::array<target_T, SIZE> result{};
336 for (std::size_t d = 0; d < SIZE; ++d) {
337 result[d] = static_cast<target_T>(std::floor(a[d]));
338 }
339 return result;
340}
341
351template <class target_T = int, class float_T, std::size_t SIZE>
352[[nodiscard]] constexpr std::array<target_T, SIZE> ceilAndCast(const std::array<float_T, SIZE> &a) {
353 std::array<target_T, SIZE> result{};
354 for (std::size_t d = 0; d < SIZE; ++d) {
355 result[d] = static_cast<target_T>(std::ceil(a[d]));
356 }
357 return result;
358}
359
371template <ContainerType Container>
372bool isInUlp(Container lhs, Container rhs, unsigned int ulpDistance = Math::MAX_ULP_DISTANCE) {
373 return lhs.size() == rhs.size() && std::ranges::equal(lhs, rhs, [&ulpDistance](const auto &lhs, const auto &rhs) {
374 return Math::isInUlp(lhs, rhs, ulpDistance);
375 });
376}
377
386template <ContainerType Container>
387bool isNearRel(Container lhs, Container rhs, double maxRelativeDifference = Math::EPSILON_RELATIVE_EQUALITY) {
388 return lhs.size() == rhs.size() &&
389 std::ranges::equal(lhs, rhs, [&maxRelativeDifference](const auto &lhs, const auto &rhs) {
390 return Math::isNearRel(lhs, rhs, maxRelativeDifference);
391 });
392}
393
404template <class T, std::size_t SIZE>
405[[nodiscard]] bool isNearRel(const std::vector<std::array<T, SIZE>> &a, const std::vector<std::array<T, SIZE>> &b,
406 double maxRelativeDifference = Math::EPSILON_RELATIVE_EQUALITY) {
407 const auto size = a.size();
408 if (size != b.size()) {
409 return false;
410 }
411 bool arraysAreNear = true;
412 for (std::size_t i = 0; i < size; ++i) {
413 arraysAreNear = arraysAreNear and utils::ArrayMath::isNearRel(a[i], b[i], maxRelativeDifference);
414 }
415 return arraysAreNear;
416}
417
426template <class T>
427[[nodiscard]] bool isEqual(const std::vector<T> &a, const std::vector<T> &b) {
428 if (a.size() != b.size()) {
429 return false;
430 }
431 bool arraysAreEqual = true;
432 for (std::size_t i = 0; i < a.size(); ++i) {
433 arraysAreEqual = arraysAreEqual and (a[i] == b[i]);
434 }
435 return arraysAreEqual;
436}
437
446template <typename new_T, typename old_T, std::size_t SIZE>
447[[nodiscard]] constexpr std::array<new_T, SIZE> staticCastArray(const std::array<old_T, SIZE> &a) {
448 std::array<new_T, SIZE> result{};
449 for (std::size_t d = 0; d < SIZE; ++d) {
450 result[d] = static_cast<new_T>(a[d]);
451 }
452 return result;
453}
454
455// namespace for templated operators
456inline namespace literals {
465template <class T, std::size_t SIZE>
466constexpr std::array<T, SIZE> operator+(const std::array<T, SIZE> &a, const std::array<T, SIZE> &b) {
467 return add(a, b);
468}
469
478template <class T, std::size_t SIZE>
479constexpr std::array<T, SIZE> &operator+=(std::array<T, SIZE> &a, const std::array<T, SIZE> &b) {
480 for (std::size_t d = 0; d < SIZE; ++d) {
481 a[d] += b[d];
482 }
483 return a;
484}
485
494template <class T, std::size_t SIZE>
495constexpr std::array<T, SIZE> operator-(const std::array<T, SIZE> &a, const std::array<T, SIZE> &b) {
496 return sub(a, b);
497}
498
507template <class T, std::size_t SIZE>
508constexpr std::array<T, SIZE> &operator-=(std::array<T, SIZE> &a, const std::array<T, SIZE> &b) {
509 for (std::size_t d = 0; d < SIZE; ++d) {
510 a[d] -= b[d];
511 }
512 return a;
513}
514
523template <class T, std::size_t SIZE>
524constexpr std::array<T, SIZE> operator*(const std::array<T, SIZE> &a, const std::array<T, SIZE> &b) {
525 return mul(a, b);
526}
527
536template <class T, std::size_t SIZE>
537constexpr std::array<T, SIZE> &operator*=(std::array<T, SIZE> &a, const std::array<T, SIZE> &b) {
538 for (std::size_t d = 0; d < SIZE; ++d) {
539 a[d] *= b[d];
540 }
541 return a;
542}
543
552template <class T, std::size_t SIZE>
553constexpr std::array<T, SIZE> operator/(const std::array<T, SIZE> &a, const std::array<T, SIZE> &b) {
554 return div(a, b);
555}
556
565template <class T, std::size_t SIZE>
566constexpr std::array<T, SIZE> operator/(const std::array<T, SIZE> &a, T b) {
567 return divScalar(a, b);
568}
569
578template <class T, std::size_t SIZE>
579constexpr std::array<T, SIZE> operator/(T a, const std::array<T, SIZE> &b) {
580 return divScalar(a, b);
581}
582
591template <class T, std::size_t SIZE>
592constexpr std::array<T, SIZE> &operator/=(std::array<T, SIZE> &a, const std::array<T, SIZE> &b) {
593 for (std::size_t d = 0; d < SIZE; ++d) {
594 a[d] /= b[d];
595 }
596 return a;
597}
598
607template <class T, std::size_t SIZE>
608constexpr std::array<T, SIZE> operator+(const std::array<T, SIZE> &a, T s) {
609 return addScalar(a, s);
610}
611
620template <class T, std::size_t SIZE>
621constexpr std::array<T, SIZE> &operator+=(std::array<T, SIZE> &a, T s) {
622 for (std::size_t d = 0; d < SIZE; ++d) {
623 a[d] += s;
624 }
625 return a;
626}
627
636template <class T, std::size_t SIZE>
637constexpr std::array<T, SIZE> operator-(const std::array<T, SIZE> &a, T s) {
638 return subScalar(a, s);
639}
640
649template <class T, std::size_t SIZE>
650constexpr std::array<T, SIZE> &operator-=(std::array<T, SIZE> &a, T s) {
651 for (std::size_t d = 0; d < SIZE; ++d) {
652 a[d] -= s;
653 }
654 return a;
655}
656
665template <class T, std::size_t SIZE>
666constexpr std::array<T, SIZE> operator*(const std::array<T, SIZE> &a, T s) {
667 return mulScalar(a, s);
668}
669
678template <class T, std::size_t SIZE>
679constexpr std::array<T, SIZE> &operator*=(std::array<T, SIZE> &a, T s) {
680 for (std::size_t d = 0; d < SIZE; ++d) {
681 a[d] *= s;
682 }
683 return a;
684}
685} // namespace literals
686
696template <class T, std::size_t SIZE>
697double boxDistanceSquared(const std::array<T, SIZE> &aMin, const std::array<T, SIZE> &aMax,
698 const std::array<T, SIZE> &bMin, const std::array<T, SIZE> &bMax) {
699 using namespace autopas::utils::ArrayMath::literals;
702
703 const auto aToB = max(std::array<T, SIZE>{}, aMin - bMax);
704 const auto bToA = max(std::array<T, SIZE>{}, bMin - aMax);
705
706 return dot(aToB, aToB) + dot(bToA, bToA);
707}
708} // namespace autopas::utils::ArrayMath
Namespace to handle mathematical operations of std::array.
Definition: namespaces.h:49
constexpr T dot(const std::array< T, SIZE > &a, const std::array< T, SIZE > &b)
Generates the dot product of two arrays.
Definition: ArrayMath.h:233
constexpr std::array< target_T, SIZE > floorAndCast(const std::array< float_T, SIZE > &a)
Floors all array elements and converts them to a different type.
Definition: ArrayMath.h:334
constexpr std::array< new_T, SIZE > staticCastArray(const std::array< old_T, SIZE > &a)
static_casts all elements of an array to a new type.
Definition: ArrayMath.h:447
constexpr T L2Norm(const std::array< T, SIZE > &a)
Computes the L2Norm / Euclidean norm.
Definition: ArrayMath.h:265
constexpr std::array< T, SIZE > operator*(const std::array< T, SIZE > &a, const std::array< T, SIZE > &b)
Multiplies two array's element wise and returns the result.
Definition: ArrayMath.h:524
constexpr std::array< T, SIZE > ceil(const std::array< T, SIZE > &a)
For each element in a, computes the smallest integer value not less than the element.
Definition: ArrayMath.h:316
constexpr std::array< T, SIZE > & operator*=(std::array< T, SIZE > &a, const std::array< T, SIZE > &b)
Assignment operator to multiply two arrays.
Definition: ArrayMath.h:537
constexpr std::array< T, SIZE > div(const std::array< T, SIZE > &a, const std::array< T, SIZE > &b)
Divides two array's element-wise and returns the result.
Definition: ArrayMath.h:130
constexpr std::array< T, SIZE > mulScalar(const std::array< T, SIZE > &a, T s)
Multiplies a scalar s to each element of array a and returns the result.
Definition: ArrayMath.h:181
constexpr std::array< target_T, SIZE > ceilAndCast(const std::array< float_T, SIZE > &a)
Ceils all array elements and converts them to a different type.
Definition: ArrayMath.h:352
bool isInUlp(Container lhs, Container rhs, unsigned int ulpDistance=Math::MAX_ULP_DISTANCE)
Function for comparing closeness of two floating point numbers using ULP (Units in the Last Place) me...
Definition: ArrayMath.h:372
constexpr std::array< T, SIZE > sub(const std::array< T, SIZE > &a, const std::array< T, SIZE > &b)
Subtracts array b from array a and returns the result.
Definition: ArrayMath.h:45
constexpr std::array< T, SIZE > add(const std::array< T, SIZE > &a, const std::array< T, SIZE > &b)
Adds two arrays, returns the result.
Definition: ArrayMath.h:28
constexpr std::array< T, SIZE > max(const std::array< T, SIZE > &a, const std::array< T, SIZE > &b)
Takes elementwise maximum and returns the result.
Definition: ArrayMath.h:96
constexpr std::array< T, SIZE > divScalar(const std::array< T, SIZE > &a, T s)
Divides an array element-wise by a given scalar and returns the result.
Definition: ArrayMath.h:198
constexpr std::array< T, SIZE > & operator/=(std::array< T, SIZE > &a, const std::array< T, SIZE > &b)
Assignment operator to divide two arrays.
Definition: ArrayMath.h:592
constexpr std::array< T, SIZE > abs(const std::array< T, SIZE > &a)
Computes the absolute value for all elements in a.
Definition: ArrayMath.h:288
constexpr std::array< T, SIZE > subScalar(const std::array< T, SIZE > &a, T s)
Subtracts a scalar s from each element of array a and returns the result.
Definition: ArrayMath.h:164
constexpr std::array< T, SIZE > addScalar(const std::array< T, SIZE > &a, T s)
Adds a scalar s to each element of array a and returns the result.
Definition: ArrayMath.h:147
constexpr std::array< T, SIZE > operator/(const std::array< T, SIZE > &a, const std::array< T, SIZE > &b)
Divides two array's element-wise and returns the result.
Definition: ArrayMath.h:553
constexpr std::array< T, SIZE > & operator-=(std::array< T, SIZE > &a, const std::array< T, SIZE > &b)
Assignment operator to subtract two arrays.
Definition: ArrayMath.h:508
constexpr bool less(const std::array< T, SIZE > &a, const std::array< T, SIZE > &b)
True iff for all d the following holds: a[d] < b[d].
Definition: ArrayMath.h:79
constexpr T::value_type prod(const T &a)
Computes the product of all elements in a.
Definition: ArrayMath.h:276
constexpr std::array< T, SIZE > min(const std::array< T, SIZE > &a, const std::array< T, SIZE > &b)
Takes elementwise minimum, returns the result.
Definition: ArrayMath.h:62
constexpr std::array< T, 3 > cross(const std::array< T, 3 > &a, const std::array< T, 3 > &b)
Generates the cross product of two arrays of 3 floats.
Definition: ArrayMath.h:249
constexpr std::array< T, SIZE > mul(const std::array< T, SIZE > &a, const std::array< T, SIZE > &b)
Multiplies two array's element wise and returns the result.
Definition: ArrayMath.h:113
bool isEqual(const std::vector< T > &a, const std::vector< T > &b)
Returns true if vectors are elementwise equal to each other.
Definition: ArrayMath.h:427
double boxDistanceSquared(const std::array< T, SIZE > &aMin, const std::array< T, SIZE > &aMax, const std::array< T, SIZE > &bMin, const std::array< T, SIZE > &bMax)
Calculate the squared minimum distance between two boxes, which are aligned to the Cartesian grid.
Definition: ArrayMath.h:697
bool isNearRel(Container lhs, Container rhs, double maxRelativeDifference=Math::EPSILON_RELATIVE_EQUALITY)
Returns true if arrays are elementwise relatively near each other.
Definition: ArrayMath.h:387
constexpr std::array< T, SIZE > normalize(const std::array< T, SIZE > &a)
Generates a normalized array (|a| = 1).
Definition: ArrayMath.h:304
constexpr std::array< T, SIZE > & operator+=(std::array< T, SIZE > &a, const std::array< T, SIZE > &b)
Assignment operator to add two arrays.
Definition: ArrayMath.h:479
constexpr std::array< T, SIZE > operator-(const std::array< T, SIZE > &a, const std::array< T, SIZE > &b)
Subtracts array b from array a and returns the result.
Definition: ArrayMath.h:495
constexpr std::array< T, SIZE > operator+(const std::array< T, SIZE > &a, const std::array< T, SIZE > &b)
Adds two arrays, returns the result.
Definition: ArrayMath.h:466