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.
This commit is contained in:
Clément Foucault 2022-06-07 20:07:56 +02:00
parent a857156578
commit 173a15bcda
Notes: blender-bot 2023-02-14 08:33:26 +01:00
Referenced by issue #99196, Regression: Rendering in the viewport is constantly restarted by some sculpting brushes and the position of mouse cursor
2 changed files with 33 additions and 0 deletions

View File

@ -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;

View File

@ -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