[Bf-blender-cvs] [399168f3c13] master: BLI: Implement templated math functions for basic types

Hans Goudey noreply at git.blender.org
Wed Feb 16 17:30:14 CET 2022


Commit: 399168f3c13fadb41c9fbec8a1b5c56cb6609343
Author: Hans Goudey
Date:   Wed Feb 16 10:28:18 2022 -0600
Branches: master
https://developer.blender.org/rB399168f3c13fadb41c9fbec8a1b5c56cb6609343

BLI: Implement templated math functions for basic types

This is meant to complement the `blender::math` functions recently
added by D13791. It's sometimes desired to template an operation to work
on vector types, but also basic types like `float` and `int`. This patch
adds that ability with a new `BLI_math_base.hh` header.

The existing vector math header is changed to use the `vec_base` type
more explicitly, to allow the compiler's generic function overload resolution
to determine which implementation of each math function to use.
This is a relatively large change, but it also makes the file significantly
easier to understand by reducing the use of macros.

Differential Revision: https://developer.blender.org/D14113

===================================================================

A	source/blender/blenlib/BLI_math_base.hh
M	source/blender/blenlib/BLI_math_vec_types.hh
M	source/blender/blenlib/BLI_math_vector.hh
M	source/blender/blenlib/CMakeLists.txt
M	source/blender/blenlib/intern/delaunay_2d.cc
M	source/blender/blenlib/tests/BLI_math_base_test.cc

===================================================================

diff --git a/source/blender/blenlib/BLI_math_base.hh b/source/blender/blenlib/BLI_math_base.hh
new file mode 100644
index 00000000000..6a988eda8a9
--- /dev/null
+++ b/source/blender/blenlib/BLI_math_base.hh
@@ -0,0 +1,104 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later
+ * Copyright 2022 Blender Foundation. */
+
+#pragma once
+
+/** \file
+ * \ingroup bli
+ */
+
+#include <algorithm>
+#include <cmath>
+#include <type_traits>
+
+#include "BLI_math_base_safe.h"
+#include "BLI_math_vec_types.hh"
+#include "BLI_utildefines.h"
+
+#ifdef WITH_GMP
+#  include "BLI_math_mpq.hh"
+#endif
+
+namespace blender::math {
+
+template<typename T> inline bool is_zero(const T &a)
+{
+  return a == T(0);
+}
+
+template<typename T> inline bool is_any_zero(const T &a)
+{
+  return is_zero(a);
+}
+
+template<typename T> inline T abs(const T &a)
+{
+  return std::abs(a);
+}
+
+template<typename T> inline T min(const T &a, const T &b)
+{
+  return std::min(a, b);
+}
+
+template<typename T> inline T max(const T &a, const T &b)
+{
+  return std::max(a, b);
+}
+
+template<typename T> inline T clamp(const T &a, const T &min, const T &max)
+{
+  return std::clamp(a, min, max);
+}
+
+template<typename T, BLI_ENABLE_IF((is_math_float_type<T>))> inline T mod(const T &a, const T &b)
+{
+  return std::fmod(a, b);
+}
+
+template<typename T, BLI_ENABLE_IF((is_math_float_type<T>))>
+inline T safe_mod(const T &a, const T &b)
+{
+  return (b != 0) ? std::fmod(a, b) : 0;
+}
+
+template<typename T> inline void min_max(const T &value, T &min, T &max)
+{
+  min = math::min(value, min);
+  max = math::max(value, max);
+}
+
+template<typename T, BLI_ENABLE_IF((is_math_float_type<T>))>
+inline T safe_divide(const T &a, const T &b)
+{
+  return (b != 0) ? a / b : T(0.0f);
+}
+
+template<typename T, BLI_ENABLE_IF((is_math_float_type<T>))> inline T floor(const T &a)
+{
+  return std::floor(a);
+}
+
+template<typename T, BLI_ENABLE_IF((is_math_float_type<T>))> inline T ceil(const T &a)
+{
+  return std::ceil(a);
+}
+
+template<typename T, BLI_ENABLE_IF((is_math_float_type<T>))> inline T fract(const T &a)
+{
+  return a - std::floor(a);
+}
+
+template<typename T, BLI_ENABLE_IF((is_math_float_type<T>))>
+inline T interpolate(const T &a, const T &b, const T &t)
+{
+  return a * (1 - t) + b * t;
+}
+
+template<typename T, BLI_ENABLE_IF((is_math_float_type<T>))>
+inline T midpoint(const T &a, const T &b)
+{
+  return (a + b) * T(0.5);
+}
+
+}  // namespace blender::math
diff --git a/source/blender/blenlib/BLI_math_vec_types.hh b/source/blender/blenlib/BLI_math_vec_types.hh
index 8d6f04ab15f..b6b3d15aefe 100644
--- a/source/blender/blenlib/BLI_math_vec_types.hh
+++ b/source/blender/blenlib/BLI_math_vec_types.hh
@@ -14,6 +14,10 @@
 
 #include "BLI_utildefines.h"
 
+#ifdef WITH_GMP
+#  include "BLI_math_mpq.hh"
+#endif
+
 namespace blender {
 
 /* clang-format off */
@@ -60,10 +64,10 @@ template<typename T> uint64_t vector_hash(const T &vec)
   return result;
 }
 
-template<typename T> inline bool is_any_zero(const T &a)
+template<typename T, int Size> inline bool is_any_zero(const vec_struct_base<T, Size> &a)
 {
-  for (int i = 0; i < T::type_length; i++) {
-    if (a[i] == typename T::base_type(0)) {
+  for (int i = 0; i < Size; i++) {
+    if (a[i] == T(0)) {
       return true;
     }
   }
@@ -579,4 +583,13 @@ using double2 = vec_base<double, 2>;
 using double3 = vec_base<double, 3>;
 using double4 = vec_base<double, 4>;
 
+template<typename T>
+inline constexpr bool is_math_float_type = (std::is_floating_point_v<T>
+#ifdef WITH_GMP
+                                            || std::is_same_v<T, mpq_class>
+#endif
+);
+
+template<typename T> inline constexpr bool is_math_integral_type = std::is_integral_v<T>;
+
 }  // namespace blender
diff --git a/source/blender/blenlib/BLI_math_vector.hh b/source/blender/blenlib/BLI_math_vector.hh
index d2ef2a1c5c8..3bb89bb26b2 100644
--- a/source/blender/blenlib/BLI_math_vector.hh
+++ b/source/blender/blenlib/BLI_math_vector.hh
@@ -15,10 +15,6 @@
 #include "BLI_span.hh"
 #include "BLI_utildefines.h"
 
-#ifdef WITH_GMP
-#  include "BLI_math_mpq.hh"
-#endif
-
 namespace blender::math {
 
 #ifndef NDEBUG
@@ -33,277 +29,293 @@ namespace blender::math {
 #  define BLI_ASSERT_UNIT(v) (void)(v)
 #endif
 
-#define bT typename T::base_type
-
-#ifdef WITH_GMP
-#  define BLI_ENABLE_IF_FLT_VEC(T) \
-    BLI_ENABLE_IF((std::is_floating_point_v<typename T::base_type> || \
-                   std::is_same_v<typename T::base_type, mpq_class>))
-#else
-#  define BLI_ENABLE_IF_FLT_VEC(T) BLI_ENABLE_IF((std::is_floating_point_v<typename T::base_type>))
-#endif
-
-#define BLI_ENABLE_IF_INT_VEC(T) BLI_ENABLE_IF((std::is_integral_v<typename T::base_type>))
-
-template<typename T> inline bool is_zero(const T &a)
+template<typename T, int Size> inline bool is_zero(const vec_base<T, Size> &a)
 {
-  for (int i = 0; i < T::type_length; i++) {
-    if (a[i] != bT(0)) {
+  for (int i = 0; i < Size; i++) {
+    if (a[i] != T(0)) {
       return false;
     }
   }
   return true;
 }
 
-template<typename T> inline T abs(const T &a)
+template<typename T, int Size> inline vec_base<T, Size> abs(const vec_base<T, Size> &a)
 {
-  T result;
-  for (int i = 0; i < T::type_length; i++) {
+  vec_base<T, Size> result;
+  for (int i = 0; i < Size; i++) {
     result[i] = a[i] >= 0 ? a[i] : -a[i];
   }
   return result;
 }
 
-template<typename T> inline T min(const T &a, const T &b)
+template<typename T, int Size>
+inline vec_base<T, Size> min(const vec_base<T, Size> &a, const vec_base<T, Size> &b)
 {
-  T result;
-  for (int i = 0; i < T::type_length; i++) {
+  vec_base<T, Size> result;
+  for (int i = 0; i < Size; i++) {
     result[i] = a[i] < b[i] ? a[i] : b[i];
   }
   return result;
 }
 
-template<typename T> inline T max(const T &a, const T &b)
+template<typename T, int Size>
+inline vec_base<T, Size> max(const vec_base<T, Size> &a, const vec_base<T, Size> &b)
 {
-  T result;
-  for (int i = 0; i < T::type_length; i++) {
+  vec_base<T, Size> result;
+  for (int i = 0; i < Size; i++) {
     result[i] = a[i] > b[i] ? a[i] : b[i];
   }
   return result;
 }
 
-template<typename T> inline T clamp(const T &a, const T &min_v, const T &max_v)
+template<typename T, int Size>
+inline T clamp(const vec_base<T, Size> &a,
+               const vec_base<T, Size> &min,
+               const vec_base<T, Size> &max)
 {
-  T result = a;
-  for (int i = 0; i < T::type_length; i++) {
-    CLAMP(result[i], min_v[i], max_v[i]);
+  vec_base<T, Size> result = a;
+  for (int i = 0; i < Size; i++) {
+    std::clamp(result[i], min[i], max[i]);
   }
   return result;
 }
 
-template<typename T> inline T clamp(const T &a, const bT &min_v, const bT &max_v)
+template<typename T, int Size>
+inline vec_base<T, Size> clamp(const vec_base<T, Size> &a, const T &min, const T &max)
 {
-  T result = a;
-  for (int i = 0; i < T::type_length; i++) {
-    CLAMP(result[i], min_v, max_v);
+  vec_base<T, Size> result = a;
+  for (int i = 0; i < Size; i++) {
+    std::clamp(result[i], min, max);
   }
   return result;
 }
 
-template<typename T, BLI_ENABLE_IF_FLT_VEC(T)> inline T mod(const T &a, const T &b)
+template<typename T, int Size, BLI_ENABLE_IF((is_math_float_type<T>))>
+inline vec_base<T, Size> mod(const vec_base<T, Size> &a, const vec_base<T, Size> &b)
 {
-  T result;
-  for (int i = 0; i < T::type_length; i++) {
+  vec_base<T, Size> result;
+  for (int i = 0; i < Size; i++) {
     BLI_assert(b[i] != 0);
     result[i] = std::fmod(a[i], b[i]);
   }
   return result;
 }
 
-template<typename T, BLI_ENABLE_IF_FLT_VEC(T)> inline T mod(const T &a, bT b)
+template<typename T, int Size, BLI_ENABLE_IF((is_math_float_type<T>))>
+inline vec_base<T, Size> mod(const vec_base<T, Size> &a, const T &b)
 {
   BLI_assert(b != 0);
-  T result;
-  for (int i = 0; i < T::type_length; i++) {
+  vec_base<T, Size> result;
+  for (int i = 0; i < Size; i++) {
     result[i] = std::fmod(a[i], b);
   }
   return result;
 }
 
-template<typename T, BLI_ENABLE_IF_FLT_VEC(T)> inline T safe_mod(const T &a, const T &b)
+template<typename T, int Size, BLI_ENABLE_IF((is_math_float_type<T>))>
+inline T safe_mod(const vec_base<T, Size> &a, const vec_base<T, Size> &b)
 {
-  T result;
-  for (int i = 0; i < T::type_length; i++) {
+  vec_base<T, Size> result;
+  for (int i = 0; i < Size; i++) {
     result[i] = (b[i] != 0) ? std::fmod(a[i], b[i]) : 0;
   }
   return result;
 }
 
-template<typename T, BLI_ENABLE_IF_FLT_VEC(T)> inline T safe_mod(const T &a, bT b)
+template<typename T, int Size, BLI_ENABLE_IF((is_math_float_type<T>))>
+inline T safe_mod(const vec_base<T, Size> &a, const T &b)
 {
   if (b == 0) {
-    return T(0.0f);
+    return vec_base<T, Size>(0);
   }
-  T result;
-  for (int i = 0; i < T::type_length; i++) {
+  vec_base<T, Size> result;
+  for (int i = 0; i < Size; i++) {
     result[i] = std::fmod(a[i], b);
   }
   return result;
 }
 
-template<typename T> inline void min_max(const T &vector, T &min_vec, T &max_vec)
+template<typename T, int Size>
+inline void min_max(const vec_base<T, Size> &vector,
+                    vec_base<T, Size> &min,
+                    vec_base<T, Size> &max)
 {
-  min_vec = min(vector, min_vec);
-  max_vec = max(vector, max_vec);
+  min = math::min(vector, min);
+  max = math::max(vector, max);
 }
 
-template<typename T, BLI_ENABLE_IF_FLT_VEC(T)> inline T safe_divide(const T &a, const T &b)
+template<typename T, int Size, BLI_ENABLE_IF((is_math_float_type<T>))>
+inline vec_base<T, Size> safe_divide(const vec_base<T, Size> &a, const vec_base<T, Size> &b)
 {
-  T result;
-  for (int i = 0; i < T::type_length; i++) {
+  vec_base<T, Size> result;
+  for (int i = 0; i < Size; i++) {
     result[i] = (b[i] == 0) ? 0 : a[i] / b[i];
   }
   return result;
 }
 
-template<typename T, BLI_ENABLE_IF_FLT_VEC(T)> inline T safe_divide(const T &a, const bT b)
+template<typename T, int Size, BLI_ENABLE_IF((is_math_float_type<T>))>
+inline vec_base<T, Size> safe_divide(const vec_base<T, Size> &a, const T &b)
 {
-  return (b != 0) ? a / b : T(0.0f);
+  return (b != 0) ? a / b : vec_base<T, Size>(0.0f);
 }
 
-template<typename T, BLI_ENABLE_IF_FLT_VEC(T)> inline T floor(const T &a)
+template<typename T, int Size, BLI_ENABLE_IF((is_math_float_

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list