diff options
author | Clément Foucault <foucault.clem@gmail.com> | 2022-01-10 19:43:20 +0300 |
---|---|---|
committer | Clément Foucault <foucault.clem@gmail.com> | 2022-01-10 20:21:05 +0300 |
commit | 4c95619a78a3504ae623c223afce6ac4ac4ba1b9 (patch) | |
tree | b9bb850f5a5b89fcd0fcf76587f4a53e36537918 | |
parent | 88498ab9b5fad61fa0d3a82c5e5ae4c57466516f (diff) |
BLI_math_vector: Split vector template and vector functions into 2 files
Also rework the macros to be less context dependent.
-rw-r--r-- | source/blender/blenlib/BLI_double2.hh | 2 | ||||
-rw-r--r-- | source/blender/blenlib/BLI_double3.hh | 2 | ||||
-rw-r--r-- | source/blender/blenlib/BLI_float2.hh | 2 | ||||
-rw-r--r-- | source/blender/blenlib/BLI_float3.hh | 2 | ||||
-rw-r--r-- | source/blender/blenlib/BLI_float4.hh | 2 | ||||
-rw-r--r-- | source/blender/blenlib/BLI_float4x4.hh | 2 | ||||
-rw-r--r-- | source/blender/blenlib/BLI_int2.hh | 2 | ||||
-rw-r--r-- | source/blender/blenlib/BLI_int3.hh | 2 | ||||
-rw-r--r-- | source/blender/blenlib/BLI_int4.hh | 2 | ||||
-rw-r--r-- | source/blender/blenlib/BLI_math_vec_types.hh | 523 | ||||
-rw-r--r-- | source/blender/blenlib/BLI_math_vector.hh | 589 | ||||
-rw-r--r-- | source/blender/blenlib/BLI_mpq3.hh | 2 | ||||
-rw-r--r-- | source/blender/blenlib/CMakeLists.txt | 1 |
13 files changed, 582 insertions, 551 deletions
diff --git a/source/blender/blenlib/BLI_double2.hh b/source/blender/blenlib/BLI_double2.hh index cc28bfa17ab..a2b3c710b6f 100644 --- a/source/blender/blenlib/BLI_double2.hh +++ b/source/blender/blenlib/BLI_double2.hh @@ -20,7 +20,7 @@ * \ingroup bli */ -#include "BLI_math_vector.hh" +#include "BLI_math_vec_types.hh" namespace blender { diff --git a/source/blender/blenlib/BLI_double3.hh b/source/blender/blenlib/BLI_double3.hh index ddb541402f0..cfc39c4ad0a 100644 --- a/source/blender/blenlib/BLI_double3.hh +++ b/source/blender/blenlib/BLI_double3.hh @@ -20,7 +20,7 @@ * \ingroup bli */ -#include "BLI_math_vector.hh" +#include "BLI_math_vec_types.hh" #include "BLI_span.hh" namespace blender { diff --git a/source/blender/blenlib/BLI_float2.hh b/source/blender/blenlib/BLI_float2.hh index 7a769e5a885..5ac99ac9ab9 100644 --- a/source/blender/blenlib/BLI_float2.hh +++ b/source/blender/blenlib/BLI_float2.hh @@ -16,7 +16,7 @@ #pragma once -#include "BLI_math_vector.hh" +#include "BLI_math_vec_types.hh" namespace blender { diff --git a/source/blender/blenlib/BLI_float3.hh b/source/blender/blenlib/BLI_float3.hh index a961cd3f4ff..7b5e30a0cff 100644 --- a/source/blender/blenlib/BLI_float3.hh +++ b/source/blender/blenlib/BLI_float3.hh @@ -16,7 +16,7 @@ #pragma once -#include "BLI_math_vector.hh" +#include "BLI_math_vec_types.hh" namespace blender { diff --git a/source/blender/blenlib/BLI_float4.hh b/source/blender/blenlib/BLI_float4.hh index b2e88d71fed..a4a64570cc1 100644 --- a/source/blender/blenlib/BLI_float4.hh +++ b/source/blender/blenlib/BLI_float4.hh @@ -16,7 +16,7 @@ #pragma once -#include "BLI_math_vector.hh" +#include "BLI_math_vec_types.hh" namespace blender { diff --git a/source/blender/blenlib/BLI_float4x4.hh b/source/blender/blenlib/BLI_float4x4.hh index 7695e94acda..20f99f4315b 100644 --- a/source/blender/blenlib/BLI_float4x4.hh +++ b/source/blender/blenlib/BLI_float4x4.hh @@ -18,8 +18,8 @@ #include "BLI_float3.hh" #include "BLI_math_matrix.h" +#include "BLI_math_vec_types.hh" #include "BLI_math_vector.h" -#include "BLI_math_vector.hh" namespace blender { diff --git a/source/blender/blenlib/BLI_int2.hh b/source/blender/blenlib/BLI_int2.hh index 65f9053f141..a07604eb0c1 100644 --- a/source/blender/blenlib/BLI_int2.hh +++ b/source/blender/blenlib/BLI_int2.hh @@ -20,7 +20,7 @@ * \ingroup bli */ -#include "BLI_math_vector.hh" +#include "BLI_math_vec_types.hh" namespace blender { diff --git a/source/blender/blenlib/BLI_int3.hh b/source/blender/blenlib/BLI_int3.hh index aceb61b0bae..8a0c4ec81ce 100644 --- a/source/blender/blenlib/BLI_int3.hh +++ b/source/blender/blenlib/BLI_int3.hh @@ -20,7 +20,7 @@ * \ingroup bli */ -#include "BLI_math_vector.hh" +#include "BLI_math_vec_types.hh" namespace blender { diff --git a/source/blender/blenlib/BLI_int4.hh b/source/blender/blenlib/BLI_int4.hh index 4c975e6defb..7a64000ccaa 100644 --- a/source/blender/blenlib/BLI_int4.hh +++ b/source/blender/blenlib/BLI_int4.hh @@ -20,7 +20,7 @@ * \ingroup bli */ -#include "BLI_math_vector.hh" +#include "BLI_math_vec_types.hh" namespace blender { diff --git a/source/blender/blenlib/BLI_math_vec_types.hh b/source/blender/blenlib/BLI_math_vec_types.hh new file mode 100644 index 00000000000..9ba29d41684 --- /dev/null +++ b/source/blender/blenlib/BLI_math_vec_types.hh @@ -0,0 +1,523 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Copyright 2022, Blender Foundation. + */ + +#pragma once + +/** \file + * \ingroup bli + */ + +#include <array> +#include <cmath> +#include <iostream> +#include <type_traits> + +#include "BLI_math_vector.hh" +#include "BLI_utildefines.h" + +namespace blender { + +/* clang-format off */ +template<typename T> +using as_uint_type = std::conditional_t<sizeof(T) == sizeof(uint8_t), uint8_t, + std::conditional_t<sizeof(T) == sizeof(uint16_t), uint16_t, + std::conditional_t<sizeof(T) == sizeof(uint32_t), uint32_t, uint64_t>>>; +/* clang-format on */ + +template<typename T, int Size> struct vec_struct_base { + std::array<T, Size> values; +}; + +template<typename T> struct vec_struct_base<T, 2> { + T x, y; +}; + +template<typename T> struct vec_struct_base<T, 3> { + T x, y, z; +}; + +template<typename T> struct vec_struct_base<T, 4> { + T x, y, z, w; +}; + +template<typename T, int Size> struct vec_base : public vec_struct_base<T, Size> { + + static constexpr int type_length = Size; + + typedef T base_type; + typedef vec_base<as_uint_type<T>, Size> uint_type; + + vec_base() = default; + + explicit vec_base(uint value) + { + for (int i = 0; i < Size; i++) { + (*this)[i] = static_cast<T>(value); + } + } + + explicit vec_base(int value) + { + for (int i = 0; i < Size; i++) { + (*this)[i] = static_cast<T>(value); + } + } + + explicit vec_base(float value) + { + for (int i = 0; i < Size; i++) { + (*this)[i] = static_cast<T>(value); + } + } + + explicit vec_base(double value) + { + for (int i = 0; i < Size; i++) { + (*this)[i] = static_cast<T>(value); + } + } + +/* Workaround issue with template. */ +#define BLI_VEC_ENABLE_IF(_size, _test) int S = _size, BLI_ENABLE_IF((S _test)) + + template<BLI_VEC_ENABLE_IF(Size, == 2)> vec_base(T _x, T _y) + { + (*this)[0] = _x; + (*this)[1] = _y; + } + + template<BLI_VEC_ENABLE_IF(Size, == 3)> vec_base(T _x, T _y, T _z) + { + (*this)[0] = _x; + (*this)[1] = _y; + (*this)[2] = _z; + } + + template<BLI_VEC_ENABLE_IF(Size, == 4)> vec_base(T _x, T _y, T _z, T _w) + { + (*this)[0] = _x; + (*this)[1] = _y; + (*this)[2] = _z; + (*this)[3] = _w; + } + + /** Mixed scalar-vector constructors. */ + + template<typename U, BLI_VEC_ENABLE_IF(Size, == 3)> + constexpr vec_base(const vec_base<U, 2> &xy, T z) + : vec_base(static_cast<T>(xy.x), static_cast<T>(xy.y), z) + { + } + + template<typename U, BLI_VEC_ENABLE_IF(Size, == 3)> + constexpr vec_base(T x, const vec_base<U, 2> &yz) + : vec_base(x, static_cast<T>(yz.x), static_cast<T>(yz.y)) + { + } + + template<typename U, BLI_VEC_ENABLE_IF(Size, == 4)> + vec_base(vec_base<U, 3> xyz, T w) + : vec_base( + static_cast<T>(xyz.x), static_cast<T>(xyz.y), static_cast<T>(xyz.z), static_cast<T>(w)) + { + } + + template<typename U, BLI_VEC_ENABLE_IF(Size, == 4)> + vec_base(T x, vec_base<U, 3> yzw) + : vec_base( + static_cast<T>(x), static_cast<T>(yzw.x), static_cast<T>(yzw.y), static_cast<T>(yzw.z)) + { + } + + template<typename U, BLI_VEC_ENABLE_IF(Size, == 4)> + vec_base(vec_base<U, 2> xy, vec_base<U, 2> zw) + : vec_base( + static_cast<T>(xy.x), static_cast<T>(xy.y), static_cast<T>(zw.x), static_cast<T>(zw.y)) + { + } + + template<typename U, BLI_VEC_ENABLE_IF(Size, == 4)> + vec_base(vec_base<U, 2> xy, T z, T w) + : vec_base(static_cast<T>(xy.x), static_cast<T>(xy.y), static_cast<T>(z), static_cast<T>(w)) + { + } + + template<typename U, BLI_VEC_ENABLE_IF(Size, == 4)> + vec_base(T x, vec_base<U, 2> yz, T w) + : vec_base(static_cast<T>(x), static_cast<T>(yz.x), static_cast<T>(yz.y), static_cast<T>(w)) + { + } + + template<typename U, BLI_VEC_ENABLE_IF(Size, == 4)> + vec_base(T x, T y, vec_base<U, 2> zw) + : vec_base(static_cast<T>(x), static_cast<T>(y), static_cast<T>(zw.x), static_cast<T>(zw.y)) + { + } + + /** Masking. */ + + template<BLI_VEC_ENABLE_IF(Size, >= 3)> explicit operator vec_base<T, 2>() const + { + return vec_base<T, 2>(UNPACK2(*this)); + } + + template<BLI_VEC_ENABLE_IF(Size, >= 4)> explicit operator vec_base<T, 3>() const + { + return vec_base<T, 3>(UNPACK3(*this)); + } + +#undef BLI_VEC_ENABLE_IF + + /** Conversion from pointers (from C-style vectors). */ + + vec_base(const T *ptr) + { + for (int i = 0; i < Size; i++) { + (*this)[i] = ptr[i]; + } + } + + vec_base(const T (*ptr)[Size]) : vec_base(static_cast<const T *>(ptr[0])) + { + } + + /** Conversion from other vector types. */ + + template<typename U> explicit vec_base(const vec_base<U, Size> &vec) + { + for (int i = 0; i < Size; i++) { + (*this)[i] = static_cast<T>(vec[i]); + } + } + + /** C-style pointer dereference. */ + + operator const T *() const + { + return reinterpret_cast<const T *>(this); + } + + operator T *() + { + return reinterpret_cast<T *>(this); + } + + /** Array access. */ + + const T &operator[](int index) const + { + BLI_assert(index >= 0); + BLI_assert(index < Size); + return reinterpret_cast<const T *>(this)[index]; + } + + T &operator[](int index) + { + BLI_assert(index >= 0); + BLI_assert(index < Size); + return reinterpret_cast<T *>(this)[index]; + } + + /** Internal Operators Macro. */ + +#define VEC_INT_OP(_T) template<typename U = _T, BLI_ENABLE_IF((std::is_integral_v<U>))> + +#define BLI_VEC_OP(_result, _i, _op) \ + vec_base _result; \ + for (int _i = 0; _i < Size; _i++) { \ + _op; \ + } \ + return _result; + +#define BLI_VEC_OP_SELF(_i, _op) \ + for (int _i = 0; _i < Size; _i++) { \ + _op; \ + } \ + return *this; + + /** Arithmetic operators. */ + + friend vec_base operator+(const vec_base &a, const vec_base &b) + { + BLI_VEC_OP(ret, i, ret[i] = a[i] + b[i]); + } + + friend vec_base operator+(const vec_base &a, const T &b) + { + BLI_VEC_OP(ret, i, ret[i] = a[i] + b); + } + + friend vec_base operator+(const T &a, const vec_base &b) + { + return b + a; + } + + vec_base &operator+=(const vec_base &b) + { + BLI_VEC_OP_SELF(i, (*this)[i] += b[i]); + } + + vec_base &operator+=(const T &b) + { + BLI_VEC_OP_SELF(i, (*this)[i] += b); + } + + friend vec_base operator-(const vec_base &a) + { + BLI_VEC_OP(ret, i, ret[i] = -a[i]); + } + + friend vec_base operator-(const vec_base &a, const vec_base &b) + { + BLI_VEC_OP(ret, i, ret[i] = a[i] - b[i]); + } + + friend vec_base operator-(const vec_base &a, const T &b) + { + BLI_VEC_OP(ret, i, ret[i] = a[i] - b); + } + + friend vec_base operator-(const T &a, const vec_base &b) + { + BLI_VEC_OP(ret, i, ret[i] = a - b[i]); + } + + vec_base &operator-=(const vec_base &b) + { + BLI_VEC_OP_SELF(i, (*this)[i] -= b[i]); + } + + vec_base &operator-=(const T &b) + { + BLI_VEC_OP_SELF(i, (*this)[i] -= b); + } + + friend vec_base operator*(const vec_base &a, const vec_base &b) + { + BLI_VEC_OP(ret, i, ret[i] = a[i] * b[i]); + } + + friend vec_base operator*(const vec_base &a, T b) + { + BLI_VEC_OP(ret, i, ret[i] = a[i] * b); + } + + friend vec_base operator*(T a, const vec_base &b) + { + return b * a; + } + + vec_base &operator*=(T b) + { + BLI_VEC_OP_SELF(i, (*this)[i] *= b); + } + + vec_base &operator*=(const vec_base &b) + { + BLI_VEC_OP_SELF(i, (*this)[i] *= b[i]); + } + + friend vec_base operator/(const vec_base &a, const vec_base &b) + { + BLI_assert(!b.is_any_zero()); + BLI_VEC_OP(ret, i, ret[i] = a[i] / b[i]); + } + + friend vec_base operator/(const vec_base &a, T b) + { + BLI_assert(b != T(0)); + BLI_VEC_OP(ret, i, ret[i] = a[i] / b); + } + + friend vec_base operator/(T a, const vec_base &b) + { + BLI_assert(!b.is_any_zero()); + BLI_VEC_OP(ret, i, ret[i] = a / b[i]); + } + + vec_base &operator/=(T b) + { + BLI_assert(b != T(0)); + BLI_VEC_OP_SELF(i, (*this)[i] /= b); + } + + vec_base &operator/=(const vec_base &b) + { + BLI_assert(!b.is_any_zero()); + BLI_VEC_OP_SELF(i, (*this)[i] /= b[i]); + } + + /** Binary operators. */ + + VEC_INT_OP(T) friend vec_base operator&(const vec_base &a, const vec_base &b) + { + BLI_VEC_OP(ret, i, ret[i] = a[i] & b[i]); + } + + VEC_INT_OP(T) friend vec_base operator&(const vec_base &a, T b) + { + BLI_VEC_OP(ret, i, ret[i] = a[i] & b); + } + + VEC_INT_OP(T) friend vec_base operator&(T a, const vec_base &b) + { + return b & a; + } + + VEC_INT_OP(T) vec_base &operator&=(T b) + { + BLI_VEC_OP_SELF(i, (*this)[i] &= b); + } + + VEC_INT_OP(T) vec_base &operator&=(const vec_base &b) + { + BLI_VEC_OP_SELF(i, (*this)[i] &= b[i]); + } + + VEC_INT_OP(T) friend vec_base operator|(const vec_base &a, const vec_base &b) + { + BLI_VEC_OP(ret, i, ret[i] = a[i] | b[i]); + } + + VEC_INT_OP(T) friend vec_base operator|(const vec_base &a, T b) + { + BLI_VEC_OP(ret, i, ret[i] = a[i] | b); + } + + VEC_INT_OP(T) friend vec_base operator|(T a, const vec_base &b) + { + return b | a; + } + + VEC_INT_OP(T) vec_base &operator|=(T b) + { + BLI_VEC_OP_SELF(i, (*this)[i] |= b); + } + + VEC_INT_OP(T) vec_base &operator|=(const vec_base &b) + { + BLI_VEC_OP_SELF(i, (*this)[i] |= b[i]); + } + + VEC_INT_OP(T) friend vec_base operator^(const vec_base &a, const vec_base &b) + { + BLI_VEC_OP(ret, i, ret[i] = a[i] ^ b[i]); + } + + VEC_INT_OP(T) friend vec_base operator^(const vec_base &a, T b) + { + BLI_VEC_OP(ret, i, ret[i] = a[i] ^ b); + } + + VEC_INT_OP(T) friend vec_base operator^(T a, const vec_base &b) + { + return b ^ a; + } + + VEC_INT_OP(T) vec_base &operator^=(T b) + { + BLI_VEC_OP_SELF(i, (*this)[i] ^= b); + } + + VEC_INT_OP(T) vec_base &operator^=(const vec_base &b) + { + BLI_VEC_OP_SELF(i, (*this)[i] ^= b[i]); + } + + VEC_INT_OP(T) friend vec_base operator~(const vec_base &a) + { + BLI_VEC_OP(ret, i, ret[i] = ~a[i]); + } + + /** Modulo operators. */ + + VEC_INT_OP(T) friend vec_base operator%(const vec_base &a, const vec_base &b) + { + BLI_VEC_OP(ret, i, ret[i] = a[i] % b[i]); + } + + VEC_INT_OP(T) friend vec_base operator%(const vec_base &a, T b) + { + BLI_VEC_OP(ret, i, ret[i] = a[i] % b); + } + + VEC_INT_OP(T) friend vec_base operator%(T a, const vec_base &b) + { + BLI_VEC_OP(ret, i, ret[i] = a % b[i]); + } + +#undef VEC_INT_OP +#undef BLI_VEC_OP +#undef BLI_VEC_OP_SELF + + /** Compare. */ + + friend bool operator==(const vec_base &a, const vec_base &b) + { + bool result = true; + for (int i = 0; i < Size; i++) { + result = result && (a[i] == b[i]); + } + return result; + } + + friend bool operator!=(const vec_base &a, const vec_base &b) + { + return !(a == b); + } + + bool is_zero() const + { + bool result = true; + for (int i = 0; i < Size; i++) { + result = result && ((*this)[i] == T(0)); + } + return result; + } + + bool is_any_zero() const + { + bool result = false; + for (int i = 0; i < Size && result; i++) { + result = result || ((*this)[i] == T(0)); + } + return result; + } + + /** Misc. */ + + uint64_t hash() const + { + return math::vector_hash(*this); + } + + friend std::ostream &operator<<(std::ostream &stream, const vec_base &v) + { + stream << "("; + for (int i = 0; i < Size; i++) { + stream << v[i]; + if (i != Size - 1) { + stream << ", "; + } + } + stream << ")"; + return stream; + } +}; + +} // namespace blender diff --git a/source/blender/blenlib/BLI_math_vector.hh b/source/blender/blenlib/BLI_math_vector.hh index 5eb1d63e22a..2d486783624 100644 --- a/source/blender/blenlib/BLI_math_vector.hh +++ b/source/blender/blenlib/BLI_math_vector.hh @@ -22,9 +22,7 @@ * \ingroup bli */ -#include <array> #include <cmath> -#include <iostream> #include <type_traits> #include "BLI_math_base_safe.h" @@ -35,28 +33,31 @@ # include "BLI_math_mpq.hh" #endif -#define ASSERT_UNIT_VECTOR(v) \ - { \ - const float _test_unit = length_squared(v); \ - BLI_assert(!(std::abs(_test_unit - 1.0f) >= BLI_ASSERT_UNIT_EPSILON) || \ - !(std::abs(_test_unit) >= BLI_ASSERT_UNIT_EPSILON)); \ - } \ - (void)0 +#ifndef NDEBUG +# define BLI_ASSERT_UNIT(v) \ + { \ + const float _test_unit = length_squared(v); \ + BLI_assert(!(std::abs(_test_unit - 1.0f) >= BLI_ASSERT_UNIT_EPSILON) || \ + !(std::abs(_test_unit) >= BLI_ASSERT_UNIT_EPSILON)); \ + } \ + (void)0 +#else +# define BLI_ASSERT_UNIT(v) (void)(v) +#endif namespace blender::math { #define bT typename T::base_type #ifdef WITH_GMP -# define IS_FLOATING_POINT \ - typename std::enable_if_t< \ - std::disjunction_v<std::is_floating_point<bT>, std::is_same<bT, mpq_class>>> * = nullptr +# define BLI_IS_FLT_VEC(T) \ + BLI_ENABLE_IF((std::disjunction_v<std::is_floating_point<typename T::base_type>, \ + std::is_same<typename T::base_type, mpq_class>>)) #else -# define IS_FLOATING_POINT \ - typename std::enable_if_t<std::is_floating_point<bT>::value> * = nullptr +# define BLI_IS_FLT_VEC(T) BLI_ENABLE_IF((std::is_floating_point<typename T::base_type>::value)) #endif -#define IS_INTEGRAL typename std::enable_if_t<std::is_integral<bT>::value> * = nullptr +#define BLI_IS_INT_VEC BLI_ENABLE_IF((std::is_integral<bT>::value)) template<typename T> inline T abs(const T &a) { @@ -86,7 +87,7 @@ template<typename T> inline T max(const T &a, const T &b) } /* Always safe. */ -template<typename T, IS_FLOATING_POINT> inline T mod(const T &a, const T &b) +template<typename T, BLI_IS_FLT_VEC(T)> inline T mod(const T &a, const T &b) { T result; for (int i = 0; i < T::type_length; i++) { @@ -96,7 +97,7 @@ template<typename T, IS_FLOATING_POINT> inline T mod(const T &a, const T &b) } /* Always safe. */ -template<typename T, IS_FLOATING_POINT> inline T mod(const T &a, bT b) +template<typename T, BLI_IS_FLT_VEC(T)> inline T mod(const T &a, bT b) { if (b == 0) { return T(0.0f); @@ -114,7 +115,7 @@ template<typename T> inline void min_max(const T &vector, T &min_vec, T &max_vec max_vec = max(vector, max_vec); } -template<typename T, IS_FLOATING_POINT> inline T safe_divide(const T &a, const T &b) +template<typename T, BLI_IS_FLT_VEC(T)> inline T safe_divide(const T &a, const T &b) { T result; for (int i = 0; i < T::type_length; i++) { @@ -123,12 +124,12 @@ template<typename T, IS_FLOATING_POINT> inline T safe_divide(const T &a, const T return result; } -template<typename T, IS_FLOATING_POINT> inline T safe_divide(const T &a, const bT b) +template<typename T, BLI_IS_FLT_VEC(T)> inline T safe_divide(const T &a, const bT b) { return (b != 0) ? a / b : T(0.0f); } -template<typename T, IS_FLOATING_POINT> inline T floor(const T &a) +template<typename T, BLI_IS_FLT_VEC(T)> inline T floor(const T &a) { T result; for (int i = 0; i < T::type_length; i++) { @@ -137,7 +138,7 @@ template<typename T, IS_FLOATING_POINT> inline T floor(const T &a) return result; } -template<typename T, IS_FLOATING_POINT> inline T ceil(const T &a) +template<typename T, BLI_IS_FLT_VEC(T)> inline T ceil(const T &a) { T result; for (int i = 0; i < T::type_length; i++) { @@ -146,7 +147,7 @@ template<typename T, IS_FLOATING_POINT> inline T ceil(const T &a) return result; } -template<typename T, IS_FLOATING_POINT> inline T fract(const T &a) +template<typename T, BLI_IS_FLT_VEC(T)> inline T fract(const T &a) { T result; for (int i = 0; i < T::type_length; i++) { @@ -155,7 +156,7 @@ template<typename T, IS_FLOATING_POINT> inline T fract(const T &a) return result; } -template<typename T, IS_FLOATING_POINT> inline bT dot(const T &a, const T &b) +template<typename T, BLI_IS_FLT_VEC(T)> inline bT dot(const T &a, const T &b) { bT result = a[0] * b[0]; for (int i = 1; i < T::type_length; i++) { @@ -164,51 +165,51 @@ template<typename T, IS_FLOATING_POINT> inline bT dot(const T &a, const T &b) return result; } -template<typename T, IS_FLOATING_POINT> inline bT length_squared(const T &a) +template<typename T, BLI_IS_FLT_VEC(T)> inline bT length_squared(const T &a) { return dot(a, a); } -template<typename T, IS_FLOATING_POINT> inline bT length(const T &a) +template<typename T, BLI_IS_FLT_VEC(T)> inline bT length(const T &a) { return std::sqrt(length_squared(a)); } -template<typename T, IS_FLOATING_POINT> inline bT distance_squared(const T &a, const T &b) +template<typename T, BLI_IS_FLT_VEC(T)> inline bT distance_squared(const T &a, const T &b) { return length_squared(a - b); } -template<typename T, IS_FLOATING_POINT> inline bT distance(const T &a, const T &b) +template<typename T, BLI_IS_FLT_VEC(T)> inline bT distance(const T &a, const T &b) { return length(a - b); } template<typename T> uint64_t vector_hash(const T &vec) { + BLI_STATIC_ASSERT(T::type_length <= 4, "Longer types need to implement vector_hash themself."); const typename T::uint_type &uvec = *reinterpret_cast<const typename T::uint_type *>(&vec); - uint64_t result; - result = uvec.x * uint64_t(435109); + result = uvec[0] * uint64_t(435109); if constexpr (T::type_length > 1) { - result ^= uvec.y * uint64_t(380867); + result ^= uvec[1] * uint64_t(380867); } if constexpr (T::type_length > 2) { - result ^= uvec.z * uint64_t(1059217); + result ^= uvec[2] * uint64_t(1059217); } if constexpr (T::type_length > 3) { - result ^= uvec.w * uint64_t(2002613); + result ^= uvec[3] * uint64_t(2002613); } return result; } -template<typename T, IS_FLOATING_POINT> inline T reflect(const T &incident, const T &normal) +template<typename T, BLI_IS_FLT_VEC(T)> inline T reflect(const T &incident, const T &normal) { - ASSERT_UNIT_VECTOR(normal); + BLI_ASSERT_UNIT(normal); return incident - 2.0 * dot(normal, incident) * normal; } -template<typename T, IS_FLOATING_POINT> +template<typename T, BLI_IS_FLT_VEC(T)> inline T refract(const T &incident, const T &normal, const bT eta) { float dot_ni = dot(normal, incident); @@ -219,7 +220,7 @@ inline T refract(const T &incident, const T &normal, const bT eta) return eta * incident - (eta * dot_ni + sqrt(k)) * normal; } -template<typename T, IS_FLOATING_POINT> inline T project(const T &p, const T &v_proj) +template<typename T, BLI_IS_FLT_VEC(T)> inline T project(const T &p, const T &v_proj) { if (UNLIKELY(v_proj.is_zero())) { return T(0.0f); @@ -227,7 +228,7 @@ template<typename T, IS_FLOATING_POINT> inline T project(const T &p, const T &v_ return v_proj * (dot(p, v_proj) / dot(v_proj, v_proj)); } -template<typename T, IS_FLOATING_POINT> +template<typename T, BLI_IS_FLT_VEC(T)> inline T normalize_and_get_length(const T &v, bT &out_length) { out_length = length_squared(v); @@ -242,19 +243,19 @@ inline T normalize_and_get_length(const T &v, bT &out_length) return T(0.0); } -template<typename T, IS_FLOATING_POINT> inline T normalize(const T &v) +template<typename T, BLI_IS_FLT_VEC(T)> inline T normalize(const T &v) { bT len; return normalize_and_get_length(v, len); } -template<typename T, IS_FLOATING_POINT> inline T cross(const T &a, const T &b) +template<typename T, BLI_IS_FLT_VEC(T)> inline T cross(const T &a, const T &b) { BLI_STATIC_ASSERT(T::type_length == 3, ""); return {a.y * b.z - a.z * b.y, a.z * b.x - a.x * b.z, a.x * b.y - a.y * b.x}; } -template<typename T, typename std::enable_if_t<std::is_same<bT, float>::value> * = nullptr> +template<typename T, BLI_ENABLE_IF((std::is_same_v<bT, float>))> inline T cross_high_precision(const T &a, const T &b) { BLI_STATIC_ASSERT(T::type_length == 3, ""); @@ -263,18 +264,18 @@ inline T cross_high_precision(const T &a, const T &b) (float)((double)a.x * b.y - (double)a.y * b.x)}; } -template<typename T, IS_FLOATING_POINT> inline T interpolate(const T &a, const T &b, bT t) +template<typename T, BLI_IS_FLT_VEC(T)> inline T interpolate(const T &a, const T &b, bT t) { return a * (1 - t) + b * t; } -template<typename T, IS_FLOATING_POINT> +template<typename T, BLI_IS_FLT_VEC(T)> inline T faceforward(const T &vector, const T &incident, const T &reference) { return (dot(reference, incident) < 0) ? vector : -vector; } -template<typename T, IS_FLOATING_POINT> inline int dominant_axis(const T &a) +template<typename T> inline int dominant_axis(const T &a) { T b = abs(a); return ((b.x > b.y) ? ((b.x > b.z) ? 0 : 2) : ((b.y > b.z) ? 1 : 2)); @@ -282,7 +283,7 @@ template<typename T, IS_FLOATING_POINT> inline int dominant_axis(const T &a) /** Intersections. */ -template<typename T, IS_FLOATING_POINT> struct isect_result { +template<typename T, BLI_IS_FLT_VEC(T)> struct isect_result { enum { LINE_LINE_COLINEAR = -1, LINE_LINE_NONE = 0, @@ -292,505 +293,11 @@ template<typename T, IS_FLOATING_POINT> struct isect_result { bT lambda; }; -/* TODO(fclem) Should be moved to math namespace once mpq2 is using the template. */ -template<typename T, IS_FLOATING_POINT> +template<typename T, BLI_IS_FLT_VEC(T)> isect_result<T> isect_seg_seg(const T &v1, const T &v2, const T &v3, const T &v4); -#undef ASSERT_UNIT_VECTOR -#undef IS_FLOATING_POINT -#undef IS_INTEGRAL +#undef BLI_IS_FLT_VEC +#undef BLI_IS_INT_VEC #undef bT } // namespace blender::math - -namespace blender { - -/* clang-format off */ -template<typename T> -using as_uint_type = std::conditional_t<sizeof(T) == sizeof(uint8_t), uint8_t, - std::conditional_t<sizeof(T) == sizeof(uint16_t), uint16_t, - std::conditional_t<sizeof(T) == sizeof(uint32_t), uint32_t, uint64_t>>>; -/* clang-format on */ - -/* FIXME(fclem): This does not works. */ -#define INTEGRAL_OP /* template<typename std::enable_if_t<std::is_integral_v<bT>> * = nullptr> */ - -template<typename T, int Size> struct vec_struct_base { - std::array<T, Size> values; -}; - -template<typename T> struct vec_struct_base<T, 2> { - T x, y; -}; - -template<typename T> struct vec_struct_base<T, 3> { - T x, y, z; -}; - -template<typename T> struct vec_struct_base<T, 4> { - T x, y, z, w; -}; - -template<typename T, int Size> struct vec_base : public vec_struct_base<T, Size> { - - static constexpr int type_length = Size; - - typedef T base_type; - typedef vec_base<as_uint_type<T>, Size> uint_type; - - vec_base() = default; - - explicit vec_base(uint value) - { - for (int i = 0; i < Size; i++) { - (*this)[i] = static_cast<T>(value); - } - } - - explicit vec_base(int value) - { - for (int i = 0; i < Size; i++) { - (*this)[i] = static_cast<T>(value); - } - } - - explicit vec_base(float value) - { - for (int i = 0; i < Size; i++) { - (*this)[i] = static_cast<T>(value); - } - } - - explicit vec_base(double value) - { - for (int i = 0; i < Size; i++) { - (*this)[i] = static_cast<T>(value); - } - } - -#define VECTOR_ENABLE_IF_SIZE_IS(_test) \ - int S = Size, typename std::enable_if_t<S _test> * = nullptr - - template<VECTOR_ENABLE_IF_SIZE_IS(== 2)> vec_base(T _x, T _y) - { - (*this)[0] = _x; - (*this)[1] = _y; - } - - template<VECTOR_ENABLE_IF_SIZE_IS(== 3)> vec_base(T _x, T _y, T _z) - { - (*this)[0] = _x; - (*this)[1] = _y; - (*this)[2] = _z; - } - - template<VECTOR_ENABLE_IF_SIZE_IS(== 4)> vec_base(T _x, T _y, T _z, T _w) - { - (*this)[0] = _x; - (*this)[1] = _y; - (*this)[2] = _z; - (*this)[3] = _w; - } - - /** Mixed scalar-vector constructors. */ - - template<typename U, VECTOR_ENABLE_IF_SIZE_IS(== 3)> - constexpr vec_base(const vec_base<U, 2> &xy, T z) - : vec_base(static_cast<T>(xy.x), static_cast<T>(xy.y), z) - { - } - - template<typename U, VECTOR_ENABLE_IF_SIZE_IS(== 3)> - constexpr vec_base(T x, const vec_base<U, 2> &yz) - : vec_base(x, static_cast<T>(yz.x), static_cast<T>(yz.y)) - { - } - - template<typename U, VECTOR_ENABLE_IF_SIZE_IS(== 4)> - vec_base(vec_base<U, 3> xyz, T w) - : vec_base( - static_cast<T>(xyz.x), static_cast<T>(xyz.y), static_cast<T>(xyz.z), static_cast<T>(w)) - { - } - - template<typename U, VECTOR_ENABLE_IF_SIZE_IS(== 4)> - vec_base(T x, vec_base<U, 3> yzw) - : vec_base( - static_cast<T>(x), static_cast<T>(yzw.x), static_cast<T>(yzw.y), static_cast<T>(yzw.z)) - { - } - - template<typename U, VECTOR_ENABLE_IF_SIZE_IS(== 4)> - vec_base(vec_base<U, 2> xy, vec_base<U, 2> zw) - : vec_base( - static_cast<T>(xy.x), static_cast<T>(xy.y), static_cast<T>(zw.x), static_cast<T>(zw.y)) - { - } - - template<typename U, VECTOR_ENABLE_IF_SIZE_IS(== 4)> - vec_base(vec_base<U, 2> xy, T z, T w) - : vec_base(static_cast<T>(xy.x), static_cast<T>(xy.y), static_cast<T>(z), static_cast<T>(w)) - { - } - - template<typename U, VECTOR_ENABLE_IF_SIZE_IS(== 4)> - vec_base(T x, vec_base<U, 2> yz, T w) - : vec_base(static_cast<T>(x), static_cast<T>(yz.x), static_cast<T>(yz.y), static_cast<T>(w)) - { - } - - template<typename U, VECTOR_ENABLE_IF_SIZE_IS(== 4)> - vec_base(T x, T y, vec_base<U, 2> zw) - : vec_base(static_cast<T>(x), static_cast<T>(y), static_cast<T>(zw.x), static_cast<T>(zw.y)) - { - } - - /** Masking. */ - - template<VECTOR_ENABLE_IF_SIZE_IS(>= 3)> explicit operator vec_base<T, 2>() const - { - return vec_base<T, 2>(UNPACK2(*this)); - } - - template<VECTOR_ENABLE_IF_SIZE_IS(>= 4)> explicit operator vec_base<T, 3>() const - { - return vec_base<T, 3>(UNPACK3(*this)); - } - -#undef VECTOR_ENABLE_IF_SIZE_IS - - /** Conversion from pointers (from C-style vectors). */ - - vec_base(const T *ptr) - { - for (int i = 0; i < Size; i++) { - (*this)[i] = ptr[i]; - } - } - - vec_base(const T (*ptr)[Size]) : vec_base(static_cast<const T *>(ptr[0])) - { - } - - /** Conversion from other vector types. */ - - template<typename U> explicit vec_base(const vec_base<U, Size> &vec) - { - for (int i = 0; i < Size; i++) { - (*this)[i] = static_cast<T>(vec[i]); - } - } - - /** C-style pointer dereference. */ - - operator const T *() const - { - return reinterpret_cast<const T *>(this); - } - - operator T *() - { - return reinterpret_cast<T *>(this); - } - - /** Array access. */ - - const T &operator[](int index) const - { - BLI_assert(index >= 0); - BLI_assert(index < Size); - return reinterpret_cast<const T *>(this)[index]; - } - - T &operator[](int index) - { - BLI_assert(index >= 0); - BLI_assert(index < Size); - return reinterpret_cast<T *>(this)[index]; - } - - /** Arithmetic operators. */ - -#define VECTOR_OP(_op) \ - vec_base result; \ - for (int i = 0; i < Size; i++) { \ - _op; \ - } \ - return result; - -#define VECTOR_SELF_OP(_op) \ - for (int i = 0; i < Size; i++) { \ - _op; \ - } \ - return *this; - - friend vec_base operator+(const vec_base &a, const vec_base &b) - { - VECTOR_OP(result[i] = a[i] + b[i]); - } - - friend vec_base operator+(const vec_base &a, const T &b) - { - VECTOR_OP(result[i] = a[i] + b); - } - - friend vec_base operator+(const T &a, const vec_base &b) - { - return b + a; - } - - vec_base &operator+=(const vec_base &b) - { - VECTOR_SELF_OP((*this)[i] += b[i]); - } - - vec_base &operator+=(const T &b) - { - VECTOR_SELF_OP((*this)[i] += b); - } - - friend vec_base operator-(const vec_base &a) - { - VECTOR_OP(result[i] = -a[i]); - } - - friend vec_base operator-(const vec_base &a, const vec_base &b) - { - VECTOR_OP(result[i] = a[i] - b[i]); - } - - friend vec_base operator-(const vec_base &a, const T &b) - { - VECTOR_OP(result[i] = a[i] - b); - } - - friend vec_base operator-(const T &a, const vec_base &b) - { - VECTOR_OP(result[i] = a - b[i]); - } - - vec_base &operator-=(const vec_base &b) - { - VECTOR_SELF_OP((*this)[i] -= b[i]); - } - - vec_base &operator-=(const T &b) - { - VECTOR_SELF_OP((*this)[i] -= b); - } - - friend vec_base operator*(const vec_base &a, const vec_base &b) - { - VECTOR_OP(result[i] = a[i] * b[i]); - } - - friend vec_base operator*(const vec_base &a, T b) - { - VECTOR_OP(result[i] = a[i] * b); - } - - friend vec_base operator*(T a, const vec_base &b) - { - return b * a; - } - - vec_base &operator*=(T b) - { - VECTOR_SELF_OP((*this)[i] *= b); - } - - vec_base &operator*=(const vec_base &b) - { - VECTOR_SELF_OP((*this)[i] *= b[i]); - } - - friend vec_base operator/(const vec_base &a, const vec_base &b) - { - BLI_assert(!b.is_any_zero()); - VECTOR_OP(result[i] = a[i] / b[i]); - } - - friend vec_base operator/(const vec_base &a, T b) - { - BLI_assert(b != T(0)); - VECTOR_OP(result[i] = a[i] / b); - } - - friend vec_base operator/(T a, const vec_base &b) - { - BLI_assert(!b.is_any_zero()); - VECTOR_OP(result[i] = a / b[i]); - } - - vec_base &operator/=(T b) - { - BLI_assert(b != T(0)); - VECTOR_SELF_OP((*this)[i] /= b); - } - - vec_base &operator/=(const vec_base &b) - { - BLI_assert(!b.is_any_zero()); - VECTOR_SELF_OP((*this)[i] /= b[i]); - } - - /** Binary operators. */ - - INTEGRAL_OP friend vec_base operator&(const vec_base &a, const vec_base &b) - { - VECTOR_OP(result[i] = a[i] & b[i]); - } - - INTEGRAL_OP friend vec_base operator&(const vec_base &a, T b) - { - VECTOR_OP(result[i] = a[i] & b); - } - - INTEGRAL_OP friend vec_base operator&(T a, const vec_base &b) - { - return b & a; - } - - INTEGRAL_OP vec_base &operator&=(T b) - { - VECTOR_SELF_OP((*this)[i] &= b); - } - - INTEGRAL_OP vec_base &operator&=(const vec_base &b) - { - VECTOR_SELF_OP((*this)[i] &= b[i]); - } - - INTEGRAL_OP friend vec_base operator|(const vec_base &a, const vec_base &b) - { - VECTOR_OP(result[i] = a[i] | b[i]); - } - - INTEGRAL_OP friend vec_base operator|(const vec_base &a, T b) - { - VECTOR_OP(result[i] = a[i] | b); - } - - INTEGRAL_OP friend vec_base operator|(T a, const vec_base &b) - { - return b | a; - } - - INTEGRAL_OP vec_base &operator|=(T b) - { - VECTOR_SELF_OP((*this)[i] |= b); - } - - INTEGRAL_OP vec_base &operator|=(const vec_base &b) - { - VECTOR_SELF_OP((*this)[i] |= b[i]); - } - - INTEGRAL_OP friend vec_base operator^(const vec_base &a, const vec_base &b) - { - VECTOR_OP(result[i] = a[i] ^ b[i]); - } - - INTEGRAL_OP friend vec_base operator^(const vec_base &a, T b) - { - VECTOR_OP(result[i] = a[i] ^ b); - } - - INTEGRAL_OP friend vec_base operator^(T a, const vec_base &b) - { - return b ^ a; - } - - INTEGRAL_OP vec_base &operator^=(T b) - { - VECTOR_SELF_OP((*this)[i] ^= b); - } - - INTEGRAL_OP vec_base &operator^=(const vec_base &b) - { - VECTOR_SELF_OP((*this)[i] ^= b[i]); - } - - INTEGRAL_OP friend vec_base operator~(const vec_base &a) - { - VECTOR_OP(result[i] = ~a[i]); - } - - /** Modulo operators. */ - - INTEGRAL_OP friend vec_base operator%(const vec_base &a, const vec_base &b) - { - VECTOR_OP(result[i] = a[i] % b[i]); - } - - INTEGRAL_OP friend vec_base operator%(const vec_base &a, T b) - { - VECTOR_OP(result[i] = a[i] % b); - } - - INTEGRAL_OP friend vec_base operator%(T a, const vec_base &b) - { - VECTOR_OP(result[i] = a % b[i]); - } - -#undef VECTOR_OP -#undef VECTOR_SELF_OP - - /** Compare. */ - - friend bool operator==(const vec_base &a, const vec_base &b) - { - bool result = true; - for (int i = 0; i < Size; i++) { - result = result && (a[i] == b[i]); - } - return result; - } - - friend bool operator!=(const vec_base &a, const vec_base &b) - { - return !(a == b); - } - - bool is_zero() const - { - bool result = true; - for (int i = 0; i < Size; i++) { - result = result && ((*this)[i] == T(0)); - } - return result; - } - - bool is_any_zero() const - { - bool result = false; - for (int i = 0; i < Size && result; i++) { - result = result || ((*this)[i] == T(0)); - } - return result; - } - - /** Misc. */ - - uint64_t hash() const - { - return math::vector_hash(*this); - } - - friend std::ostream &operator<<(std::ostream &stream, const vec_base &v) - { - stream << "("; - for (int i = 0; i < Size; i++) { - stream << v[i]; - if (i != Size - 1) { - stream << ", "; - } - } - stream << ")"; - return stream; - } -}; - -#undef INTEGRAL_OP - -} // namespace blender diff --git a/source/blender/blenlib/BLI_mpq3.hh b/source/blender/blenlib/BLI_mpq3.hh index 33e1a1ea88f..985222cb706 100644 --- a/source/blender/blenlib/BLI_mpq3.hh +++ b/source/blender/blenlib/BLI_mpq3.hh @@ -26,7 +26,7 @@ # include "BLI_math.h" # include "BLI_math_mpq.hh" -# include "BLI_math_vector.hh" +# include "BLI_math_vec_types.hh" # include "BLI_span.hh" namespace blender { diff --git a/source/blender/blenlib/CMakeLists.txt b/source/blender/blenlib/CMakeLists.txt index 49585479941..6fb07f7466f 100644 --- a/source/blender/blenlib/CMakeLists.txt +++ b/source/blender/blenlib/CMakeLists.txt @@ -261,6 +261,7 @@ set(SRC BLI_math_statistics.h BLI_math_time.h BLI_math_vector.h + BLI_math_vec_types.hh BLI_memarena.h BLI_memblock.h BLI_memiter.h |