diff options
author | Clément Foucault <foucault.clem@gmail.com> | 2022-06-07 21:07:56 +0300 |
---|---|---|
committer | Clément Foucault <foucault.clem@gmail.com> | 2022-06-07 21:08:39 +0300 |
commit | 173a15bcda8f09f7028a1d9e3ae2d05e0b13ec06 (patch) | |
tree | 97c4292fcf398dd3d082b78167f147cf858c6d68 /source/blender/blenlib | |
parent | a857156578c99cbfc8abd658abfeac74d09affa3 (diff) |
BLI: Math: Add description and test to `ceil_to_multiple` and `divide_ceil`
I took the decision to assert on unexpected value as the behavior of these
functions are not consistent across the whole integer domain.
Diffstat (limited to 'source/blender/blenlib')
-rw-r--r-- | source/blender/blenlib/BLI_math_vector.hh | 13 | ||||
-rw-r--r-- | source/blender/blenlib/tests/BLI_math_vector_test.cc | 20 |
2 files changed, 33 insertions, 0 deletions
diff --git a/source/blender/blenlib/BLI_math_vector.hh b/source/blender/blenlib/BLI_math_vector.hh index e5273d050a6..384c4b49070 100644 --- a/source/blender/blenlib/BLI_math_vector.hh +++ b/source/blender/blenlib/BLI_math_vector.hh @@ -159,21 +159,34 @@ inline T safe_mod(const vec_base<T, Size> &a, const T &b) return result; } +/** + * Returns \a a if it is a multiple of \a b or the next multiple or \a b after \b a . + * In other words, it is equivalent to `divide_ceil(a, b) * b`. + * It is undefined if \a a is negative or \b b is not strictly positive. + */ template<typename T, int Size, BLI_ENABLE_IF((is_math_integral_type<T>))> inline vec_base<T, Size> ceil_to_multiple(const vec_base<T, Size> &a, const vec_base<T, Size> &b) { vec_base<T, Size> result; for (int i = 0; i < Size; i++) { + BLI_assert(a[i] >= 0); + BLI_assert(b[i] > 0); result[i] = ((a[i] + b[i] - 1) / b[i]) * b[i]; } return result; } +/** + * Integer division that returns the ceiling, instead of flooring like normal C division. + * It is undefined if \a a is negative or \b b is not strictly positive. + */ template<typename T, int Size, BLI_ENABLE_IF((is_math_integral_type<T>))> inline vec_base<T, Size> divide_ceil(const vec_base<T, Size> &a, const vec_base<T, Size> &b) { vec_base<T, Size> result; for (int i = 0; i < Size; i++) { + BLI_assert(a[i] >= 0); + BLI_assert(b[i] > 0); result[i] = (a[i] + b[i] - 1) / b[i]; } return result; diff --git a/source/blender/blenlib/tests/BLI_math_vector_test.cc b/source/blender/blenlib/tests/BLI_math_vector_test.cc index 282be5f1963..5686be975b5 100644 --- a/source/blender/blenlib/tests/BLI_math_vector_test.cc +++ b/source/blender/blenlib/tests/BLI_math_vector_test.cc @@ -105,4 +105,24 @@ TEST(math_vector, InterpolateFloat) EXPECT_FLOAT_EQ(result.z, 75.0f); } +TEST(math_vector, CeilToMultiple) +{ + const int3 a(21, 16, 0); + const int3 b(8, 16, 15); + const int3 result = math::ceil_to_multiple(a, b); + EXPECT_FLOAT_EQ(result.x, 24); + EXPECT_FLOAT_EQ(result.y, 16); + EXPECT_FLOAT_EQ(result.z, 0); +} + +TEST(math_vector, DivideCeil) +{ + const int3 a(21, 16, 0); + const int3 b(8, 16, 15); + const int3 result = math::divide_ceil(a, b); + EXPECT_FLOAT_EQ(result.x, 3); + EXPECT_FLOAT_EQ(result.y, 1); + EXPECT_FLOAT_EQ(result.z, 0); +} + } // namespace blender::tests |