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>();