test: runtime unit tests refactored to have a bigger granularity (less top level tests)

This commit is contained in:
Mateusz Pusz
2024-11-12 11:27:52 +01:00
parent 123b4c0f14
commit 78204c7e5f
5 changed files with 1528 additions and 1495 deletions

File diff suppressed because it is too large Load Diff

View File

@ -38,19 +38,22 @@ import mp_units;
using namespace mp_units;
TEST_CASE("fixed_string::at", "[fixed_string]")
TEST_CASE("fixed_string operations", "[fixed_string]")
{
basic_fixed_string txt = "abc";
SECTION("in range")
SECTION("fixed_string::at")
{
CHECK(txt.at(0) == 'a');
CHECK(txt.at(1) == 'b');
CHECK(txt.at(2) == 'c');
}
SECTION("out of range")
{
REQUIRE_THROWS_MATCHES(txt.at(3), std::out_of_range, Catch::Matchers::Message("basic_fixed_string::at"));
REQUIRE_THROWS_MATCHES(txt.at(1024), std::out_of_range, Catch::Matchers::Message("basic_fixed_string::at"));
basic_fixed_string txt = "abc";
SECTION("in range")
{
CHECK(txt.at(0) == 'a');
CHECK(txt.at(1) == 'b');
CHECK(txt.at(2) == 'c');
}
SECTION("out of range")
{
REQUIRE_THROWS_MATCHES(txt.at(3), std::out_of_range, Catch::Matchers::Message("basic_fixed_string::at"));
REQUIRE_THROWS_MATCHES(txt.at(1024), std::out_of_range, Catch::Matchers::Message("basic_fixed_string::at"));
}
}
}

File diff suppressed because it is too large Load Diff

View File

@ -43,486 +43,488 @@ using namespace mp_units::si::unit_symbols;
// classical
TEST_CASE("'pow<N>()' on quantity changes the value and the dimension accordingly", "[math][pow]")
TEST_CASE("math operations", "[math]")
{
SECTION("'pow<0>(q)' returns '1'") { CHECK(pow<0>(2 * isq::length[m]) == 1 * one); }
SECTION("'pow<1>(q)' returns 'q'") { CHECK(pow<1>(2 * isq::length[m]) == 2 * isq::length[m]); }
SECTION("'pow<2>(q)' squares both the value and a dimension")
SECTION("'pow<N>()' on quantity changes the value and the dimension accordingly")
{
CHECK(pow<2>(2 * isq::length[m]) == 4 * isq::area[m2]);
SECTION("'pow<0>(q)' returns '1'") { CHECK(pow<0>(2 * isq::length[m]) == 1 * one); }
SECTION("'pow<1>(q)' returns 'q'") { CHECK(pow<1>(2 * isq::length[m]) == 2 * isq::length[m]); }
SECTION("'pow<2>(q)' squares both the value and a dimension")
{
CHECK(pow<2>(2 * isq::length[m]) == 4 * isq::area[m2]);
}
SECTION("'pow<3>(q)' cubes both the value and a dimension")
{
CHECK(pow<3>(2 * isq::length[m]) == 8 * isq::volume[m3]);
}
}
SECTION("'pow<3>(q)' cubes both the value and a dimension")
SECTION("'sqrt()' on quantity changes the value and the dimension accordingly")
{
CHECK(pow<3>(2 * isq::length[m]) == 8 * isq::volume[m3]);
}
}
TEST_CASE("'sqrt()' on quantity changes the value and the dimension accordingly", "[math][sqrt]")
{
REQUIRE(sqrt(4 * isq::area[m2]) == 2 * isq::length[m]);
}
TEST_CASE("'cbrt()' on quantity changes the value and the dimension accordingly", "[math][cbrt]")
{
REQUIRE(cbrt(8 * isq::volume[m3]) == 2 * isq::length[m]);
}
TEST_CASE("'fma()' on quantity changes the value and the dimension accordingly", "[math][fma]")
{
REQUIRE(fma(1.0 * isq::length[m], 2.0 * one, 2.0 * isq::length[m]) == 4.0 * isq::length[m]);
REQUIRE(fma(isq::speed(10.0 * m / s), isq::time(2.0 * s), isq::height(42.0 * m)) == isq::length(62.0 * m));
}
TEST_CASE("fmod functions", "[math][fmod]")
{
SECTION("fmod should work on the same quantities")
{
REQUIRE(fmod(4. * isq::length[km], 3. * isq::length[km]) == 1. * isq::length[km]);
REQUIRE(fmod(-9. * isq::length[km], 3. * isq::length[km]) == -0. * isq::length[km]);
REQUIRE(fmod(3 * isq::length[km], 2 * isq::length[km]) == 1 * isq::length[km]);
REQUIRE(fmod(4 * isq::length[km], 2.5f * isq::length[km]) == 1.5 * isq::length[km]);
}
SECTION("fmod should work with different units of the same dimension")
{
REQUIRE(fmod(4. * isq::length[km], 3000. * isq::length[m]) == 1000. * isq::length[m]);
REQUIRE(fmod(-9. * isq::length[km], 3000. * isq::length[m]) == -0. * isq::length[m]);
REQUIRE(fmod(3. * isq::length[km], 2000. * isq::length[m]) == 1000 * isq::length[m]);
REQUIRE(fmod(4 * isq::length[km], 2500 * isq::length[m]) == 1500 * isq::length[m]);
}
}
TEST_CASE("remainder functions", "[math][remainder]")
{
SECTION("remainder should work on the same quantities")
{
REQUIRE(remainder(4. * isq::length[km], 3. * isq::length[km]) == 1. * isq::length[km]);
REQUIRE(remainder(-9. * isq::length[km], 3. * isq::length[km]) == -0. * isq::length[km]);
REQUIRE(remainder(3 * isq::length[km], 2 * isq::length[km]) == -1 * isq::length[km]);
REQUIRE(remainder(4 * isq::length[km], 2.75f * isq::length[km]) == 1.25 * isq::length[km]);
}
SECTION("remainder should work with different units of the same dimension")
{
REQUIRE(remainder(4. * isq::length[km], 3000. * isq::length[m]) == 1000. * isq::length[m]);
REQUIRE(remainder(-9. * isq::length[km], 3000. * isq::length[m]) == -0. * isq::length[m]);
REQUIRE(remainder(3. * isq::length[km], 2000. * isq::length[m]) == -1000 * isq::length[m]);
REQUIRE(remainder(4 * isq::length[km], 2750 * isq::length[m]) == 1250 * isq::length[m]);
}
}
TEST_CASE("'isfinite()' accepts dimensioned arguments", "[math][isfinite]") { REQUIRE(isfinite(4.0 * isq::length[m])); }
TEST_CASE("'isinf()' accepts dimensioned arguments", "[math][isinf]") { REQUIRE(!isinf(4.0 * isq::length[m])); }
TEST_CASE("'isnan()' accepts dimensioned arguments", "[math][isnan]") { REQUIRE(!isnan(4.0 * isq::length[m])); }
TEST_CASE("'pow<Num, Den>()' on quantity changes the value and the dimension accordingly", "[math][pow]")
{
REQUIRE(pow<1, 4>(16 * isq::area[m2]) == sqrt(4 * isq::length[m]));
}
// TODO add tests for exp()
TEST_CASE("absolute functions on quantity returns the absolute value", "[math][abs][fabs]")
{
SECTION("'abs()' on a negative quantity returns the abs")
{
SECTION("integral representation") { REQUIRE(abs(-1 * isq::length[m]) == 1 * isq::length[m]); }
SECTION("floating-point representation") { REQUIRE(abs(-1. * isq::length[m]) == 1 * isq::length[m]); }
REQUIRE(sqrt(4 * isq::area[m2]) == 2 * isq::length[m]);
}
SECTION("'abs()' on a positive quantity returns the abs")
SECTION("'cbrt()' on quantity changes the value and the dimension accordingly")
{
SECTION("integral representation") { REQUIRE(abs(1 * isq::length[m]) == 1 * isq::length[m]); }
SECTION("floating-point representation") { REQUIRE(abs(1. * isq::length[m]) == 1 * isq::length[m]); }
}
}
TEST_CASE("numeric_limits functions", "[limits]")
{
SECTION("'epsilon' works as expected using default floating type")
{
REQUIRE(epsilon<double>(isq::length[m]).numerical_value_in(m) ==
std::numeric_limits<decltype(1. * isq::length[m])::rep>::epsilon());
}
SECTION("'epsilon' works as expected using integers")
{
REQUIRE(epsilon<int>(isq::length[m]).numerical_value_in(m) ==
std::numeric_limits<decltype(1 * isq::length[m])::rep>::epsilon());
}
}
TEST_CASE("floor functions", "[floor]")
{
SECTION("floor 1 second with target unit second should be 1 second")
{
REQUIRE(floor<si::second>(1 * isq::time[s]) == 1 * isq::time[s]);
}
SECTION("floor 1000 milliseconds with target unit second should be 1 second")
{
REQUIRE(floor<si::second>(1000 * isq::time[ms]) == 1 * isq::time[s]);
}
SECTION("floor 1001 milliseconds with target unit second should be 1 second")
{
REQUIRE(floor<si::second>(1001 * isq::time[ms]) == 1 * isq::time[s]);
}
SECTION("floor 1999 milliseconds with target unit second should be 1 second")
{
REQUIRE(floor<si::second>(1999 * isq::time[ms]) == 1 * isq::time[s]);
}
SECTION("floor -1000 milliseconds with target unit second should be -1 second")
{
REQUIRE(floor<si::second>(-1000 * isq::time[ms]) == -1 * isq::time[s]);
}
SECTION("floor -999 milliseconds with target unit second should be -1 second")
{
REQUIRE(floor<si::second>(-999 * isq::time[ms]) == -1 * isq::time[s]);
}
SECTION("floor 1.3 seconds with target unit second should be 1 second")
{
REQUIRE(floor<si::second>(1.3 * isq::time[s]) == 1 * isq::time[s]);
}
SECTION("floor -1.3 seconds with target unit second should be -2 seconds")
{
REQUIRE(floor<si::second>(-1.3 * isq::time[s]) == -2 * isq::time[s]);
}
SECTION("floor 1001. milliseconds with target unit second should be 1 second")
{
REQUIRE(floor<si::second>(1001. * isq::time[ms]) == 1 * isq::time[s]);
}
SECTION("floor 1999. milliseconds with target unit second should be 1 second")
{
REQUIRE(floor<si::second>(1999. * isq::time[ms]) == 1 * isq::time[s]);
}
SECTION("floor -1000. milliseconds with target unit second should be -1 second")
{
REQUIRE(floor<si::second>(-1000. * isq::time[ms]) == -1 * isq::time[s]);
}
SECTION("floor -999. milliseconds with target unit second should be -1 second")
{
REQUIRE(floor<si::second>(-999. * isq::time[ms]) == -1 * isq::time[s]);
REQUIRE(cbrt(8 * isq::volume[m3]) == 2 * isq::length[m]);
}
// TODO Add tests for `N`, `kN` and `kg * m / s2` i `kg * km / s2`
}
TEST_CASE("ceil functions", "[ceil]")
{
SECTION("ceil 1 second with target unit second should be 1 second")
SECTION("'fma()' on quantity changes the value and the dimension accordingly")
{
REQUIRE(ceil<si::second>(1 * isq::time[s]) == 1 * isq::time[s]);
}
SECTION("ceil 1000 milliseconds with target unit second should be 1 second")
{
REQUIRE(ceil<si::second>(1000 * isq::time[ms]) == 1 * isq::time[s]);
}
SECTION("ceil 1001 milliseconds with target unit second should be 2 seconds")
{
REQUIRE(ceil<si::second>(1001 * isq::time[ms]) == 2 * isq::time[s]);
}
SECTION("ceil 1999 milliseconds with target unit second should be 2 seconds")
{
REQUIRE(ceil<si::second>(1999 * isq::time[ms]) == 2 * isq::time[s]);
}
SECTION("ceil -1000 milliseconds with target unit second should be -1 second")
{
REQUIRE(ceil<si::second>(-1000 * isq::time[ms]) == -1 * isq::time[s]);
}
SECTION("ceil -999 milliseconds with target unit second should be 0 seconds")
{
REQUIRE(ceil<si::second>(-999 * isq::time[ms]) == 0 * isq::time[s]);
}
SECTION("ceil 1.3 seconds with target unit second should be 2 seconds")
{
REQUIRE(ceil<si::second>(1.3 * isq::time[s]) == 2 * isq::time[s]);
}
SECTION("ceil -1.3 seconds with target unit second should be -1 second")
{
REQUIRE(ceil<si::second>(-1.3 * isq::time[s]) == -1 * isq::time[s]);
}
SECTION("ceil 1001. milliseconds with target unit second should be 2 seconds")
{
REQUIRE(ceil<si::second>(1001. * isq::time[ms]) == 2 * isq::time[s]);
}
SECTION("ceil 1999. milliseconds with target unit second should be 2 seconds")
{
REQUIRE(ceil<si::second>(1999. * isq::time[ms]) == 2 * isq::time[s]);
}
SECTION("ceil -1000. milliseconds with target unit second should be -1 second")
{
REQUIRE(ceil<si::second>(-1000. * isq::time[ms]) == -1 * isq::time[s]);
}
SECTION("ceil -999. milliseconds with target unit second should be 0 seconds")
{
REQUIRE(ceil<si::second>(-999. * isq::time[ms]) == 0 * isq::time[s]);
}
}
TEST_CASE("round functions", "[round]")
{
SECTION("round 1 second with target unit second should be 1 second")
{
REQUIRE(round<si::second>(1 * isq::time[s]) == 1 * isq::time[s]);
}
SECTION("round 1000 milliseconds with target unit second should be 1 second")
{
REQUIRE(round<si::second>(1000 * isq::time[ms]) == 1 * isq::time[s]);
}
SECTION("round 1001 milliseconds with target unit second should be 1 second")
{
REQUIRE(round<si::second>(1001 * isq::time[ms]) == 1 * isq::time[s]);
}
SECTION("round 1499 milliseconds with target unit second should be 1 second")
{
REQUIRE(round<si::second>(1499 * isq::time[ms]) == 1 * isq::time[s]);
}
SECTION("round 1500 milliseconds with target unit second should be 2 seconds")
{
REQUIRE(round<si::second>(1500 * isq::time[ms]) == 2 * isq::time[s]);
}
SECTION("round 1999 milliseconds with target unit second should be 2 seconds")
{
REQUIRE(round<si::second>(1999 * isq::time[ms]) == 2 * isq::time[s]);
}
SECTION("round -1000 milliseconds with target unit second should be -1 second")
{
REQUIRE(round<si::second>(-1000 * isq::time[ms]) == -1 * isq::time[s]);
}
SECTION("round -1001 milliseconds with target unit second should be -1 second")
{
REQUIRE(round<si::second>(-1001 * isq::time[ms]) == -1 * isq::time[s]);
}
SECTION("round -1499 milliseconds with target unit second should be -1 second")
{
REQUIRE(round<si::second>(-1499 * isq::time[ms]) == -1 * isq::time[s]);
}
SECTION("round -1500 milliseconds with target unit second should be -2 seconds")
{
REQUIRE(round<si::second>(-1500 * isq::time[ms]) == -2 * isq::time[s]);
}
SECTION("round -1999 milliseconds with target unit second should be -2 seconds")
{
REQUIRE(round<si::second>(-1999 * isq::time[ms]) == -2 * isq::time[s]);
}
SECTION("round 1000. milliseconds with target unit second should be 1 second")
{
REQUIRE(round<si::second>(1000. * isq::time[ms]) == 1 * isq::time[s]);
}
SECTION("round 1001. milliseconds with target unit second should be 1 second")
{
REQUIRE(round<si::second>(1001. * isq::time[ms]) == 1 * isq::time[s]);
}
SECTION("round 1499. milliseconds with target unit second should be 1 second")
{
REQUIRE(round<si::second>(1499. * isq::time[ms]) == 1 * isq::time[s]);
}
SECTION("round 1500. milliseconds with target unit second should be 2 seconds")
{
REQUIRE(round<si::second>(1500. * isq::time[ms]) == 2 * isq::time[s]);
}
SECTION("round 1999. milliseconds with target unit second should be 2 seconds")
{
REQUIRE(round<si::second>(1999. * isq::time[ms]) == 2 * isq::time[s]);
}
SECTION("round -1000. milliseconds with target unit second should be -1 second")
{
REQUIRE(round<si::second>(-1000. * isq::time[ms]) == -1 * isq::time[s]);
}
SECTION("round -1001. milliseconds with target unit second should be -1 second")
{
REQUIRE(round<si::second>(-1001. * isq::time[ms]) == -1 * isq::time[s]);
}
SECTION("round -1499. milliseconds with target unit second should be -1 second")
{
REQUIRE(round<si::second>(-1499. * isq::time[ms]) == -1 * isq::time[s]);
}
SECTION("round -1500. milliseconds with target unit second should be -2 seconds")
{
REQUIRE(round<si::second>(-1500. * isq::time[ms]) == -2 * isq::time[s]);
}
SECTION("round -1999. milliseconds with target unit second should be -2 seconds")
{
REQUIRE(round<si::second>(-1999. * isq::time[ms]) == -2 * isq::time[s]);
}
}
TEST_CASE("hypot functions", "[hypot]")
{
SECTION("hypot should work on the same quantities")
{
REQUIRE(hypot(3. * isq::length[km], 4. * isq::length[km]) == 5. * isq::length[km]);
REQUIRE(hypot(2. * isq::length[km], 3. * isq::length[km], 6. * isq::length[km]) == 7. * isq::length[km]);
}
SECTION("hypot should work with different units of the same dimension")
{
REQUIRE(hypot(3. * isq::length[km], 4000. * isq::length[m]) == 5. * isq::length[km]);
REQUIRE(hypot(2. * isq::length[km], 3000. * isq::length[m], 6. * isq::length[km]) == 7. * isq::length[km]);
}
}
TEST_CASE("SI trigonometric functions", "[trig][si]")
{
SECTION("sin")
{
REQUIRE_THAT(si::sin(0 * deg), AlmostEquals(0. * one));
REQUIRE_THAT(si::sin(90 * deg), AlmostEquals(1. * one));
REQUIRE_THAT(si::sin(180 * deg), AlmostEquals(0. * one));
REQUIRE_THAT(si::sin(270 * deg), AlmostEquals(-1. * one));
REQUIRE(fma(1.0 * isq::length[m], 2.0 * one, 2.0 * isq::length[m]) == 4.0 * isq::length[m]);
REQUIRE(fma(isq::speed(10.0 * m / s), isq::time(2.0 * s), isq::height(42.0 * m)) == isq::length(62.0 * m));
}
SECTION("cos")
SECTION("fmod functions")
{
REQUIRE_THAT(si::cos(0 * deg), AlmostEquals(1. * one));
REQUIRE_THAT(si::cos(90 * deg), AlmostEquals(0. * one));
REQUIRE_THAT(si::cos(180 * deg), AlmostEquals(-1. * one));
REQUIRE_THAT(si::cos(270 * deg), AlmostEquals(0. * one));
SECTION("fmod should work on the same quantities")
{
REQUIRE(fmod(4. * isq::length[km], 3. * isq::length[km]) == 1. * isq::length[km]);
REQUIRE(fmod(-9. * isq::length[km], 3. * isq::length[km]) == -0. * isq::length[km]);
REQUIRE(fmod(3 * isq::length[km], 2 * isq::length[km]) == 1 * isq::length[km]);
REQUIRE(fmod(4 * isq::length[km], 2.5f * isq::length[km]) == 1.5 * isq::length[km]);
}
SECTION("fmod should work with different units of the same dimension")
{
REQUIRE(fmod(4. * isq::length[km], 3000. * isq::length[m]) == 1000. * isq::length[m]);
REQUIRE(fmod(-9. * isq::length[km], 3000. * isq::length[m]) == -0. * isq::length[m]);
REQUIRE(fmod(3. * isq::length[km], 2000. * isq::length[m]) == 1000 * isq::length[m]);
REQUIRE(fmod(4 * isq::length[km], 2500 * isq::length[m]) == 1500 * isq::length[m]);
}
}
SECTION("tan")
SECTION("remainder functions")
{
REQUIRE_THAT(si::tan(0 * deg), AlmostEquals(0. * one));
REQUIRE_THAT(si::tan(45. * deg), AlmostEquals(1. * one));
REQUIRE_THAT(si::tan(135. * deg), AlmostEquals(-1. * one));
REQUIRE_THAT(si::tan(180. * deg), AlmostEquals(0. * one));
}
}
TEST_CASE("SI inverse trigonometric functions", "[inv trig][si]")
{
SECTION("asin")
{
REQUIRE_THAT(si::asin(-1 * one), AlmostEquals(-90. * deg));
REQUIRE_THAT(si::asin(0 * one), AlmostEquals(0. * deg));
REQUIRE_THAT(si::asin(1 * one), AlmostEquals(90. * deg));
SECTION("remainder should work on the same quantities")
{
REQUIRE(remainder(4. * isq::length[km], 3. * isq::length[km]) == 1. * isq::length[km]);
REQUIRE(remainder(-9. * isq::length[km], 3. * isq::length[km]) == -0. * isq::length[km]);
REQUIRE(remainder(3 * isq::length[km], 2 * isq::length[km]) == -1 * isq::length[km]);
REQUIRE(remainder(4 * isq::length[km], 2.75f * isq::length[km]) == 1.25 * isq::length[km]);
}
SECTION("remainder should work with different units of the same dimension")
{
REQUIRE(remainder(4. * isq::length[km], 3000. * isq::length[m]) == 1000. * isq::length[m]);
REQUIRE(remainder(-9. * isq::length[km], 3000. * isq::length[m]) == -0. * isq::length[m]);
REQUIRE(remainder(3. * isq::length[km], 2000. * isq::length[m]) == -1000 * isq::length[m]);
REQUIRE(remainder(4 * isq::length[km], 2750 * isq::length[m]) == 1250 * isq::length[m]);
}
}
SECTION("acos")
SECTION("'isfinite()' accepts dimensioned arguments") { REQUIRE(isfinite(4.0 * isq::length[m])); }
SECTION("'isinf()' accepts dimensioned arguments") { REQUIRE(!isinf(4.0 * isq::length[m])); }
SECTION("'isnan()' accepts dimensioned arguments") { REQUIRE(!isnan(4.0 * isq::length[m])); }
SECTION("'pow<Num, Den>()' on quantity changes the value and the dimension accordingly")
{
REQUIRE_THAT(si::asin(-1 * one), AlmostEquals(-90. * deg));
REQUIRE_THAT(si::asin(0 * one), AlmostEquals(0. * deg));
REQUIRE_THAT(si::asin(1 * one), AlmostEquals(90. * deg));
REQUIRE(pow<1, 4>(16 * isq::area[m2]) == sqrt(4 * isq::length[m]));
}
SECTION("atan")
// TODO add tests for exp()
SECTION("absolute functions on quantity returns the absolute value")
{
REQUIRE_THAT(si::atan(-1 * one), AlmostEquals(-45. * deg));
REQUIRE_THAT(si::atan(0 * one), AlmostEquals(0. * deg));
REQUIRE_THAT(si::atan(1 * one), AlmostEquals(45. * deg));
}
}
SECTION("'abs()' on a negative quantity returns the abs")
{
SECTION("integral representation") { REQUIRE(abs(-1 * isq::length[m]) == 1 * isq::length[m]); }
TEST_CASE("SI atan2 functions", "[atan2][si]")
{
SECTION("atan2 should work on the same quantities")
{
REQUIRE_THAT(si::atan2(-1. * isq::length[km], 1. * isq::length[km]), AlmostEquals(-45. * deg));
REQUIRE_THAT(si::atan2(0. * isq::length[km], 1. * isq::length[km]), AlmostEquals(0. * deg));
REQUIRE_THAT(si::atan2(1. * isq::length[km], 1. * isq::length[km]), AlmostEquals(45. * deg));
}
SECTION("atan2 should work with different units of the same dimension")
{
REQUIRE_THAT(si::atan2(-1. * isq::length[km], 1000. * isq::length[m]), AlmostEquals(-45. * deg));
REQUIRE_THAT(si::atan2(0. * isq::length[km], 1000. * isq::length[m]), AlmostEquals(0. * deg));
REQUIRE_THAT(si::atan2(1. * isq::length[km], 1000. * isq::length[m]), AlmostEquals(45. * deg));
}
}
SECTION("floating-point representation") { REQUIRE(abs(-1. * isq::length[m]) == 1 * isq::length[m]); }
}
SECTION("'abs()' on a positive quantity returns the abs")
{
SECTION("integral representation") { REQUIRE(abs(1 * isq::length[m]) == 1 * isq::length[m]); }
TEST_CASE("Angle trigonometric functions", "[trig][angle]")
{
using namespace mp_units::angular;
using namespace mp_units::angular::unit_symbols;
using mp_units::angular::unit_symbols::deg;
SECTION("sin")
{
REQUIRE_THAT(sin(0 * angle[deg]), AlmostEquals(0. * one));
REQUIRE_THAT(sin(90 * angle[deg]), AlmostEquals(1. * one));
REQUIRE_THAT(sin(180 * angle[deg]), AlmostEquals(0. * one));
REQUIRE_THAT(sin(270 * angle[deg]), AlmostEquals(-1. * one));
REQUIRE_THAT(sin(0 * angle[grad]), AlmostEquals(0. * one));
REQUIRE_THAT(sin(100 * angle[grad]), AlmostEquals(1. * one));
REQUIRE_THAT(sin(200 * angle[grad]), AlmostEquals(0. * one, 2));
REQUIRE_THAT(sin(300 * angle[grad]), AlmostEquals(-1. * one));
SECTION("floating-point representation") { REQUIRE(abs(1. * isq::length[m]) == 1 * isq::length[m]); }
}
}
SECTION("cos")
SECTION("numeric_limits functions")
{
REQUIRE_THAT(cos(0 * angle[deg]), AlmostEquals(1. * one));
REQUIRE_THAT(cos(90 * angle[deg]), AlmostEquals(0. * one));
REQUIRE_THAT(cos(180 * angle[deg]), AlmostEquals(-1. * one));
REQUIRE_THAT(cos(270 * angle[deg]), AlmostEquals(0. * one));
REQUIRE_THAT(cos(0 * angle[grad]), AlmostEquals(1. * one));
REQUIRE_THAT(cos(100 * angle[grad]), AlmostEquals(0. * one));
REQUIRE_THAT(cos(200 * angle[grad]), AlmostEquals(-1. * one));
REQUIRE_THAT(cos(300 * angle[grad]), AlmostEquals(0. * one));
SECTION("'epsilon' works as expected using default floating type")
{
REQUIRE(epsilon<double>(isq::length[m]).numerical_value_in(m) ==
std::numeric_limits<decltype(1. * isq::length[m])::rep>::epsilon());
}
SECTION("'epsilon' works as expected using integers")
{
REQUIRE(epsilon<int>(isq::length[m]).numerical_value_in(m) ==
std::numeric_limits<decltype(1 * isq::length[m])::rep>::epsilon());
}
}
SECTION("tan")
SECTION("floor functions")
{
REQUIRE_THAT(tan(0 * angle[deg]), AlmostEquals(0. * one));
REQUIRE_THAT(tan(45 * angle[deg]), AlmostEquals(1. * one));
REQUIRE_THAT(tan(135 * angle[deg]), AlmostEquals(-1. * one));
REQUIRE_THAT(tan(180 * angle[deg]), AlmostEquals(0. * one));
SECTION("floor 1 second with target unit second should be 1 second")
{
REQUIRE(floor<si::second>(1 * isq::time[s]) == 1 * isq::time[s]);
}
SECTION("floor 1000 milliseconds with target unit second should be 1 second")
{
REQUIRE(floor<si::second>(1000 * isq::time[ms]) == 1 * isq::time[s]);
}
SECTION("floor 1001 milliseconds with target unit second should be 1 second")
{
REQUIRE(floor<si::second>(1001 * isq::time[ms]) == 1 * isq::time[s]);
}
SECTION("floor 1999 milliseconds with target unit second should be 1 second")
{
REQUIRE(floor<si::second>(1999 * isq::time[ms]) == 1 * isq::time[s]);
}
SECTION("floor -1000 milliseconds with target unit second should be -1 second")
{
REQUIRE(floor<si::second>(-1000 * isq::time[ms]) == -1 * isq::time[s]);
}
SECTION("floor -999 milliseconds with target unit second should be -1 second")
{
REQUIRE(floor<si::second>(-999 * isq::time[ms]) == -1 * isq::time[s]);
}
SECTION("floor 1.3 seconds with target unit second should be 1 second")
{
REQUIRE(floor<si::second>(1.3 * isq::time[s]) == 1 * isq::time[s]);
}
SECTION("floor -1.3 seconds with target unit second should be -2 seconds")
{
REQUIRE(floor<si::second>(-1.3 * isq::time[s]) == -2 * isq::time[s]);
}
SECTION("floor 1001. milliseconds with target unit second should be 1 second")
{
REQUIRE(floor<si::second>(1001. * isq::time[ms]) == 1 * isq::time[s]);
}
SECTION("floor 1999. milliseconds with target unit second should be 1 second")
{
REQUIRE(floor<si::second>(1999. * isq::time[ms]) == 1 * isq::time[s]);
}
SECTION("floor -1000. milliseconds with target unit second should be -1 second")
{
REQUIRE(floor<si::second>(-1000. * isq::time[ms]) == -1 * isq::time[s]);
}
SECTION("floor -999. milliseconds with target unit second should be -1 second")
{
REQUIRE(floor<si::second>(-999. * isq::time[ms]) == -1 * isq::time[s]);
}
REQUIRE_THAT(tan(0 * angle[grad]), AlmostEquals(0. * one));
REQUIRE_THAT(tan(50 * angle[grad]), AlmostEquals(1. * one));
REQUIRE_THAT(tan(150 * angle[grad]), AlmostEquals(-1. * one));
REQUIRE_THAT(tan(200 * angle[grad]), AlmostEquals(0. * one, 2));
}
}
TEST_CASE("Angle inverse trigonometric functions", "[inv trig][angle]")
{
using namespace mp_units::angular;
using namespace mp_units::angular::unit_symbols;
using mp_units::angular::unit_symbols::deg;
SECTION("asin")
{
REQUIRE_THAT(asin(-1 * one), AlmostEquals(-90. * angle[deg]));
REQUIRE_THAT(asin(0 * one), AlmostEquals(0. * angle[deg]));
REQUIRE_THAT(asin(1 * one), AlmostEquals(90. * angle[deg]));
// TODO Add tests for `N`, `kN` and `kg * m / s2` i `kg * km / s2`
}
SECTION("acos")
SECTION("ceil functions")
{
REQUIRE_THAT(asin(-1 * one), AlmostEquals(-90. * angle[deg]));
REQUIRE_THAT(asin(0 * one), AlmostEquals(0. * angle[deg]));
REQUIRE_THAT(asin(1 * one), AlmostEquals(90. * angle[deg]));
SECTION("ceil 1 second with target unit second should be 1 second")
{
REQUIRE(ceil<si::second>(1 * isq::time[s]) == 1 * isq::time[s]);
}
SECTION("ceil 1000 milliseconds with target unit second should be 1 second")
{
REQUIRE(ceil<si::second>(1000 * isq::time[ms]) == 1 * isq::time[s]);
}
SECTION("ceil 1001 milliseconds with target unit second should be 2 seconds")
{
REQUIRE(ceil<si::second>(1001 * isq::time[ms]) == 2 * isq::time[s]);
}
SECTION("ceil 1999 milliseconds with target unit second should be 2 seconds")
{
REQUIRE(ceil<si::second>(1999 * isq::time[ms]) == 2 * isq::time[s]);
}
SECTION("ceil -1000 milliseconds with target unit second should be -1 second")
{
REQUIRE(ceil<si::second>(-1000 * isq::time[ms]) == -1 * isq::time[s]);
}
SECTION("ceil -999 milliseconds with target unit second should be 0 seconds")
{
REQUIRE(ceil<si::second>(-999 * isq::time[ms]) == 0 * isq::time[s]);
}
SECTION("ceil 1.3 seconds with target unit second should be 2 seconds")
{
REQUIRE(ceil<si::second>(1.3 * isq::time[s]) == 2 * isq::time[s]);
}
SECTION("ceil -1.3 seconds with target unit second should be -1 second")
{
REQUIRE(ceil<si::second>(-1.3 * isq::time[s]) == -1 * isq::time[s]);
}
SECTION("ceil 1001. milliseconds with target unit second should be 2 seconds")
{
REQUIRE(ceil<si::second>(1001. * isq::time[ms]) == 2 * isq::time[s]);
}
SECTION("ceil 1999. milliseconds with target unit second should be 2 seconds")
{
REQUIRE(ceil<si::second>(1999. * isq::time[ms]) == 2 * isq::time[s]);
}
SECTION("ceil -1000. milliseconds with target unit second should be -1 second")
{
REQUIRE(ceil<si::second>(-1000. * isq::time[ms]) == -1 * isq::time[s]);
}
SECTION("ceil -999. milliseconds with target unit second should be 0 seconds")
{
REQUIRE(ceil<si::second>(-999. * isq::time[ms]) == 0 * isq::time[s]);
}
}
SECTION("atan")
SECTION("round functions")
{
REQUIRE_THAT(atan(-1 * one), AlmostEquals(-45. * angle[deg]));
REQUIRE_THAT(atan(0 * one), AlmostEquals(0. * angle[deg]));
REQUIRE_THAT(atan(1 * one), AlmostEquals(45. * angle[deg]));
SECTION("round 1 second with target unit second should be 1 second")
{
REQUIRE(round<si::second>(1 * isq::time[s]) == 1 * isq::time[s]);
}
SECTION("round 1000 milliseconds with target unit second should be 1 second")
{
REQUIRE(round<si::second>(1000 * isq::time[ms]) == 1 * isq::time[s]);
}
SECTION("round 1001 milliseconds with target unit second should be 1 second")
{
REQUIRE(round<si::second>(1001 * isq::time[ms]) == 1 * isq::time[s]);
}
SECTION("round 1499 milliseconds with target unit second should be 1 second")
{
REQUIRE(round<si::second>(1499 * isq::time[ms]) == 1 * isq::time[s]);
}
SECTION("round 1500 milliseconds with target unit second should be 2 seconds")
{
REQUIRE(round<si::second>(1500 * isq::time[ms]) == 2 * isq::time[s]);
}
SECTION("round 1999 milliseconds with target unit second should be 2 seconds")
{
REQUIRE(round<si::second>(1999 * isq::time[ms]) == 2 * isq::time[s]);
}
SECTION("round -1000 milliseconds with target unit second should be -1 second")
{
REQUIRE(round<si::second>(-1000 * isq::time[ms]) == -1 * isq::time[s]);
}
SECTION("round -1001 milliseconds with target unit second should be -1 second")
{
REQUIRE(round<si::second>(-1001 * isq::time[ms]) == -1 * isq::time[s]);
}
SECTION("round -1499 milliseconds with target unit second should be -1 second")
{
REQUIRE(round<si::second>(-1499 * isq::time[ms]) == -1 * isq::time[s]);
}
SECTION("round -1500 milliseconds with target unit second should be -2 seconds")
{
REQUIRE(round<si::second>(-1500 * isq::time[ms]) == -2 * isq::time[s]);
}
SECTION("round -1999 milliseconds with target unit second should be -2 seconds")
{
REQUIRE(round<si::second>(-1999 * isq::time[ms]) == -2 * isq::time[s]);
}
SECTION("round 1000. milliseconds with target unit second should be 1 second")
{
REQUIRE(round<si::second>(1000. * isq::time[ms]) == 1 * isq::time[s]);
}
SECTION("round 1001. milliseconds with target unit second should be 1 second")
{
REQUIRE(round<si::second>(1001. * isq::time[ms]) == 1 * isq::time[s]);
}
SECTION("round 1499. milliseconds with target unit second should be 1 second")
{
REQUIRE(round<si::second>(1499. * isq::time[ms]) == 1 * isq::time[s]);
}
SECTION("round 1500. milliseconds with target unit second should be 2 seconds")
{
REQUIRE(round<si::second>(1500. * isq::time[ms]) == 2 * isq::time[s]);
}
SECTION("round 1999. milliseconds with target unit second should be 2 seconds")
{
REQUIRE(round<si::second>(1999. * isq::time[ms]) == 2 * isq::time[s]);
}
SECTION("round -1000. milliseconds with target unit second should be -1 second")
{
REQUIRE(round<si::second>(-1000. * isq::time[ms]) == -1 * isq::time[s]);
}
SECTION("round -1001. milliseconds with target unit second should be -1 second")
{
REQUIRE(round<si::second>(-1001. * isq::time[ms]) == -1 * isq::time[s]);
}
SECTION("round -1499. milliseconds with target unit second should be -1 second")
{
REQUIRE(round<si::second>(-1499. * isq::time[ms]) == -1 * isq::time[s]);
}
SECTION("round -1500. milliseconds with target unit second should be -2 seconds")
{
REQUIRE(round<si::second>(-1500. * isq::time[ms]) == -2 * isq::time[s]);
}
SECTION("round -1999. milliseconds with target unit second should be -2 seconds")
{
REQUIRE(round<si::second>(-1999. * isq::time[ms]) == -2 * isq::time[s]);
}
}
}
TEST_CASE("Angle atan2 functions", "[atan2][angle]")
{
using namespace mp_units::angular;
using namespace mp_units::angular::unit_symbols;
using mp_units::angular::unit_symbols::deg;
SECTION("hypot functions")
{
SECTION("hypot should work on the same quantities")
{
REQUIRE(hypot(3. * isq::length[km], 4. * isq::length[km]) == 5. * isq::length[km]);
REQUIRE(hypot(2. * isq::length[km], 3. * isq::length[km], 6. * isq::length[km]) == 7. * isq::length[km]);
}
SECTION("hypot should work with different units of the same dimension")
{
REQUIRE(hypot(3. * isq::length[km], 4000. * isq::length[m]) == 5. * isq::length[km]);
REQUIRE(hypot(2. * isq::length[km], 3000. * isq::length[m], 6. * isq::length[km]) == 7. * isq::length[km]);
}
}
SECTION("atan2 should work on the same quantities")
SECTION("SI trigonometric functions")
{
REQUIRE_THAT(atan2(-1. * isq::length[km], 1. * isq::length[km]), AlmostEquals(-45. * angle[deg]));
REQUIRE_THAT(atan2(0. * isq::length[km], 1. * isq::length[km]), AlmostEquals(0. * angle[deg]));
REQUIRE_THAT(atan2(1. * isq::length[km], 1. * isq::length[km]), AlmostEquals(45. * angle[deg]));
SECTION("sin")
{
REQUIRE_THAT(si::sin(0 * deg), AlmostEquals(0. * one));
REQUIRE_THAT(si::sin(90 * deg), AlmostEquals(1. * one));
REQUIRE_THAT(si::sin(180 * deg), AlmostEquals(0. * one));
REQUIRE_THAT(si::sin(270 * deg), AlmostEquals(-1. * one));
}
SECTION("cos")
{
REQUIRE_THAT(si::cos(0 * deg), AlmostEquals(1. * one));
REQUIRE_THAT(si::cos(90 * deg), AlmostEquals(0. * one));
REQUIRE_THAT(si::cos(180 * deg), AlmostEquals(-1. * one));
REQUIRE_THAT(si::cos(270 * deg), AlmostEquals(0. * one));
}
SECTION("tan")
{
REQUIRE_THAT(si::tan(0 * deg), AlmostEquals(0. * one));
REQUIRE_THAT(si::tan(45. * deg), AlmostEquals(1. * one));
REQUIRE_THAT(si::tan(135. * deg), AlmostEquals(-1. * one));
REQUIRE_THAT(si::tan(180. * deg), AlmostEquals(0. * one));
}
}
SECTION("atan2 should work with different units of the same dimension")
SECTION("SI inverse trigonometric functions")
{
REQUIRE_THAT(atan2(-1. * isq::length[km], 1000. * isq::length[m]), AlmostEquals(-45. * angle[deg]));
REQUIRE_THAT(atan2(0. * isq::length[km], 1000. * isq::length[m]), AlmostEquals(0. * angle[deg]));
REQUIRE_THAT(atan2(1. * isq::length[km], 1000. * isq::length[m]), AlmostEquals(45. * angle[deg]));
SECTION("asin")
{
REQUIRE_THAT(si::asin(-1 * one), AlmostEquals(-90. * deg));
REQUIRE_THAT(si::asin(0 * one), AlmostEquals(0. * deg));
REQUIRE_THAT(si::asin(1 * one), AlmostEquals(90. * deg));
}
SECTION("acos")
{
REQUIRE_THAT(si::asin(-1 * one), AlmostEquals(-90. * deg));
REQUIRE_THAT(si::asin(0 * one), AlmostEquals(0. * deg));
REQUIRE_THAT(si::asin(1 * one), AlmostEquals(90. * deg));
}
SECTION("atan")
{
REQUIRE_THAT(si::atan(-1 * one), AlmostEquals(-45. * deg));
REQUIRE_THAT(si::atan(0 * one), AlmostEquals(0. * deg));
REQUIRE_THAT(si::atan(1 * one), AlmostEquals(45. * deg));
}
}
}
SECTION("SI atan2 functions")
{
SECTION("atan2 should work on the same quantities")
{
REQUIRE_THAT(si::atan2(-1. * isq::length[km], 1. * isq::length[km]), AlmostEquals(-45. * deg));
REQUIRE_THAT(si::atan2(0. * isq::length[km], 1. * isq::length[km]), AlmostEquals(0. * deg));
REQUIRE_THAT(si::atan2(1. * isq::length[km], 1. * isq::length[km]), AlmostEquals(45. * deg));
}
SECTION("atan2 should work with different units of the same dimension")
{
REQUIRE_THAT(si::atan2(-1. * isq::length[km], 1000. * isq::length[m]), AlmostEquals(-45. * deg));
REQUIRE_THAT(si::atan2(0. * isq::length[km], 1000. * isq::length[m]), AlmostEquals(0. * deg));
REQUIRE_THAT(si::atan2(1. * isq::length[km], 1000. * isq::length[m]), AlmostEquals(45. * deg));
}
}
SECTION("Angle trigonometric functions")
{
using namespace mp_units::angular;
using namespace mp_units::angular::unit_symbols;
using mp_units::angular::unit_symbols::deg;
SECTION("sin")
{
REQUIRE_THAT(sin(0 * angle[deg]), AlmostEquals(0. * one));
REQUIRE_THAT(sin(90 * angle[deg]), AlmostEquals(1. * one));
REQUIRE_THAT(sin(180 * angle[deg]), AlmostEquals(0. * one));
REQUIRE_THAT(sin(270 * angle[deg]), AlmostEquals(-1. * one));
REQUIRE_THAT(sin(0 * angle[grad]), AlmostEquals(0. * one));
REQUIRE_THAT(sin(100 * angle[grad]), AlmostEquals(1. * one));
REQUIRE_THAT(sin(200 * angle[grad]), AlmostEquals(0. * one, 2));
REQUIRE_THAT(sin(300 * angle[grad]), AlmostEquals(-1. * one));
}
SECTION("cos")
{
REQUIRE_THAT(cos(0 * angle[deg]), AlmostEquals(1. * one));
REQUIRE_THAT(cos(90 * angle[deg]), AlmostEquals(0. * one));
REQUIRE_THAT(cos(180 * angle[deg]), AlmostEquals(-1. * one));
REQUIRE_THAT(cos(270 * angle[deg]), AlmostEquals(0. * one));
REQUIRE_THAT(cos(0 * angle[grad]), AlmostEquals(1. * one));
REQUIRE_THAT(cos(100 * angle[grad]), AlmostEquals(0. * one));
REQUIRE_THAT(cos(200 * angle[grad]), AlmostEquals(-1. * one));
REQUIRE_THAT(cos(300 * angle[grad]), AlmostEquals(0. * one));
}
SECTION("tan")
{
REQUIRE_THAT(tan(0 * angle[deg]), AlmostEquals(0. * one));
REQUIRE_THAT(tan(45 * angle[deg]), AlmostEquals(1. * one));
REQUIRE_THAT(tan(135 * angle[deg]), AlmostEquals(-1. * one));
REQUIRE_THAT(tan(180 * angle[deg]), AlmostEquals(0. * one));
REQUIRE_THAT(tan(0 * angle[grad]), AlmostEquals(0. * one));
REQUIRE_THAT(tan(50 * angle[grad]), AlmostEquals(1. * one));
REQUIRE_THAT(tan(150 * angle[grad]), AlmostEquals(-1. * one));
REQUIRE_THAT(tan(200 * angle[grad]), AlmostEquals(0. * one, 2));
}
}
SECTION("Angle inverse trigonometric functions")
{
using namespace mp_units::angular;
using namespace mp_units::angular::unit_symbols;
using mp_units::angular::unit_symbols::deg;
SECTION("asin")
{
REQUIRE_THAT(asin(-1 * one), AlmostEquals(-90. * angle[deg]));
REQUIRE_THAT(asin(0 * one), AlmostEquals(0. * angle[deg]));
REQUIRE_THAT(asin(1 * one), AlmostEquals(90. * angle[deg]));
}
SECTION("acos")
{
REQUIRE_THAT(asin(-1 * one), AlmostEquals(-90. * angle[deg]));
REQUIRE_THAT(asin(0 * one), AlmostEquals(0. * angle[deg]));
REQUIRE_THAT(asin(1 * one), AlmostEquals(90. * angle[deg]));
}
SECTION("atan")
{
REQUIRE_THAT(atan(-1 * one), AlmostEquals(-45. * angle[deg]));
REQUIRE_THAT(atan(0 * one), AlmostEquals(0. * angle[deg]));
REQUIRE_THAT(atan(1 * one), AlmostEquals(45. * angle[deg]));
}
}
SECTION("Angle atan2 functions")
{
using namespace mp_units::angular;
using namespace mp_units::angular::unit_symbols;
using mp_units::angular::unit_symbols::deg;
SECTION("atan2 should work on the same quantities")
{
REQUIRE_THAT(atan2(-1. * isq::length[km], 1. * isq::length[km]), AlmostEquals(-45. * angle[deg]));
REQUIRE_THAT(atan2(0. * isq::length[km], 1. * isq::length[km]), AlmostEquals(0. * angle[deg]));
REQUIRE_THAT(atan2(1. * isq::length[km], 1. * isq::length[km]), AlmostEquals(45. * angle[deg]));
}
SECTION("atan2 should work with different units of the same dimension")
{
REQUIRE_THAT(atan2(-1. * isq::length[km], 1000. * isq::length[m]), AlmostEquals(-45. * angle[deg]));
REQUIRE_THAT(atan2(0. * isq::length[km], 1000. * isq::length[m]), AlmostEquals(0. * angle[deg]));
REQUIRE_THAT(atan2(1. * isq::length[km], 1000. * isq::length[m]), AlmostEquals(45. * angle[deg]));
}
}
}

View File

@ -60,22 +60,25 @@ constexpr bool within_4_ulps(T a, T b)
} // namespace
// conversion requiring radical magnitudes
TEST_CASE("unit conversions support radical magnitudes", "[conversion][radical]")
TEST_CASE("quantity operations", "[quantity]")
{
REQUIRE(within_4_ulps(sqrt((1.0 * m) * (1.0 * km)).numerical_value_in(m), sqrt(1000.0)));
}
// conversion requiring radical magnitudes
SECTION("unit conversions support radical magnitudes")
{
REQUIRE(within_4_ulps(sqrt((1.0 * m) * (1.0 * km)).numerical_value_in(m), sqrt(1000.0)));
}
// Reproducing issue #474 exactly:
TEST_CASE("Issue 474 is fixed", "[conversion][radical]")
{
constexpr auto val_issue_474 = 8.0 * si::si2019::boltzmann_constant * 1000.0 * K / (std::numbers::pi * 10 * Da);
REQUIRE(within_4_ulps(sqrt(val_issue_474).numerical_value_in(m / s),
sqrt(val_issue_474.numerical_value_in(m * m / s / s))));
}
// Reproducing issue #474 exactly:
SECTION("Issue 474 is fixed")
{
constexpr auto val_issue_474 = 8.0 * si::si2019::boltzmann_constant * 1000.0 * K / (std::numbers::pi * 10 * Da);
REQUIRE(within_4_ulps(sqrt(val_issue_474).numerical_value_in(m / s),
sqrt(val_issue_474.numerical_value_in(m * m / s / s))));
}
TEST_CASE("Volatile representation type", "[volatile]")
{
volatile std::int16_t vint = 123;
REQUIRE(quantity(vint * m).numerical_value_in(m) == 123);
}
SECTION("Volatile representation type")
{
volatile std::int16_t vint = 123;
REQUIRE(quantity(vint * m).numerical_value_in(m) == 123);
}
}