Add RoundUpToMultiple and DivideAndRoundUp functions to MathUtils.h (#6989)
* Add RoundUpToMultiple and DivideAndRoundUp functions to MathUtils.h Signed-off-by: Tommy Walton <waltont@amazon.com> * Rename DivideByMultiple2 back to DivideByMultiple, now that I've confirmed it's not in use in the codebase. RHI::DivideByMultiple can be fully deprecated in favor of AZ::DivideAndRoundUp at a later date, once the deprecation strategy has been finalized. Signed-off-by: Tommy Walton <waltont@amazon.com> * Update based on PR feedback Signed-off-by: Tommy Walton <waltont@amazon.com> * Switched from std::numeric_limits to AZStd::numeric_limits and updated the header to indicate it works for non-power of two alignments, but that SizeAlignUp is more efficient if the alignment is a power of 2 Signed-off-by: Tommy Walton <waltont@amazon.com> * Added missing arguments to the assert, and a missing namespace and include that failed to compile on non-unity builds Signed-off-by: Tommy Walton <waltont@amazon.com>
This commit is contained in:
@@ -37,8 +37,8 @@ namespace UnitTest
|
||||
// min/max need to be substantially different to return a useful t value
|
||||
|
||||
// Float
|
||||
const float epsilonF = std::numeric_limits<float>::epsilon();
|
||||
const float doesntMatterF = std::numeric_limits<float>::signaling_NaN();
|
||||
const float epsilonF = AZStd::numeric_limits<float>::epsilon();
|
||||
const float doesntMatterF = AZStd::numeric_limits<float>::signaling_NaN();
|
||||
float lowerF = 2.3f, upperF = 2.3f;
|
||||
EXPECT_EQ(0.0f, AZ::LerpInverse(lowerF, upperF, doesntMatterF));
|
||||
EXPECT_EQ(0.0f, AZ::LerpInverse(0.0f, 0.5f * epsilonF, doesntMatterF));
|
||||
@@ -48,8 +48,8 @@ namespace UnitTest
|
||||
EXPECT_NEAR(1.0f, AZ::LerpInverse(1.0f, 1.0f + 5.0f * epsilonF, 1.0f + 5.0f * epsilonF), epsilonF);
|
||||
|
||||
// Double
|
||||
const double epsilonD = std::numeric_limits<double>::epsilon();
|
||||
const double doesntMatterD = std::numeric_limits<double>::signaling_NaN();
|
||||
const double epsilonD = AZStd::numeric_limits<double>::epsilon();
|
||||
const double doesntMatterD = AZStd::numeric_limits<double>::signaling_NaN();
|
||||
double lowerD = 2.3, upperD = 2.3;
|
||||
EXPECT_EQ(0.0, AZ::LerpInverse(lowerD, upperD, doesntMatterD));
|
||||
EXPECT_EQ(0.0, AZ::LerpInverse(0.0, 0.5 * epsilonD, doesntMatterD));
|
||||
@@ -58,4 +58,128 @@ namespace UnitTest
|
||||
EXPECT_NEAR(0.6, AZ::LerpInverse(1.0, 1.0 + 5.0 * epsilonD, 1.0 + 3.0 * epsilonD), epsilonD);
|
||||
EXPECT_NEAR(1.0, AZ::LerpInverse(1.0, 1.0 + 5.0 * epsilonD, 1.0 + 5.0 * epsilonD), epsilonD);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void TestRoundUpToMultipleIsCorrect()
|
||||
{
|
||||
// Example: alignment: 4
|
||||
// inputValue: 0 1 2 3 4 5 6 7 8 ...
|
||||
// expectedOutput: 0 4 4 4 4 8 8 8 8 ...
|
||||
EXPECT_EQ(RoundUpToMultiple(static_cast<T>(0) , static_cast<T>(1)) , 0);
|
||||
EXPECT_EQ(RoundUpToMultiple(static_cast<T>(1) , static_cast<T>(1)) , 1);
|
||||
EXPECT_EQ(RoundUpToMultiple(static_cast<T>(2) , static_cast<T>(1)) , 2);
|
||||
|
||||
EXPECT_EQ(RoundUpToMultiple(static_cast<T>(0) , static_cast<T>(2)) , 0);
|
||||
EXPECT_EQ(RoundUpToMultiple(static_cast<T>(1) , static_cast<T>(2)) , 2);
|
||||
EXPECT_EQ(RoundUpToMultiple(static_cast<T>(2) , static_cast<T>(2)) , 2);
|
||||
EXPECT_EQ(RoundUpToMultiple(static_cast<T>(3) , static_cast<T>(2)) , 4);
|
||||
EXPECT_EQ(RoundUpToMultiple(static_cast<T>(4) , static_cast<T>(2)) , 4);
|
||||
EXPECT_EQ(RoundUpToMultiple(static_cast<T>(5) , static_cast<T>(2)) , 6);
|
||||
|
||||
EXPECT_EQ(RoundUpToMultiple(static_cast<T>(0) , static_cast<T>(8)) , 0);
|
||||
EXPECT_EQ(RoundUpToMultiple(static_cast<T>(1) , static_cast<T>(8)) , 8);
|
||||
EXPECT_EQ(RoundUpToMultiple(static_cast<T>(7) , static_cast<T>(8)) , 8);
|
||||
EXPECT_EQ(RoundUpToMultiple(static_cast<T>(8) , static_cast<T>(8)) , 8);
|
||||
EXPECT_EQ(RoundUpToMultiple(static_cast<T>(9) , static_cast<T>(8)) , 16);
|
||||
EXPECT_EQ(RoundUpToMultiple(static_cast<T>(15), static_cast<T>(8)) , 16);
|
||||
EXPECT_EQ(RoundUpToMultiple(static_cast<T>(16), static_cast<T>(8)) , 16);
|
||||
EXPECT_EQ(RoundUpToMultiple(static_cast<T>(17), static_cast<T>(8)) , 24);
|
||||
|
||||
EXPECT_EQ(RoundUpToMultiple(static_cast<T>(0) , static_cast<T>(13)), 0);
|
||||
EXPECT_EQ(RoundUpToMultiple(static_cast<T>(1) , static_cast<T>(13)), 13);
|
||||
EXPECT_EQ(RoundUpToMultiple(static_cast<T>(9) , static_cast<T>(13)), 13);
|
||||
EXPECT_EQ(RoundUpToMultiple(static_cast<T>(12), static_cast<T>(13)), 13);
|
||||
EXPECT_EQ(RoundUpToMultiple(static_cast<T>(13), static_cast<T>(13)), 13);
|
||||
EXPECT_EQ(RoundUpToMultiple(static_cast<T>(14), static_cast<T>(13)), 26);
|
||||
EXPECT_EQ(RoundUpToMultiple(static_cast<T>(25), static_cast<T>(13)), 26);
|
||||
EXPECT_EQ(RoundUpToMultiple(static_cast<T>(26), static_cast<T>(13)), 26);
|
||||
EXPECT_EQ(RoundUpToMultiple(static_cast<T>(27), static_cast<T>(13)), 39);
|
||||
|
||||
EXPECT_EQ(RoundUpToMultiple(static_cast<T>(0), AZStd::numeric_limits<T>::max()), 0);
|
||||
|
||||
T aVeryLargeNumberThatStillWontOverflow = AZStd::numeric_limits<T>::max() - 4;
|
||||
EXPECT_EQ(RoundUpToMultiple(static_cast<T>(1), aVeryLargeNumberThatStillWontOverflow), aVeryLargeNumberThatStillWontOverflow);
|
||||
EXPECT_EQ(RoundUpToMultiple(aVeryLargeNumberThatStillWontOverflow, static_cast<T>(1)), aVeryLargeNumberThatStillWontOverflow);
|
||||
}
|
||||
|
||||
TEST(RoundUpToMultipleTest, RoundUpToMultipleUInt32_ValidInput_IsCorrect)
|
||||
{
|
||||
TestRoundUpToMultipleIsCorrect<uint32_t>();
|
||||
}
|
||||
|
||||
TEST(RoundUpToMultipleTest, RoundUpToMultipleUInt64_ValidInput_IsCorrect)
|
||||
{
|
||||
TestRoundUpToMultipleIsCorrect<uint64_t>();
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void TestDivideAndRoundUpIsCorrect()
|
||||
{
|
||||
//! Example: alignment: 3
|
||||
//! Value: 0 1 2 3 4 5 6 7 8
|
||||
//! Result: 0 1 1 1 2 2 2 3 3
|
||||
EXPECT_EQ(DivideAndRoundUp(static_cast<T>(0), static_cast<T>(3)), 0);
|
||||
EXPECT_EQ(DivideAndRoundUp(static_cast<T>(1), static_cast<T>(3)), 1);
|
||||
EXPECT_EQ(DivideAndRoundUp(static_cast<T>(2), static_cast<T>(3)), 1);
|
||||
EXPECT_EQ(DivideAndRoundUp(static_cast<T>(3), static_cast<T>(3)), 1);
|
||||
EXPECT_EQ(DivideAndRoundUp(static_cast<T>(4), static_cast<T>(3)), 2);
|
||||
EXPECT_EQ(DivideAndRoundUp(static_cast<T>(5), static_cast<T>(3)), 2);
|
||||
EXPECT_EQ(DivideAndRoundUp(static_cast<T>(6), static_cast<T>(3)), 2);
|
||||
EXPECT_EQ(DivideAndRoundUp(static_cast<T>(7), static_cast<T>(3)), 3);
|
||||
EXPECT_EQ(DivideAndRoundUp(static_cast<T>(8), static_cast<T>(3)), 3);
|
||||
|
||||
EXPECT_EQ(DivideAndRoundUp(static_cast<T>(0), AZStd::numeric_limits<T>::max()), 0);
|
||||
|
||||
T aVeryLargeNumberThatStillWontOverflow = AZStd::numeric_limits<T>::max() - 4;
|
||||
EXPECT_EQ(DivideAndRoundUp(static_cast<T>(1), aVeryLargeNumberThatStillWontOverflow), static_cast<T>(1));
|
||||
EXPECT_EQ(DivideAndRoundUp(aVeryLargeNumberThatStillWontOverflow, static_cast<T>(1)), aVeryLargeNumberThatStillWontOverflow);
|
||||
|
||||
}
|
||||
|
||||
TEST(DivideAndRoundUpTest, DivideAndRoundUpUInt32_ValidInput_IsCorrect)
|
||||
{
|
||||
TestDivideAndRoundUpIsCorrect<uint32_t>();
|
||||
}
|
||||
|
||||
TEST(DivideAndRoundUpTest, DivideAndRoundUpUInt64_ValidInput_IsCorrect)
|
||||
{
|
||||
TestDivideAndRoundUpIsCorrect<uint64_t>();
|
||||
}
|
||||
|
||||
|
||||
class RoundUpInvalidInputTestsFixture : public ScopedAllocatorSetupFixture
|
||||
{
|
||||
};
|
||||
|
||||
TEST_F(RoundUpInvalidInputTestsFixture, DividAndRoundUp_AlignmentZeroUint32_Assert)
|
||||
{
|
||||
AZ_TEST_START_TRACE_SUPPRESSION;
|
||||
DivideAndRoundUp(static_cast<uint32_t>(0), static_cast<uint32_t>(0));
|
||||
AZ_TEST_STOP_TRACE_SUPPRESSION(1);
|
||||
}
|
||||
|
||||
TEST_F(RoundUpInvalidInputTestsFixture, DividAndRoundUp_AlignmentZeroUint64_Assert)
|
||||
{
|
||||
AZ_TEST_START_TRACE_SUPPRESSION;
|
||||
DivideAndRoundUp(static_cast<uint64_t>(0), static_cast<uint64_t>(0));
|
||||
AZ_TEST_STOP_TRACE_SUPPRESSION(1);
|
||||
}
|
||||
|
||||
TEST_F(RoundUpInvalidInputTestsFixture, DividAndRoundUp_OverflowUint32_Assert)
|
||||
{
|
||||
AZ_TEST_START_TRACE_SUPPRESSION;
|
||||
DivideAndRoundUp(
|
||||
static_cast<uint32_t>((AZStd::numeric_limits<uint32_t>::max() / 2) + 1),
|
||||
static_cast<uint32_t>((AZStd::numeric_limits<uint32_t>::max() / 2) + 1));
|
||||
AZ_TEST_STOP_TRACE_SUPPRESSION(1);
|
||||
}
|
||||
|
||||
TEST_F(RoundUpInvalidInputTestsFixture, DividAndRoundUp_OverflowUint64_Assert)
|
||||
{
|
||||
AZ_TEST_START_TRACE_SUPPRESSION;
|
||||
DivideAndRoundUp(
|
||||
static_cast<uint64_t>((AZStd::numeric_limits<uint64_t>::max() / 2) + 1),
|
||||
static_cast<uint64_t>((AZStd::numeric_limits<uint64_t>::max() / 2) + 1));
|
||||
AZ_TEST_STOP_TRACE_SUPPRESSION(1);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user