diff --git a/src/math.hpp b/src/math.hpp index bf964ba38c07487914ffcf5768b7f39aee63a5d1..36767bcbc20c57a581210c8a3b5ea831aafbde0b 100644 --- a/src/math.hpp +++ b/src/math.hpp @@ -11,7 +11,7 @@ namespace math { template <typename T> T constexpr pi() { - return T(3.1415926535897932384626433832795); + return T(3.1415926535897932384626433832795l); } template <typename T = float> diff --git a/tests/unit/test_math.cpp b/tests/unit/test_math.cpp index b32bd194cb75b9df1c31c34c0323fdc0b95bce9e..5dff6c81e950d901012ffe4dcce995c02a3b5cd3 100644 --- a/tests/unit/test_math.cpp +++ b/tests/unit/test_math.cpp @@ -6,6 +6,78 @@ using namespace nest::mc::math; +TEST(math, pi) { + // check regression against long double literal in implementation + auto pi_ld = pi<long double>(); + auto pi_d = pi<double>(); + + if (std::numeric_limits<long double>::digits>std::numeric_limits<double>::digits) { + EXPECT_NE(0.0, pi_ld-pi_d); + } + else { + EXPECT_EQ(0.0, pi_ld-pi_d); + } + + // library quality of implementation dependent, but expect cos(pi) to be within + // 1 epsilon of -1. + + auto eps_d = std::numeric_limits<double>::epsilon(); + auto cos_pi_d = std::cos(pi_d); + EXPECT_LE(-1.0-eps_d, cos_pi_d); + EXPECT_GE(-1.0+eps_d, cos_pi_d); + + auto eps_ld = std::numeric_limits<long double>::epsilon(); + auto cos_pi_ld = std::cos(pi_ld); + EXPECT_LE(-1.0-eps_ld, cos_pi_ld); + EXPECT_GE(-1.0+eps_ld, cos_pi_ld); +} + +TEST(math, lerp) { + // expect exact computation when u is zero or one + double a = 1.0/3; + double b = 11.0/7; + + EXPECT_EQ(a, lerp(a, b, 0.)); + EXPECT_EQ(b, lerp(a, b, 1.)); + + // expect exact computation here as well + EXPECT_EQ(2.75, lerp(2.0, 3.0, 0.75)); + + // and otherwise to be close + EXPECT_DOUBLE_EQ(100.101, lerp(100.1, 200.1, 0.00001)); + EXPECT_DOUBLE_EQ(200.099, lerp(100.1, 200.1, 0.99999)); + + // should be able to lerp with differing types for end points and u + EXPECT_EQ(0.25f, lerp(0.f, 1.f, 0.25)); +} + +TEST(math, frustrum) { + // cross check against cone calculation + auto cone_area = [](double l, double r) { + return std::hypot(l,r)*r*pi<double>(); + }; + + auto cone_volume = [](double l, double r) { + return pi<double>()*square(r)*l/3.0; + }; + + EXPECT_DOUBLE_EQ(cone_area(5.0, 1.3), area_frustrum(5.0, 0.0, 1.3)); + EXPECT_DOUBLE_EQ(cone_volume(5.0, 1.3), volume_frustrum(5.0, 0.0, 1.3)); + + double r1 = 7.0; + double r2 = 9.0; + double l = 11.0; + + double s = l*r2/(r2-r1); + double ca = cone_area(s, r2)-cone_area(s-l, r1); + double cv = cone_volume(s, r2)-cone_volume(s-l, r1); + + EXPECT_DOUBLE_EQ(ca, area_frustrum(l, r1, r2)); + EXPECT_DOUBLE_EQ(ca, area_frustrum(l, r2, r1)); + EXPECT_DOUBLE_EQ(cv, volume_frustrum(l, r1, r2)); + EXPECT_DOUBLE_EQ(cv, volume_frustrum(l, r2, r1)); +} + TEST(math, infinity) { // check values for float, double, long double auto finf = infinity<float>();