BLI_math: add floor_power_of_10, ceil_power_of_10

Add utility functions to get the floor/ceiling of a float value
to the next power of 10.
This commit is contained in:
Campbell Barton 2020-11-13 16:58:14 +11:00
parent 40b2ce5ea7
commit ccf8df66fe
3 changed files with 57 additions and 0 deletions

View File

@ -219,6 +219,9 @@ MINLINE unsigned int round_db_to_uint_clamp(double a);
int pow_i(int base, int exp);
double double_round(double x, int ndigits);
float floor_power_of_10(float f);
float ceil_power_of_10(float f);
#ifdef BLI_MATH_GCC_WARN_PRAGMA
# pragma GCC diagnostic pop
#endif

View File

@ -79,3 +79,39 @@ double double_round(double x, int ndigits)
/* if computation resulted in overflow, raise OverflowError */
return z;
}
/**
* Floor to the nearest power of 10, e.g.:
* - 15.0 -> 10.0
* - 0.015 -> 0.01
* - 1.0 -> 1.0
*
* \param f: Value to floor, must be over 0.0.
* \note If we wanted to support signed values we could if this becomes necessary.
*/
float floor_power_of_10(float f)
{
BLI_assert(!(f < 0.0f));
if (f != 0.0f) {
return 1.0f / (powf(10.0f, ceilf(log10f(1.0f / f))));
}
return 0.0f;
}
/**
* Ceiling to the nearest power of 10, e.g.:
* - 15.0 -> 100.0
* - 0.015 -> 0.1
* - 1.0 -> 1.0
*
* \param f: Value to ceiling, must be over 0.0.
* \note If we wanted to support signed values we could if this becomes necessary.
*/
float ceil_power_of_10(float f)
{
BLI_assert(!(f < 0.0f));
if (f != 0.0f) {
return 1.0f / (powf(10.0f, floorf(log10f(1.0f / f))));
}
return 0.0f;
}

View File

@ -113,3 +113,21 @@ TEST(math_base, Log2CeilU)
EXPECT_EQ(log2_ceil_u(9), 4);
EXPECT_EQ(log2_ceil_u(123456), 17);
}
TEST(math_base, CeilPowerOf10)
{
EXPECT_EQ(ceil_power_of_10(0), 0);
EXPECT_EQ(ceil_power_of_10(1), 1);
EXPECT_EQ(ceil_power_of_10(1e-6f), 1e-6f);
EXPECT_NEAR(ceil_power_of_10(100.1f), 1000.0f, 1e-4f);
EXPECT_NEAR(ceil_power_of_10(99.9f), 100.0f, 1e-4f);
}
TEST(math_base, FloorPowerOf10)
{
EXPECT_EQ(floor_power_of_10(0), 0);
EXPECT_EQ(floor_power_of_10(1), 1);
EXPECT_EQ(floor_power_of_10(1e-6f), 1e-6f);
EXPECT_NEAR(floor_power_of_10(100.1f), 100.0f, 1e-4f);
EXPECT_NEAR(floor_power_of_10(99.9f), 10.0f, 1e-4f);
}