Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'source/blender/blenlib/BLI_math_vec_types.hh')
-rw-r--r--source/blender/blenlib/BLI_math_vec_types.hh566
1 files changed, 566 insertions, 0 deletions
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..52aacd294e4
--- /dev/null
+++ b/source/blender/blenlib/BLI_math_vec_types.hh
@@ -0,0 +1,566 @@
+/*
+ * 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,
+ std::conditional_t<sizeof(T) == sizeof(uint64_t), uint64_t, void>>>>;
+/* 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;
+
+ using base_type = T;
+ using uint_type = vec_base<as_uint_type<T>, Size>;
+
+ 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 BLI_ENABLE_IF((Size == 2)) not working. */
+#define BLI_ENABLE_IF_VEC(_size, _test) int S = _size, BLI_ENABLE_IF((S _test))
+
+ template<BLI_ENABLE_IF_VEC(Size, == 2)> vec_base(T _x, T _y)
+ {
+ (*this)[0] = _x;
+ (*this)[1] = _y;
+ }
+
+ template<BLI_ENABLE_IF_VEC(Size, == 3)> vec_base(T _x, T _y, T _z)
+ {
+ (*this)[0] = _x;
+ (*this)[1] = _y;
+ (*this)[2] = _z;
+ }
+
+ template<BLI_ENABLE_IF_VEC(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_ENABLE_IF_VEC(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_ENABLE_IF_VEC(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_ENABLE_IF_VEC(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_ENABLE_IF_VEC(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, typename V, BLI_ENABLE_IF_VEC(Size, == 4)>
+ vec_base(vec_base<U, 2> xy, vec_base<V, 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_ENABLE_IF_VEC(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_ENABLE_IF_VEC(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_ENABLE_IF_VEC(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<typename U, int OtherSize, BLI_ENABLE_IF(OtherSize > Size)>
+ explicit vec_base(const vec_base<U, OtherSize> &other)
+ {
+ for (int i = 0; i < Size; i++) {
+ (*this)[i] = static_cast<T>(other[i]);
+ }
+ }
+
+#undef BLI_ENABLE_IF_VEC
+
+ /** 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 BLI_INT_OP(_T) template<typename U = _T, BLI_ENABLE_IF((std::is_integral_v<U>))>
+
+#define BLI_VEC_OP_IMPL(_result, _i, _op) \
+ vec_base _result; \
+ for (int _i = 0; _i < Size; _i++) { \
+ _op; \
+ } \
+ return _result;
+
+#define BLI_VEC_OP_IMPL_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_IMPL(ret, i, ret[i] = a[i] + b[i]);
+ }
+
+ friend vec_base operator+(const vec_base &a, const T &b)
+ {
+ BLI_VEC_OP_IMPL(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_IMPL_SELF(i, (*this)[i] += b[i]);
+ }
+
+ vec_base &operator+=(const T &b)
+ {
+ BLI_VEC_OP_IMPL_SELF(i, (*this)[i] += b);
+ }
+
+ friend vec_base operator-(const vec_base &a)
+ {
+ BLI_VEC_OP_IMPL(ret, i, ret[i] = -a[i]);
+ }
+
+ friend vec_base operator-(const vec_base &a, const vec_base &b)
+ {
+ BLI_VEC_OP_IMPL(ret, i, ret[i] = a[i] - b[i]);
+ }
+
+ friend vec_base operator-(const vec_base &a, const T &b)
+ {
+ BLI_VEC_OP_IMPL(ret, i, ret[i] = a[i] - b);
+ }
+
+ friend vec_base operator-(const T &a, const vec_base &b)
+ {
+ BLI_VEC_OP_IMPL(ret, i, ret[i] = a - b[i]);
+ }
+
+ vec_base &operator-=(const vec_base &b)
+ {
+ BLI_VEC_OP_IMPL_SELF(i, (*this)[i] -= b[i]);
+ }
+
+ vec_base &operator-=(const T &b)
+ {
+ BLI_VEC_OP_IMPL_SELF(i, (*this)[i] -= b);
+ }
+
+ friend vec_base operator*(const vec_base &a, const vec_base &b)
+ {
+ BLI_VEC_OP_IMPL(ret, i, ret[i] = a[i] * b[i]);
+ }
+
+ friend vec_base operator*(const vec_base &a, T b)
+ {
+ BLI_VEC_OP_IMPL(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_IMPL_SELF(i, (*this)[i] *= b);
+ }
+
+ vec_base &operator*=(const vec_base &b)
+ {
+ BLI_VEC_OP_IMPL_SELF(i, (*this)[i] *= b[i]);
+ }
+
+ friend vec_base operator/(const vec_base &a, const vec_base &b)
+ {
+ BLI_assert(!math::is_any_zero(b));
+ BLI_VEC_OP_IMPL(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_IMPL(ret, i, ret[i] = a[i] / b);
+ }
+
+ friend vec_base operator/(T a, const vec_base &b)
+ {
+ BLI_assert(!math::is_any_zero(b));
+ BLI_VEC_OP_IMPL(ret, i, ret[i] = a / b[i]);
+ }
+
+ vec_base &operator/=(T b)
+ {
+ BLI_assert(b != T(0));
+ BLI_VEC_OP_IMPL_SELF(i, (*this)[i] /= b);
+ }
+
+ vec_base &operator/=(const vec_base &b)
+ {
+ BLI_assert(!math::is_any_zero(b));
+ BLI_VEC_OP_IMPL_SELF(i, (*this)[i] /= b[i]);
+ }
+
+ /** Binary operators. */
+
+ BLI_INT_OP(T) friend vec_base operator&(const vec_base &a, const vec_base &b)
+ {
+ BLI_VEC_OP_IMPL(ret, i, ret[i] = a[i] & b[i]);
+ }
+
+ BLI_INT_OP(T) friend vec_base operator&(const vec_base &a, T b)
+ {
+ BLI_VEC_OP_IMPL(ret, i, ret[i] = a[i] & b);
+ }
+
+ BLI_INT_OP(T) friend vec_base operator&(T a, const vec_base &b)
+ {
+ return b & a;
+ }
+
+ BLI_INT_OP(T) vec_base &operator&=(T b)
+ {
+ BLI_VEC_OP_IMPL_SELF(i, (*this)[i] &= b);
+ }
+
+ BLI_INT_OP(T) vec_base &operator&=(const vec_base &b)
+ {
+ BLI_VEC_OP_IMPL_SELF(i, (*this)[i] &= b[i]);
+ }
+
+ BLI_INT_OP(T) friend vec_base operator|(const vec_base &a, const vec_base &b)
+ {
+ BLI_VEC_OP_IMPL(ret, i, ret[i] = a[i] | b[i]);
+ }
+
+ BLI_INT_OP(T) friend vec_base operator|(const vec_base &a, T b)
+ {
+ BLI_VEC_OP_IMPL(ret, i, ret[i] = a[i] | b);
+ }
+
+ BLI_INT_OP(T) friend vec_base operator|(T a, const vec_base &b)
+ {
+ return b | a;
+ }
+
+ BLI_INT_OP(T) vec_base &operator|=(T b)
+ {
+ BLI_VEC_OP_IMPL_SELF(i, (*this)[i] |= b);
+ }
+
+ BLI_INT_OP(T) vec_base &operator|=(const vec_base &b)
+ {
+ BLI_VEC_OP_IMPL_SELF(i, (*this)[i] |= b[i]);
+ }
+
+ BLI_INT_OP(T) friend vec_base operator^(const vec_base &a, const vec_base &b)
+ {
+ BLI_VEC_OP_IMPL(ret, i, ret[i] = a[i] ^ b[i]);
+ }
+
+ BLI_INT_OP(T) friend vec_base operator^(const vec_base &a, T b)
+ {
+ BLI_VEC_OP_IMPL(ret, i, ret[i] = a[i] ^ b);
+ }
+
+ BLI_INT_OP(T) friend vec_base operator^(T a, const vec_base &b)
+ {
+ return b ^ a;
+ }
+
+ BLI_INT_OP(T) vec_base &operator^=(T b)
+ {
+ BLI_VEC_OP_IMPL_SELF(i, (*this)[i] ^= b);
+ }
+
+ BLI_INT_OP(T) vec_base &operator^=(const vec_base &b)
+ {
+ BLI_VEC_OP_IMPL_SELF(i, (*this)[i] ^= b[i]);
+ }
+
+ BLI_INT_OP(T) friend vec_base operator~(const vec_base &a)
+ {
+ BLI_VEC_OP_IMPL(ret, i, ret[i] = ~a[i]);
+ }
+
+ /** Bit-shift operators. */
+
+ BLI_INT_OP(T) friend vec_base operator<<(const vec_base &a, const vec_base &b)
+ {
+ BLI_VEC_OP_IMPL(ret, i, ret[i] = a[i] << b[i]);
+ }
+
+ BLI_INT_OP(T) friend vec_base operator<<(const vec_base &a, T b)
+ {
+ BLI_VEC_OP_IMPL(ret, i, ret[i] = a[i] << b);
+ }
+
+ BLI_INT_OP(T) vec_base &operator<<=(T b)
+ {
+ BLI_VEC_OP_IMPL_SELF(i, (*this)[i] <<= b);
+ }
+
+ BLI_INT_OP(T) vec_base &operator<<=(const vec_base &b)
+ {
+ BLI_VEC_OP_IMPL_SELF(i, (*this)[i] <<= b[i]);
+ }
+
+ BLI_INT_OP(T) friend vec_base operator>>(const vec_base &a, const vec_base &b)
+ {
+ BLI_VEC_OP_IMPL(ret, i, ret[i] = a[i] >> b[i]);
+ }
+
+ BLI_INT_OP(T) friend vec_base operator>>(const vec_base &a, T b)
+ {
+ BLI_VEC_OP_IMPL(ret, i, ret[i] = a[i] >> b);
+ }
+
+ BLI_INT_OP(T) vec_base &operator>>=(T b)
+ {
+ BLI_VEC_OP_IMPL_SELF(i, (*this)[i] >>= b);
+ }
+
+ BLI_INT_OP(T) vec_base &operator>>=(const vec_base &b)
+ {
+ BLI_VEC_OP_IMPL_SELF(i, (*this)[i] >>= b[i]);
+ }
+
+ /** Modulo operators. */
+
+ BLI_INT_OP(T) friend vec_base operator%(const vec_base &a, const vec_base &b)
+ {
+ BLI_assert(!math::is_any_zero(b));
+ BLI_VEC_OP_IMPL(ret, i, ret[i] = a[i] % b[i]);
+ }
+
+ BLI_INT_OP(T) friend vec_base operator%(const vec_base &a, T b)
+ {
+ BLI_assert(b != 0);
+ BLI_VEC_OP_IMPL(ret, i, ret[i] = a[i] % b);
+ }
+
+ BLI_INT_OP(T) friend vec_base operator%(T a, const vec_base &b)
+ {
+ BLI_assert(!math::is_any_zero(b));
+ BLI_VEC_OP_IMPL(ret, i, ret[i] = a % b[i]);
+ }
+
+#undef BLI_INT_OP
+#undef BLI_VEC_OP_IMPL
+#undef BLI_VEC_OP_IMPL_SELF
+
+ /** Compare. */
+
+ friend bool operator==(const vec_base &a, const vec_base &b)
+ {
+ for (int i = 0; i < Size; i++) {
+ if (a[i] != b[i]) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ friend bool operator!=(const vec_base &a, const vec_base &b)
+ {
+ return !(a == b);
+ }
+
+ /** 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;
+ }
+};
+
+using int2 = vec_base<int32_t, 2>;
+using int3 = vec_base<int32_t, 3>;
+using int4 = vec_base<int32_t, 4>;
+
+using uint2 = vec_base<uint32_t, 2>;
+using uint3 = vec_base<uint32_t, 3>;
+using uint4 = vec_base<uint32_t, 4>;
+
+using float2 = vec_base<float, 2>;
+using float3 = vec_base<float, 3>;
+using float4 = vec_base<float, 4>;
+
+using double2 = vec_base<double, 2>;
+using double3 = vec_base<double, 3>;
+using double4 = vec_base<double, 4>;
+
+} // namespace blender