#include "fesa/analysis/thermal_time_grid.h" #include #include #include TEST(ThermalTimeGrid, SingleStepUsesPeriodAsActualIncrement) { const auto grid = fesa::ThermalTimeGrid::Create(2.0, 3.0, 1U); ASSERT_TRUE(grid.HasValue()); EXPECT_EQ(grid.Value().Count(), 1U); EXPECT_EQ(grid.Value().Delta(1U), 2.0); } TEST(ThermalTimeGrid, PreservesGenuineRemainderOutsideInputCells) { const auto grid = fesa::ThermalTimeGrid::Create(std::nextafter(.9, 1.0), .3, 4U); ASSERT_TRUE(grid.HasValue()); EXPECT_EQ(grid.Value().Count(), 4U); EXPECT_EQ(grid.Value().Delta(4U), 1.6653345369377348e-16); } TEST(ThermalTimeGrid, OriginalSubnormalCellsRespectOpenAndClosedContact) { const double tiny = std::numeric_limits::denorm_min(); const auto even = fesa::ThermalTimeGrid::Create(20 * tiny, 6 * tiny, 4U); const auto odd = fesa::ThermalTimeGrid::Create(17 * tiny, 5 * tiny, 4U); ASSERT_TRUE(even.HasValue()); ASSERT_TRUE(odd.HasValue()); EXPECT_EQ(even.Value().Count(), 3U); EXPECT_EQ(odd.Value().Count(), 4U); EXPECT_EQ(odd.Value().Delta(4U), 2 * tiny); } TEST(ThermalTimeGrid, DecimalCellsCounterexampleAndScale) { for (const int exponent : {-1000, 0, 1000}) { const double period = std::ldexp(.9, exponent); const double delta = std::ldexp(.3, exponent); const auto grid = fesa::ThermalTimeGrid::Create(period, delta, 3U); ASSERT_TRUE(grid.HasValue()); EXPECT_EQ(grid.Value().Count(), 3U); EXPECT_EQ(grid.Value().Delta(3U), delta); EXPECT_EQ(grid.Value().Time(3U), period); } const auto old_counterexample = fesa::ThermalTimeGrid::Create(5.351455173733616, .17262758624947144, 31U); ASSERT_TRUE(old_counterexample.HasValue()); EXPECT_EQ(old_counterexample.Value().Count(), 31U); EXPECT_EQ(old_counterexample.Value().Delta(31U), .17262758624947144); EXPECT_FALSE( fesa::ThermalTimeGrid::Create(5.351455173733616, .17262758624947144, 30U) .HasValue()); } TEST(ThermalTimeGrid, BinadeLimitsAndMaximumFinitePreserveOriginalCells) { const double max = std::numeric_limits::max(); const auto grid = fesa::ThermalTimeGrid::Create(max, max / 3, 3U); ASSERT_TRUE(grid.HasValue()); EXPECT_EQ(grid.Value().Count(), 3U); EXPECT_EQ(grid.Value().Delta(3U), max / 3); const auto upper = fesa::ThermalTimeGrid::Create(4294967295., 1., 4294967295U); ASSERT_TRUE(upper.HasValue()); EXPECT_EQ(upper.Value().Count(), 4294967295U); EXPECT_TRUE(upper.Value().Frame(4294967295U).HasValue()); EXPECT_FALSE( fesa::ThermalTimeGrid::Create(4294967296., 1., 4294967295U).HasValue()); EXPECT_FALSE(fesa::ThermalTimeGrid::Create( max, std::numeric_limits::denorm_min(), 4294967295U) .HasValue()); } TEST(ThermalTimeGrid, ShortenedIncrementAndCheckedFrames) { const auto grid = fesa::ThermalTimeGrid::Create(10., 3., 4U); ASSERT_TRUE(grid.HasValue()); EXPECT_EQ(grid.Value().Count(), 4U); EXPECT_EQ(grid.Value().Time(0U), 0.); for (std::uint32_t i = 1; i <= 4; ++i) { ASSERT_TRUE(grid.Value().Frame(i).HasValue()); EXPECT_EQ(grid.Value().Time(i), i == 4 ? 10. : 3. * i); EXPECT_EQ(grid.Value().Delta(i), i == 4 ? 1. : 3.); } EXPECT_FALSE(grid.Value().Frame(0U).HasValue()); EXPECT_FALSE(grid.Value().Frame(5U).HasValue()); const auto decimals = fesa::ThermalTimeGrid::Create(1., .1); ASSERT_TRUE(decimals.HasValue()); EXPECT_EQ(decimals.Value().Time(3U), .30000000000000004); EXPECT_EQ(decimals.Value().Delta(10U), .1); const double below = std::nextafter(.9, 0.); const auto close = fesa::ThermalTimeGrid::Create(below, .3, 3U); const auto short_last = fesa::ThermalTimeGrid::Create(std::nextafter(below, 0.), .3, 3U); ASSERT_TRUE(close.HasValue()); ASSERT_TRUE(short_last.HasValue()); EXPECT_EQ(close.Value().Delta(3U), .3); EXPECT_EQ(short_last.Value().Delta(3U), .2999999999999998); } TEST(ThermalTimeGrid, RejectsInvalidControlsBeforeIntegerConversion) { for (double bad : {0., -1., std::numeric_limits::infinity(), std::numeric_limits::quiet_NaN()}) { EXPECT_FALSE(fesa::ThermalTimeGrid::Create(bad, 1.).HasValue()); EXPECT_FALSE(fesa::ThermalTimeGrid::Create(1., bad).HasValue()); } EXPECT_FALSE(fesa::ThermalTimeGrid::Create(1., 1., 0U).HasValue()); const auto equal = fesa::ThermalTimeGrid::Create(2., 2., 1U); ASSERT_TRUE(equal.HasValue()); EXPECT_EQ(equal.Value().Delta(1U), 2.); }