File indexing completed on 2025-09-17 09:13:47
0001 #ifndef BVH_V2_VEC_H
0002 #define BVH_V2_VEC_H
0003
0004 #include "bvh/v2/utils.h"
0005
0006 #include <cstddef>
0007 #include <numeric>
0008 #include <cmath>
0009 #include <algorithm>
0010
0011 namespace bvh::v2 {
0012
0013 template <typename T, size_t N>
0014 struct Vec {
0015 T values[N];
0016
0017 Vec() = default;
0018 template <typename... Args>
0019 BVH_ALWAYS_INLINE Vec(T x, T y, Args&&... args) : values { x, y, static_cast<T>(std::forward<Args>(args))... } {}
0020 BVH_ALWAYS_INLINE explicit Vec(T x) { std::fill(values, values + N, x); }
0021
0022 template <typename Compare>
0023 BVH_ALWAYS_INLINE size_t get_best_axis(Compare&& compare) const {
0024 size_t axis = 0;
0025 static_for<1, N>([&] (size_t i) {
0026 if (compare(values[i], values[axis]))
0027 axis = i;
0028 });
0029 return axis;
0030 }
0031
0032
0033 BVH_ALWAYS_INLINE size_t get_largest_axis() const { return get_best_axis(std::greater<T>()); }
0034 BVH_ALWAYS_INLINE size_t get_smallest_axis() const { return get_best_axis(std::less<T>()); }
0035
0036 BVH_ALWAYS_INLINE T& operator [] (size_t i) { return values[i]; }
0037 BVH_ALWAYS_INLINE T operator [] (size_t i) const { return values[i]; }
0038
0039 template <typename F>
0040 BVH_ALWAYS_INLINE static Vec<T, N> generate(F&& f) {
0041 Vec<T, N> v;
0042 static_for<0, N>([&] (size_t i) { v[i] = f(i); });
0043 return v;
0044 }
0045 };
0046
0047 template <typename T, size_t N>
0048 BVH_ALWAYS_INLINE Vec<T, N> operator + (const Vec<T, N>& a, const Vec<T, N>& b) {
0049 return Vec<T, N>::generate([&] (size_t i) { return a[i] + b[i]; });
0050 }
0051
0052 template <typename T, size_t N>
0053 BVH_ALWAYS_INLINE Vec<T, N> operator - (const Vec<T, N>& a, const Vec<T, N>& b) {
0054 return Vec<T, N>::generate([&] (size_t i) { return a[i] - b[i]; });
0055 }
0056
0057 template <typename T, size_t N>
0058 BVH_ALWAYS_INLINE Vec<T, N> operator - (const Vec<T, N>& a) {
0059 return Vec<T, N>::generate([&] (size_t i) { return -a[i]; });
0060 }
0061
0062 template <typename T, size_t N>
0063 BVH_ALWAYS_INLINE Vec<T, N> operator * (const Vec<T, N>& a, const Vec<T, N>& b) {
0064 return Vec<T, N>::generate([&] (size_t i) { return a[i] * b[i]; });
0065 }
0066
0067 template <typename T, size_t N>
0068 BVH_ALWAYS_INLINE Vec<T, N> operator / (const Vec<T, N>& a, const Vec<T, N>& b) {
0069 return Vec<T, N>::generate([&] (size_t i) { return a[i] / b[i]; });
0070 }
0071
0072 template <typename T, size_t N>
0073 BVH_ALWAYS_INLINE Vec<T, N> operator * (const Vec<T, N>& a, T b) {
0074 return Vec<T, N>::generate([&] (size_t i) { return a[i] * b; });
0075 }
0076
0077 template <typename T, size_t N>
0078 BVH_ALWAYS_INLINE Vec<T, N> operator * (T a, const Vec<T, N>& b) {
0079 return b * a;
0080 }
0081
0082 template <typename T, size_t N>
0083 BVH_ALWAYS_INLINE Vec<T, N> operator / (T a, const Vec<T, N>& b) {
0084 return Vec<T, N>::generate([&] (size_t i) { return a / b[i]; });
0085 }
0086
0087 template <typename T, size_t N>
0088 BVH_ALWAYS_INLINE Vec<T, N> robust_min(const Vec<T, N>& a, const Vec<T, N>& b) {
0089 return Vec<T, N>::generate([&] (size_t i) { return robust_min(a[i], b[i]); });
0090 }
0091
0092 template <typename T, size_t N>
0093 BVH_ALWAYS_INLINE Vec<T, N> robust_max(const Vec<T, N>& a, const Vec<T, N>& b) {
0094 return Vec<T, N>::generate([&] (size_t i) { return robust_max(a[i], b[i]); });
0095 }
0096
0097 template <typename T, size_t N>
0098 BVH_ALWAYS_INLINE T dot(const Vec<T, N>& a, const Vec<T, N>& b) {
0099
0100 return std::inner_product(a.values, a.values + N, b.values, T(0));
0101 }
0102
0103 template <typename T>
0104 BVH_ALWAYS_INLINE Vec<T, 3> cross(const Vec<T, 3>& a, const Vec<T, 3>& b) {
0105 return Vec<T, 3>(
0106 a[1] * b[2] - a[2] * b[1],
0107 a[2] * b[0] - a[0] * b[2],
0108 a[0] * b[1] - a[1] * b[0]);
0109 }
0110
0111 template <typename T, size_t N>
0112 BVH_ALWAYS_INLINE Vec<T, N> fast_mul_add(const Vec<T, N>& a, const Vec<T, N>& b, const Vec<T, N>& c) {
0113 return Vec<T, N>::generate([&] (size_t i) { return fast_mul_add(a[i], b[i], c[i]); });
0114 }
0115
0116 template <typename T, size_t N>
0117 BVH_ALWAYS_INLINE Vec<T, N> safe_inverse(const Vec<T, N>& v) {
0118 return Vec<T, N>::generate([&] (size_t i) { return safe_inverse(v[i]); });
0119 }
0120
0121 template <typename T, size_t N>
0122 BVH_ALWAYS_INLINE T length(const Vec<T, N>& v) {
0123 return std::sqrt(dot(v, v));
0124 }
0125
0126 template <typename T, size_t N>
0127 BVH_ALWAYS_INLINE Vec<T, N> normalize(const Vec<T, N>& v) {
0128 return v * (static_cast<T>(1.) / length(v));
0129 }
0130
0131 }
0132
0133 #endif