#include #include #include #include #include namespace { TEST(ShapeFunction, InterpolatesBothEndpoints) { const auto first_endpoint = fesa::line2_shape(-1.0); const auto second_endpoint = fesa::line2_shape(1.0); EXPECT_DOUBLE_EQ(first_endpoint[0], 1.0); EXPECT_DOUBLE_EQ(first_endpoint[1], 0.0); EXPECT_DOUBLE_EQ(second_endpoint[0], 0.0); EXPECT_DOUBLE_EQ(second_endpoint[1], 1.0); } TEST(ShapeFunction, FormsPartitionOfUnityWithinRoundoff) { for (const double xi : std::array{-1.0, -0.25, 0.0, 0.4, 1.0}) { const auto shape = fesa::line2_shape(xi); // Four ulps at unit scale cover the two affine evaluations and sum. constexpr double tolerance = 4.0 * std::numeric_limits::epsilon(); EXPECT_NEAR(shape[0] + shape[1], 1.0, tolerance) << "xi=" << xi; } } TEST(ShapeFunction, DerivativesSumToZeroAtEveryNaturalCoordinate) { for (const double xi : std::array{-1.0, -0.25, 0.0, 0.4, 1.0}) { const auto derivative = fesa::line2_shape_derivative(xi); EXPECT_DOUBLE_EQ(derivative[0], -0.5); EXPECT_DOUBLE_EQ(derivative[1], 0.5); EXPECT_DOUBLE_EQ(derivative[0] + derivative[1], 0.0); } } TEST(Jacobian, ReturnsHalfThePhysicalLength) { EXPECT_DOUBLE_EQ(fesa::line2_jacobian(4.0), 2.0); EXPECT_DOUBLE_EQ(fesa::line2_jacobian(0.25), 0.125); } TEST(Jacobian, DoesNotAdjustSmallPositiveFiniteLengths) { constexpr double length = 1.0e-300; EXPECT_DOUBLE_EQ(fesa::line2_jacobian(length), length / 2.0); } TEST(Jacobian, RejectsNonpositiveAndNonfiniteLengths) { const double infinity = std::numeric_limits::infinity(); const double nan = std::numeric_limits::quiet_NaN(); for (const double length : std::array{0.0, -1.0, infinity, nan}) { EXPECT_THROW( static_cast(fesa::line2_jacobian(length)), std::invalid_argument); } } TEST(Jacobian, RejectsLengthWhoseHalfUnderflowsToZero) { EXPECT_THROW( static_cast(fesa::line2_jacobian( std::numeric_limits::denorm_min())), std::invalid_argument); } } // namespace