diff --git a/test/runtime/distribution_test.cpp b/test/runtime/distribution_test.cpp index 9df1eb3bf..e18d5a9eb 100644 --- a/test/runtime/distribution_test.cpp +++ b/test/runtime/distribution_test.cpp @@ -43,618 +43,621 @@ import mp_units; using namespace mp_units; -TEST_CASE("uniform_int_distribution") +TEST_CASE("distributions", "[random][distribution]") { - using rep = std::int64_t; - using q = quantity; - - SECTION("default") + SECTION("uniform_int_distribution") { - auto dist = mp_units::uniform_int_distribution(); - - CHECK(dist.a() == q::zero()); - CHECK(dist.b() == q::max()); - } + using rep = std::int64_t; + using q = quantity; - SECTION("parametrized") - { - constexpr rep a = 2; - constexpr rep b = 5; + SECTION("default") + { + auto dist = mp_units::uniform_int_distribution(); - auto stl_dist = std::uniform_int_distribution(a, b); - auto units_dist = mp_units::uniform_int_distribution(a * si::metre, b * si::metre); + CHECK(dist.a() == q::zero()); + CHECK(dist.b() == q::max()); + } - CHECK(units_dist.a() == stl_dist.a() * si::metre); - CHECK(units_dist.b() == stl_dist.b() * si::metre); - CHECK(units_dist.min() == stl_dist.min() * si::metre); - CHECK(units_dist.max() == stl_dist.max() * si::metre); - } -} + SECTION("parametrized") + { + constexpr rep a = 2; + constexpr rep b = 5; -TEST_CASE("uniform_real_distribution") -{ - using rep = long double; - using q = quantity; + auto stl_dist = std::uniform_int_distribution(a, b); + auto units_dist = mp_units::uniform_int_distribution(a * si::metre, b * si::metre); - SECTION("default") - { - auto dist = mp_units::uniform_real_distribution(); - - CHECK(dist.a() == q::zero()); - CHECK(dist.b() == q::one()); + CHECK(units_dist.a() == stl_dist.a() * si::metre); + CHECK(units_dist.b() == stl_dist.b() * si::metre); + CHECK(units_dist.min() == stl_dist.min() * si::metre); + CHECK(units_dist.max() == stl_dist.max() * si::metre); + } } - SECTION("parametrized") + SECTION("uniform_real_distribution") { - constexpr rep a = 2.0; - constexpr rep b = 5.0; + using rep = long double; + using q = quantity; - auto stl_dist = std::uniform_real_distribution(a, b); - auto units_dist = mp_units::uniform_real_distribution(a * si::metre, b * si::metre); + SECTION("default") + { + auto dist = mp_units::uniform_real_distribution(); - CHECK(units_dist.a() == stl_dist.a() * si::metre); - CHECK(units_dist.b() == stl_dist.b() * si::metre); - CHECK(units_dist.min() == stl_dist.min() * si::metre); - CHECK(units_dist.max() == stl_dist.max() * si::metre); - } -} + CHECK(dist.a() == q::zero()); + CHECK(dist.b() == q::one()); + } -TEST_CASE("binomial_distribution") -{ - using rep = std::int64_t; - using q = quantity; + SECTION("parametrized") + { + constexpr rep a = 2.0; + constexpr rep b = 5.0; - SECTION("default") - { - auto dist = mp_units::binomial_distribution(); + auto stl_dist = std::uniform_real_distribution(a, b); + auto units_dist = mp_units::uniform_real_distribution(a * si::metre, b * si::metre); - CHECK(dist.p() == 0.5); - CHECK(dist.t() == q::one()); + CHECK(units_dist.a() == stl_dist.a() * si::metre); + CHECK(units_dist.b() == stl_dist.b() * si::metre); + CHECK(units_dist.min() == stl_dist.min() * si::metre); + CHECK(units_dist.max() == stl_dist.max() * si::metre); + } } - SECTION("parametrized") + SECTION("binomial_distribution") { - constexpr rep t = 5; - constexpr double p = 0.25; + using rep = std::int64_t; + using q = quantity; - auto stl_dist = std::binomial_distribution(t, p); - auto units_dist = mp_units::binomial_distribution(t * si::metre, p); + SECTION("default") + { + auto dist = mp_units::binomial_distribution(); - CHECK(units_dist.p() == stl_dist.p()); - CHECK(units_dist.t() == stl_dist.t() * si::metre); - CHECK(units_dist.min() == stl_dist.min() * si::metre); - CHECK(units_dist.max() == stl_dist.max() * si::metre); - } -} + CHECK(dist.p() == 0.5); + CHECK(dist.t() == q::one()); + } -TEST_CASE("negative_binomial_distribution") -{ - using rep = std::int64_t; - using q = quantity; + SECTION("parametrized") + { + constexpr rep t = 5; + constexpr double p = 0.25; - SECTION("default") - { - auto dist = mp_units::negative_binomial_distribution(); + auto stl_dist = std::binomial_distribution(t, p); + auto units_dist = mp_units::binomial_distribution(t * si::metre, p); - CHECK(dist.p() == 0.5); - CHECK(dist.k() == q::one()); + CHECK(units_dist.p() == stl_dist.p()); + CHECK(units_dist.t() == stl_dist.t() * si::metre); + CHECK(units_dist.min() == stl_dist.min() * si::metre); + CHECK(units_dist.max() == stl_dist.max() * si::metre); + } } - SECTION("parametrized") + SECTION("negative_binomial_distribution") { - constexpr rep k = 5; - constexpr double p = 0.25; + using rep = std::int64_t; + using q = quantity; - auto stl_dist = std::negative_binomial_distribution(k, p); - auto units_dist = mp_units::negative_binomial_distribution(k * si::metre, p); + SECTION("default") + { + auto dist = mp_units::negative_binomial_distribution(); - CHECK(units_dist.p() == stl_dist.p()); - CHECK(units_dist.k() == stl_dist.k() * si::metre); - CHECK(units_dist.min() == stl_dist.min() * si::metre); - CHECK(units_dist.max() == stl_dist.max() * si::metre); - } -} + CHECK(dist.p() == 0.5); + CHECK(dist.k() == q::one()); + } -TEST_CASE("geometric_distribution") -{ - using rep = std::int64_t; - using q = quantity; + SECTION("parametrized") + { + constexpr rep k = 5; + constexpr double p = 0.25; - SECTION("default") - { - auto dist = mp_units::geometric_distribution(); + auto stl_dist = std::negative_binomial_distribution(k, p); + auto units_dist = mp_units::negative_binomial_distribution(k * si::metre, p); - CHECK(dist.p() == 0.5); + CHECK(units_dist.p() == stl_dist.p()); + CHECK(units_dist.k() == stl_dist.k() * si::metre); + CHECK(units_dist.min() == stl_dist.min() * si::metre); + CHECK(units_dist.max() == stl_dist.max() * si::metre); + } } - SECTION("parametrized") + SECTION("geometric_distribution") { - constexpr double p = 0.25; + using rep = std::int64_t; + using q = quantity; - auto stl_dist = std::geometric_distribution(p); - auto units_dist = mp_units::geometric_distribution(p); + SECTION("default") + { + auto dist = mp_units::geometric_distribution(); - CHECK(units_dist.p() == stl_dist.p()); - CHECK(units_dist.min() == stl_dist.min() * si::metre); - CHECK(units_dist.max() == stl_dist.max() * si::metre); - } -} + CHECK(dist.p() == 0.5); + } -TEST_CASE("poisson_distribution") -{ - using rep = std::int64_t; - using q = quantity; + SECTION("parametrized") + { + constexpr double p = 0.25; - SECTION("default") - { - auto dist = mp_units::poisson_distribution(); + auto stl_dist = std::geometric_distribution(p); + auto units_dist = mp_units::geometric_distribution(p); - CHECK(dist.mean() == 1.0); + CHECK(units_dist.p() == stl_dist.p()); + CHECK(units_dist.min() == stl_dist.min() * si::metre); + CHECK(units_dist.max() == stl_dist.max() * si::metre); + } } - SECTION("parametrized") + SECTION("poisson_distribution") { - constexpr double mean = 5.0; + using rep = std::int64_t; + using q = quantity; - auto stl_dist = std::poisson_distribution(mean); - auto units_dist = mp_units::poisson_distribution(mean); + SECTION("default") + { + auto dist = mp_units::poisson_distribution(); - CHECK(units_dist.mean() == stl_dist.mean()); - CHECK(units_dist.min() == stl_dist.min() * si::metre); - CHECK(units_dist.max() == stl_dist.max() * si::metre); - } -} + CHECK(dist.mean() == 1.0); + } -TEST_CASE("exponential_distribution") -{ - using rep = long double; - using q = quantity; + SECTION("parametrized") + { + constexpr double mean = 5.0; - SECTION("default") - { - auto dist = mp_units::exponential_distribution(); + auto stl_dist = std::poisson_distribution(mean); + auto units_dist = mp_units::poisson_distribution(mean); - CHECK(dist.lambda() == 1.0); + CHECK(units_dist.mean() == stl_dist.mean()); + CHECK(units_dist.min() == stl_dist.min() * si::metre); + CHECK(units_dist.max() == stl_dist.max() * si::metre); + } } - SECTION("parametrized") + SECTION("exponential_distribution") { - constexpr double lambda = 2.0; + using rep = long double; + using q = quantity; - auto stl_dist = std::exponential_distribution(lambda); - auto units_dist = mp_units::exponential_distribution(lambda); + SECTION("default") + { + auto dist = mp_units::exponential_distribution(); - CHECK(units_dist.lambda() == stl_dist.lambda()); - CHECK(units_dist.min() == stl_dist.min() * si::metre); - CHECK(units_dist.max() == stl_dist.max() * si::metre); - } -} + CHECK(dist.lambda() == 1.0); + } -TEST_CASE("gamma_distribution") -{ - using rep = long double; - using q = quantity; + SECTION("parametrized") + { + constexpr double lambda = 2.0; - SECTION("default") - { - auto dist = mp_units::gamma_distribution(); + auto stl_dist = std::exponential_distribution(lambda); + auto units_dist = mp_units::exponential_distribution(lambda); - CHECK(dist.alpha() == 1.0); - CHECK(dist.beta() == 1.0); + CHECK(units_dist.lambda() == stl_dist.lambda()); + CHECK(units_dist.min() == stl_dist.min() * si::metre); + CHECK(units_dist.max() == stl_dist.max() * si::metre); + } } - SECTION("parametrized") + SECTION("gamma_distribution") { - constexpr double alpha = 5.0; - constexpr double beta = 2.0; + using rep = long double; + using q = quantity; - auto stl_dist = std::gamma_distribution(alpha, beta); - auto units_dist = mp_units::gamma_distribution(alpha, beta); + SECTION("default") + { + auto dist = mp_units::gamma_distribution(); - CHECK(units_dist.alpha() == stl_dist.alpha()); - CHECK(units_dist.beta() == stl_dist.beta()); - CHECK(units_dist.min() == stl_dist.min() * si::metre); - CHECK(units_dist.max() == stl_dist.max() * si::metre); - } -} + CHECK(dist.alpha() == 1.0); + CHECK(dist.beta() == 1.0); + } -TEST_CASE("weibull_distribution") -{ - using rep = long double; - using q = quantity; + SECTION("parametrized") + { + constexpr double alpha = 5.0; + constexpr double beta = 2.0; - SECTION("default") - { - auto dist = mp_units::weibull_distribution(); + auto stl_dist = std::gamma_distribution(alpha, beta); + auto units_dist = mp_units::gamma_distribution(alpha, beta); - CHECK(dist.a() == 1.0); - CHECK(dist.b() == 1.0); + CHECK(units_dist.alpha() == stl_dist.alpha()); + CHECK(units_dist.beta() == stl_dist.beta()); + CHECK(units_dist.min() == stl_dist.min() * si::metre); + CHECK(units_dist.max() == stl_dist.max() * si::metre); + } } - SECTION("parametrized") + SECTION("weibull_distribution") { - constexpr rep a = 5.0; - constexpr rep b = 2.0; + using rep = long double; + using q = quantity; - auto stl_dist = std::weibull_distribution(a, b); - auto units_dist = mp_units::weibull_distribution(a, b); + SECTION("default") + { + auto dist = mp_units::weibull_distribution(); - CHECK(units_dist.a() == stl_dist.a()); - CHECK(units_dist.b() == stl_dist.b()); - CHECK(units_dist.min() == stl_dist.min() * si::metre); - CHECK(units_dist.max() == stl_dist.max() * si::metre); - } -} + CHECK(dist.a() == 1.0); + CHECK(dist.b() == 1.0); + } -TEST_CASE("extreme_value_distribution") -{ - using rep = long double; - using q = quantity; - - SECTION("default") - { - auto dist = mp_units::extreme_value_distribution(); + SECTION("parametrized") + { + constexpr rep a = 5.0; + constexpr rep b = 2.0; - CHECK(dist.a() == q::zero()); - CHECK(dist.b() == 1.0); - } - - SECTION("parametrized") - { - constexpr rep a = 5.0; - constexpr rep b = 2.0; - - auto stl_dist = std::extreme_value_distribution(a, b); - auto units_dist = mp_units::extreme_value_distribution(a * si::metre, b); - - CHECK(units_dist.a() == stl_dist.a() * si::metre); - CHECK(units_dist.b() == stl_dist.b()); - CHECK(units_dist.min() == stl_dist.min() * si::metre); - CHECK(units_dist.max() == stl_dist.max() * si::metre); - } -} - -TEST_CASE("normal_distribution") -{ - using rep = long double; - using q = quantity; - - SECTION("default") - { - auto dist = mp_units::normal_distribution(); + auto stl_dist = std::weibull_distribution(a, b); + auto units_dist = mp_units::weibull_distribution(a, b); - CHECK(dist.mean() == q::zero()); - CHECK(dist.stddev() == q::one()); + CHECK(units_dist.a() == stl_dist.a()); + CHECK(units_dist.b() == stl_dist.b()); + CHECK(units_dist.min() == stl_dist.min() * si::metre); + CHECK(units_dist.max() == stl_dist.max() * si::metre); + } } - SECTION("parametrized") + SECTION("extreme_value_distribution") { - constexpr rep mean = 5.0; - constexpr rep stddev = 2.0; + using rep = long double; + using q = quantity; - auto stl_dist = std::normal_distribution(mean, stddev); - auto units_dist = mp_units::normal_distribution(mean * si::metre, stddev * si::metre); + SECTION("default") + { + auto dist = mp_units::extreme_value_distribution(); - CHECK(units_dist.mean() == stl_dist.mean() * si::metre); - CHECK(units_dist.stddev() == stl_dist.stddev() * si::metre); - CHECK(units_dist.min() == stl_dist.min() * si::metre); - CHECK(units_dist.max() == stl_dist.max() * si::metre); - } -} + CHECK(dist.a() == q::zero()); + CHECK(dist.b() == 1.0); + } -TEST_CASE("lognormal_distribution") -{ - using rep = long double; - using q = quantity; + SECTION("parametrized") + { + constexpr rep a = 5.0; + constexpr rep b = 2.0; - SECTION("default") - { - auto dist = mp_units::lognormal_distribution(); + auto stl_dist = std::extreme_value_distribution(a, b); + auto units_dist = mp_units::extreme_value_distribution(a * si::metre, b); - CHECK(dist.m() == q::zero()); - CHECK(dist.s() == q::one()); + CHECK(units_dist.a() == stl_dist.a() * si::metre); + CHECK(units_dist.b() == stl_dist.b()); + CHECK(units_dist.min() == stl_dist.min() * si::metre); + CHECK(units_dist.max() == stl_dist.max() * si::metre); + } } - SECTION("parametrized") + SECTION("normal_distribution") { - constexpr rep m = 5.0; - constexpr rep s = 2.0; + using rep = long double; + using q = quantity; - auto stl_dist = std::lognormal_distribution(m, s); - auto units_dist = mp_units::lognormal_distribution(m * si::metre, s * si::metre); + SECTION("default") + { + auto dist = mp_units::normal_distribution(); - CHECK(units_dist.m() == stl_dist.m() * si::metre); - CHECK(units_dist.s() == stl_dist.s() * si::metre); - CHECK(units_dist.min() == stl_dist.min() * si::metre); - CHECK(units_dist.max() == stl_dist.max() * si::metre); - } -} + CHECK(dist.mean() == q::zero()); + CHECK(dist.stddev() == q::one()); + } -TEST_CASE("chi_squared_distribution") -{ - using rep = long double; - using q = quantity; + SECTION("parametrized") + { + constexpr rep mean = 5.0; + constexpr rep stddev = 2.0; - SECTION("default") - { - auto dist = mp_units::chi_squared_distribution(); + auto stl_dist = std::normal_distribution(mean, stddev); + auto units_dist = mp_units::normal_distribution(mean * si::metre, stddev * si::metre); - CHECK(dist.n() == 1.0); + CHECK(units_dist.mean() == stl_dist.mean() * si::metre); + CHECK(units_dist.stddev() == stl_dist.stddev() * si::metre); + CHECK(units_dist.min() == stl_dist.min() * si::metre); + CHECK(units_dist.max() == stl_dist.max() * si::metre); + } } - SECTION("parametrized") + SECTION("lognormal_distribution") { - constexpr rep n = 5.0; + using rep = long double; + using q = quantity; - auto stl_dist = std::chi_squared_distribution(n); - auto units_dist = mp_units::chi_squared_distribution(n); + SECTION("default") + { + auto dist = mp_units::lognormal_distribution(); - CHECK(units_dist.n() == stl_dist.n()); - CHECK(units_dist.min() == stl_dist.min() * si::metre); - CHECK(units_dist.max() == stl_dist.max() * si::metre); - } -} + CHECK(dist.m() == q::zero()); + CHECK(dist.s() == q::one()); + } -TEST_CASE("cauchy_distribution") -{ - using rep = long double; - using q = quantity; + SECTION("parametrized") + { + constexpr rep m = 5.0; + constexpr rep s = 2.0; - SECTION("default") - { - auto dist = mp_units::cauchy_distribution(); + auto stl_dist = std::lognormal_distribution(m, s); + auto units_dist = mp_units::lognormal_distribution(m * si::metre, s * si::metre); - CHECK(dist.a() == q::zero()); - CHECK(dist.b() == q::one()); + CHECK(units_dist.m() == stl_dist.m() * si::metre); + CHECK(units_dist.s() == stl_dist.s() * si::metre); + CHECK(units_dist.min() == stl_dist.min() * si::metre); + CHECK(units_dist.max() == stl_dist.max() * si::metre); + } } - SECTION("parametrized") + SECTION("chi_squared_distribution") { - constexpr rep a = 5.0; - constexpr rep b = 2.0; + using rep = long double; + using q = quantity; - auto stl_dist = std::cauchy_distribution(a, b); - auto units_dist = mp_units::cauchy_distribution(a * si::metre, b * si::metre); + SECTION("default") + { + auto dist = mp_units::chi_squared_distribution(); - CHECK(units_dist.a() == stl_dist.a() * si::metre); - CHECK(units_dist.b() == stl_dist.b() * si::metre); - CHECK(units_dist.min() == stl_dist.min() * si::metre); - CHECK(units_dist.max() == stl_dist.max() * si::metre); - } -} + CHECK(dist.n() == 1.0); + } -TEST_CASE("fisher_f_distribution") -{ - using rep = long double; - using q = quantity; + SECTION("parametrized") + { + constexpr rep n = 5.0; - SECTION("default") - { - auto dist = mp_units::fisher_f_distribution(); + auto stl_dist = std::chi_squared_distribution(n); + auto units_dist = mp_units::chi_squared_distribution(n); - CHECK(dist.m() == 1.0); - CHECK(dist.n() == 1.0); + CHECK(units_dist.n() == stl_dist.n()); + CHECK(units_dist.min() == stl_dist.min() * si::metre); + CHECK(units_dist.max() == stl_dist.max() * si::metre); + } } - SECTION("parametrized") + SECTION("cauchy_distribution") { - constexpr rep m = 5.0; - constexpr rep n = 2.0; + using rep = long double; + using q = quantity; - auto stl_dist = std::fisher_f_distribution(m, n); - auto units_dist = mp_units::fisher_f_distribution(m, n); + SECTION("default") + { + auto dist = mp_units::cauchy_distribution(); - CHECK(units_dist.m() == stl_dist.m()); - CHECK(units_dist.n() == stl_dist.n()); - CHECK(units_dist.min() == stl_dist.min() * si::metre); - CHECK(units_dist.max() == stl_dist.max() * si::metre); - } -} + CHECK(dist.a() == q::zero()); + CHECK(dist.b() == q::one()); + } -TEST_CASE("student_t_distribution") -{ - using rep = long double; - using q = quantity; + SECTION("parametrized") + { + constexpr rep a = 5.0; + constexpr rep b = 2.0; - SECTION("default") - { - auto dist = mp_units::student_t_distribution(); + auto stl_dist = std::cauchy_distribution(a, b); + auto units_dist = mp_units::cauchy_distribution(a * si::metre, b * si::metre); - CHECK(dist.n() == 1.0); + CHECK(units_dist.a() == stl_dist.a() * si::metre); + CHECK(units_dist.b() == stl_dist.b() * si::metre); + CHECK(units_dist.min() == stl_dist.min() * si::metre); + CHECK(units_dist.max() == stl_dist.max() * si::metre); + } } - SECTION("parametrized") + SECTION("fisher_f_distribution") { - constexpr rep n = 2.0; + using rep = long double; + using q = quantity; - auto stl_dist = std::student_t_distribution(n); - auto units_dist = mp_units::student_t_distribution(n); + SECTION("default") + { + auto dist = mp_units::fisher_f_distribution(); - CHECK(units_dist.n() == stl_dist.n()); - CHECK(units_dist.min() == stl_dist.min() * si::metre); - CHECK(units_dist.max() == stl_dist.max() * si::metre); - } -} + CHECK(dist.m() == 1.0); + CHECK(dist.n() == 1.0); + } -TEST_CASE("discrete_distribution") -{ - using rep = std::int64_t; - using q = quantity; + SECTION("parametrized") + { + constexpr rep m = 5.0; + constexpr rep n = 2.0; - SECTION("default") - { - auto stl_dist = std::discrete_distribution(); - auto units_dist = mp_units::discrete_distribution(); + auto stl_dist = std::fisher_f_distribution(m, n); + auto units_dist = mp_units::fisher_f_distribution(m, n); - CHECK(units_dist.min() == stl_dist.min() * si::metre); - CHECK(units_dist.max() == stl_dist.max() * si::metre); - CHECK(units_dist.probabilities() == stl_dist.probabilities()); + CHECK(units_dist.m() == stl_dist.m()); + CHECK(units_dist.n() == stl_dist.n()); + CHECK(units_dist.min() == stl_dist.min() * si::metre); + CHECK(units_dist.max() == stl_dist.max() * si::metre); + } } - SECTION("parametrized_input_it") + SECTION("student_t_distribution") { - constexpr std::array weights = {1.0, 2.0, 3.0}; + using rep = long double; + using q = quantity; - auto stl_dist = std::discrete_distribution(weights.cbegin(), weights.cend()); - auto units_dist = mp_units::discrete_distribution(weights.cbegin(), weights.cend()); + SECTION("default") + { + auto dist = mp_units::student_t_distribution(); - CHECK(units_dist.probabilities() == stl_dist.probabilities()); - } + CHECK(dist.n() == 1.0); + } - SECTION("parametrized_initializer_list") - { - const std::initializer_list weights = {1.0, 2.0, 3.0}; + SECTION("parametrized") + { + constexpr rep n = 2.0; - auto stl_dist = std::discrete_distribution(weights); - auto units_dist = mp_units::discrete_distribution(weights); + auto stl_dist = std::student_t_distribution(n); + auto units_dist = mp_units::student_t_distribution(n); - CHECK(units_dist.probabilities() == stl_dist.probabilities()); + CHECK(units_dist.n() == stl_dist.n()); + CHECK(units_dist.min() == stl_dist.min() * si::metre); + CHECK(units_dist.max() == stl_dist.max() * si::metre); + } } - SECTION("parametrized_range") + SECTION("discrete_distribution") { - constexpr std::size_t count = 3; - constexpr double xmin = 1, xmax = 3; + using rep = std::int64_t; + using q = quantity; - auto stl_dist = std::discrete_distribution(count, xmin, xmax, [](double val) { return val; }); - auto units_dist = mp_units::discrete_distribution(count, xmin, xmax, [](double val) { return val; }); + SECTION("default") + { + auto stl_dist = std::discrete_distribution(); + auto units_dist = mp_units::discrete_distribution(); - CHECK(units_dist.probabilities() == stl_dist.probabilities()); - } -} + CHECK(units_dist.min() == stl_dist.min() * si::metre); + CHECK(units_dist.max() == stl_dist.max() * si::metre); + CHECK(units_dist.probabilities() == stl_dist.probabilities()); + } -TEST_CASE("piecewise_constant_distribution") -{ - using rep = long double; - using q = quantity; + SECTION("parametrized_input_it") + { + constexpr std::array weights = {1.0, 2.0, 3.0}; - std::vector intervals_rep_vec = {1.0, 2.0, 3.0}; - std::vector intervals_qty_vec = {1.0 * isq::length[si::metre], 2.0 * isq::length[si::metre], - 3.0 * isq::length[si::metre]}; + auto stl_dist = std::discrete_distribution(weights.cbegin(), weights.cend()); + auto units_dist = mp_units::discrete_distribution(weights.cbegin(), weights.cend()); - SECTION("default") - { - auto stl_dist = std::piecewise_constant_distribution(); - auto units_dist = mp_units::piecewise_constant_distribution(); - - CHECK(units_dist.min() == stl_dist.min() * si::metre); - CHECK(units_dist.max() == stl_dist.max() * si::metre); - CHECK(stl_dist.intervals().size() == 2); - CHECK(units_dist.intervals().size() == 2); - CHECK(stl_dist.densities().size() == 1); - CHECK(units_dist.densities().size() == 1); - } + CHECK(units_dist.probabilities() == stl_dist.probabilities()); + } - SECTION("parametrized_input_it") - { - constexpr std::array intervals_rep = {1.0, 2.0, 3.0}; - constexpr std::array intervals_qty = {1.0 * isq::length[si::metre], 2.0 * isq::length[si::metre], - 3.0 * isq::length[si::metre]}; - constexpr std::array weights = {1.0, 2.0, 3.0}; - - auto stl_dist = - std::piecewise_constant_distribution(intervals_rep.cbegin(), intervals_rep.cend(), weights.cbegin()); - auto units_dist = - mp_units::piecewise_constant_distribution(intervals_qty.cbegin(), intervals_qty.cend(), weights.cbegin()); - - CHECK(stl_dist.intervals() == intervals_rep_vec); - CHECK(units_dist.intervals() == intervals_qty_vec); - CHECK(units_dist.densities() == stl_dist.densities()); - } + SECTION("parametrized_initializer_list") + { + const std::initializer_list weights = {1.0, 2.0, 3.0}; - SECTION("parametrized_initializer_list") - { - const std::initializer_list intervals_rep = {1.0, 2.0, 3.0}; - const std::initializer_list intervals_qty = {1.0 * isq::length[si::metre], 2.0 * isq::length[si::metre], - 3.0 * isq::length[si::metre]}; + auto stl_dist = std::discrete_distribution(weights); + auto units_dist = mp_units::discrete_distribution(weights); - auto stl_dist = std::piecewise_constant_distribution(intervals_rep, [](rep val) { return val; }); - auto units_dist = mp_units::piecewise_constant_distribution( - intervals_qty, [](q qty) { return qty.numerical_value_ref_in(qty.unit); }); + CHECK(units_dist.probabilities() == stl_dist.probabilities()); + } - CHECK(units_dist.intervals() == intervals_qty_vec); - CHECK(units_dist.densities() == stl_dist.densities()); - } + SECTION("parametrized_range") + { + constexpr std::size_t count = 3; + constexpr double xmin = 1, xmax = 3; - SECTION("parametrized_range") - { - constexpr std::size_t nw = 2; - constexpr rep xmin_rep = 1.0, xmax_rep = 3.0; - constexpr q xmin_qty = 1.0 * isq::length[si::metre], xmax_qty = 3.0 * isq::length[si::metre]; - - auto stl_dist = std::piecewise_constant_distribution(nw, xmin_rep, xmax_rep, [](rep val) { return val; }); - auto units_dist = mp_units::piecewise_constant_distribution( - nw, xmin_qty, xmax_qty, [](q qty) { return qty.numerical_value_ref_in(qty.unit); }); + auto stl_dist = std::discrete_distribution(count, xmin, xmax, [](double val) { return val; }); + auto units_dist = mp_units::discrete_distribution(count, xmin, xmax, [](double val) { return val; }); - CHECK(units_dist.intervals() == intervals_qty_vec); - CHECK(units_dist.densities() == stl_dist.densities()); + CHECK(units_dist.probabilities() == stl_dist.probabilities()); + } } -} - -TEST_CASE("piecewise_linear_distribution") -{ - using rep = long double; - using q = quantity; - - std::vector intervals_rep_vec = {1.0, 2.0, 3.0}; - std::vector intervals_qty_vec = {1.0 * isq::length[si::metre], 2.0 * isq::length[si::metre], - 3.0 * isq::length[si::metre]}; - SECTION("default") + SECTION("piecewise_constant_distribution") { - auto stl_dist = std::piecewise_linear_distribution(); - auto units_dist = mp_units::piecewise_linear_distribution(); - - CHECK(units_dist.min() == stl_dist.min() * si::metre); - CHECK(units_dist.max() == stl_dist.max() * si::metre); - CHECK(stl_dist.intervals().size() == 2); - CHECK(units_dist.intervals().size() == 2); - CHECK(stl_dist.densities().size() == 2); - CHECK(units_dist.densities().size() == 2); - } - - SECTION("parametrized_input_it") - { - constexpr std::array intervals_rep = {1.0, 2.0, 3.0}; - constexpr std::array intervals_qty = {1.0 * isq::length[si::metre], 2.0 * isq::length[si::metre], - 3.0 * isq::length[si::metre]}; - constexpr std::array weights = {1.0, 2.0, 3.0}; - - auto stl_dist = - std::piecewise_linear_distribution(intervals_rep.cbegin(), intervals_rep.cend(), weights.cbegin()); - auto units_dist = - mp_units::piecewise_linear_distribution(intervals_qty.cbegin(), intervals_qty.cend(), weights.cbegin()); - - CHECK(stl_dist.intervals() == intervals_rep_vec); - CHECK(units_dist.intervals() == intervals_qty_vec); - CHECK(units_dist.densities() == stl_dist.densities()); - } - - SECTION("parametrized_initializer_list") - { - const std::initializer_list intervals_rep = {1.0, 2.0, 3.0}; - const std::initializer_list intervals_qty = {1.0 * isq::length[si::metre], 2.0 * isq::length[si::metre], - 3.0 * isq::length[si::metre]}; + using rep = long double; + using q = quantity; - auto stl_dist = std::piecewise_linear_distribution(intervals_rep, [](rep val) { return val; }); - auto units_dist = mp_units::piecewise_linear_distribution( - intervals_qty, [](q qty) { return qty.numerical_value_ref_in(qty.unit); }); + std::vector intervals_rep_vec = {1.0, 2.0, 3.0}; + std::vector intervals_qty_vec = {1.0 * isq::length[si::metre], 2.0 * isq::length[si::metre], + 3.0 * isq::length[si::metre]}; - CHECK(units_dist.intervals() == intervals_qty_vec); - CHECK(units_dist.densities() == stl_dist.densities()); - } + SECTION("default") + { + auto stl_dist = std::piecewise_constant_distribution(); + auto units_dist = mp_units::piecewise_constant_distribution(); - SECTION("parametrized_range") - { - constexpr std::size_t nw = 2; - constexpr rep xmin_rep = 1.0, xmax_rep = 3.0; - constexpr q xmin_qty = 1.0 * isq::length[si::metre], xmax_qty = 3.0 * isq::length[si::metre]; + CHECK(units_dist.min() == stl_dist.min() * si::metre); + CHECK(units_dist.max() == stl_dist.max() * si::metre); + CHECK(stl_dist.intervals().size() == 2); + CHECK(units_dist.intervals().size() == 2); + CHECK(stl_dist.densities().size() == 1); + CHECK(units_dist.densities().size() == 1); + } - auto stl_dist = std::piecewise_linear_distribution(nw, xmin_rep, xmax_rep, [](rep val) { return val; }); - auto units_dist = mp_units::piecewise_linear_distribution( - nw, xmin_qty, xmax_qty, [](q qty) { return qty.numerical_value_ref_in(qty.unit); }); - - CHECK(units_dist.intervals() == intervals_qty_vec); - CHECK(units_dist.densities() == stl_dist.densities()); - } -} + SECTION("parametrized_input_it") + { + constexpr std::array intervals_rep = {1.0, 2.0, 3.0}; + constexpr std::array intervals_qty = {1.0 * isq::length[si::metre], 2.0 * isq::length[si::metre], + 3.0 * isq::length[si::metre]}; + constexpr std::array weights = {1.0, 2.0, 3.0}; + + auto stl_dist = + std::piecewise_constant_distribution(intervals_rep.cbegin(), intervals_rep.cend(), weights.cbegin()); + auto units_dist = + mp_units::piecewise_constant_distribution(intervals_qty.cbegin(), intervals_qty.cend(), weights.cbegin()); + + CHECK(stl_dist.intervals() == intervals_rep_vec); + CHECK(units_dist.intervals() == intervals_qty_vec); + CHECK(units_dist.densities() == stl_dist.densities()); + } + + SECTION("parametrized_initializer_list") + { + const std::initializer_list intervals_rep = {1.0, 2.0, 3.0}; + const std::initializer_list intervals_qty = {1.0 * isq::length[si::metre], 2.0 * isq::length[si::metre], + 3.0 * isq::length[si::metre]}; + + auto stl_dist = std::piecewise_constant_distribution(intervals_rep, [](rep val) { return val; }); + auto units_dist = mp_units::piecewise_constant_distribution( + intervals_qty, [](q qty) { return qty.numerical_value_ref_in(qty.unit); }); + + CHECK(units_dist.intervals() == intervals_qty_vec); + CHECK(units_dist.densities() == stl_dist.densities()); + } + + SECTION("parametrized_range") + { + constexpr std::size_t nw = 2; + constexpr rep xmin_rep = 1.0, xmax_rep = 3.0; + constexpr q xmin_qty = 1.0 * isq::length[si::metre], xmax_qty = 3.0 * isq::length[si::metre]; + + auto stl_dist = std::piecewise_constant_distribution(nw, xmin_rep, xmax_rep, [](rep val) { return val; }); + auto units_dist = mp_units::piecewise_constant_distribution( + nw, xmin_qty, xmax_qty, [](q qty) { return qty.numerical_value_ref_in(qty.unit); }); + + CHECK(units_dist.intervals() == intervals_qty_vec); + CHECK(units_dist.densities() == stl_dist.densities()); + } + } + + SECTION("piecewise_linear_distribution") + { + using rep = long double; + using q = quantity; + + std::vector intervals_rep_vec = {1.0, 2.0, 3.0}; + std::vector intervals_qty_vec = {1.0 * isq::length[si::metre], 2.0 * isq::length[si::metre], + 3.0 * isq::length[si::metre]}; + + SECTION("default") + { + auto stl_dist = std::piecewise_linear_distribution(); + auto units_dist = mp_units::piecewise_linear_distribution(); + + CHECK(units_dist.min() == stl_dist.min() * si::metre); + CHECK(units_dist.max() == stl_dist.max() * si::metre); + CHECK(stl_dist.intervals().size() == 2); + CHECK(units_dist.intervals().size() == 2); + CHECK(stl_dist.densities().size() == 2); + CHECK(units_dist.densities().size() == 2); + } + + SECTION("parametrized_input_it") + { + constexpr std::array intervals_rep = {1.0, 2.0, 3.0}; + constexpr std::array intervals_qty = {1.0 * isq::length[si::metre], 2.0 * isq::length[si::metre], + 3.0 * isq::length[si::metre]}; + constexpr std::array weights = {1.0, 2.0, 3.0}; + + auto stl_dist = + std::piecewise_linear_distribution(intervals_rep.cbegin(), intervals_rep.cend(), weights.cbegin()); + auto units_dist = + mp_units::piecewise_linear_distribution(intervals_qty.cbegin(), intervals_qty.cend(), weights.cbegin()); + + CHECK(stl_dist.intervals() == intervals_rep_vec); + CHECK(units_dist.intervals() == intervals_qty_vec); + CHECK(units_dist.densities() == stl_dist.densities()); + } + + SECTION("parametrized_initializer_list") + { + const std::initializer_list intervals_rep = {1.0, 2.0, 3.0}; + const std::initializer_list intervals_qty = {1.0 * isq::length[si::metre], 2.0 * isq::length[si::metre], + 3.0 * isq::length[si::metre]}; + + auto stl_dist = std::piecewise_linear_distribution(intervals_rep, [](rep val) { return val; }); + auto units_dist = mp_units::piecewise_linear_distribution( + intervals_qty, [](q qty) { return qty.numerical_value_ref_in(qty.unit); }); + + CHECK(units_dist.intervals() == intervals_qty_vec); + CHECK(units_dist.densities() == stl_dist.densities()); + } + + SECTION("parametrized_range") + { + constexpr std::size_t nw = 2; + constexpr rep xmin_rep = 1.0, xmax_rep = 3.0; + constexpr q xmin_qty = 1.0 * isq::length[si::metre], xmax_qty = 3.0 * isq::length[si::metre]; + + auto stl_dist = std::piecewise_linear_distribution(nw, xmin_rep, xmax_rep, [](rep val) { return val; }); + auto units_dist = mp_units::piecewise_linear_distribution( + nw, xmin_qty, xmax_qty, [](q qty) { return qty.numerical_value_ref_in(qty.unit); }); + + CHECK(units_dist.intervals() == intervals_qty_vec); + CHECK(units_dist.densities() == stl_dist.densities()); + } + } +} \ No newline at end of file diff --git a/test/runtime/fixed_string_test.cpp b/test/runtime/fixed_string_test.cpp index b1b01f214..f3bc737aa 100644 --- a/test/runtime/fixed_string_test.cpp +++ b/test/runtime/fixed_string_test.cpp @@ -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")); + } } } diff --git a/test/runtime/fmt_test.cpp b/test/runtime/fmt_test.cpp index 03eef6767..4011588e1 100644 --- a/test/runtime/fmt_test.cpp +++ b/test/runtime/fmt_test.cpp @@ -55,7 +55,271 @@ constexpr bool mp_units::is_vector = true; using namespace mp_units; using namespace mp_units::si::unit_symbols; -TEST_CASE("operator<< on a quantity", "[text][ostream][fmt]") +TEST_CASE("dimension_symbol", "[dimension][symbol]") +{ + using enum text_encoding; + + std::ostringstream os; + + SECTION("default formatting") + { + os << dimension_symbol(isq::power.dimension); + CHECK(os.str() == "L²MT⁻³"); + } + + SECTION("Portable mode") + { + os << dimension_symbol(isq::power.dimension); + CHECK(os.str() == "L^2MT^-3"); + } +} + +TEST_CASE("unit_symbol", "[unit][symbol]") +{ + using enum text_encoding; + using enum unit_symbol_solidus; + using enum unit_symbol_separator; + + std::ostringstream os; + + SECTION("default formatting") + { + os << unit_symbol(m / s2); + CHECK(os.str() == "m/s²"); + } + + SECTION("Portable mode") + { + os << unit_symbol(m / s2); + CHECK(os.str() == "m/s^2"); + } + + SECTION("solidus") + { + os << unit_symbol(m / s2); + CHECK(os.str() == "m s⁻²"); + } + + SECTION("separator") + { + os << unit_symbol(m / s2); + CHECK(os.str() == "m⋅s⁻²"); + } +} + +// TODO add dimension formatting tests + +TEST_CASE("unit formatting", "[unit][fmt]") +{ + SECTION("Unit formatting should use proper text encoding") + { + SECTION("Unicode text output") + { + CHECK(MP_UNITS_STD_FMT::format("{:U}", km / h) == "km/h"); + CHECK(MP_UNITS_STD_FMT::format("{:U}", si::kilo) == "kΩ"); + CHECK(MP_UNITS_STD_FMT::format("{:U}", us) == "µs"); + CHECK(MP_UNITS_STD_FMT::format("{:U}", m / s2) == "m/s²"); + } + + SECTION("Unicode text output is used by default") + { + CHECK(MP_UNITS_STD_FMT::format("{}", km / h) == "km/h"); + CHECK(MP_UNITS_STD_FMT::format("{}", si::kilo) == "kΩ"); + CHECK(MP_UNITS_STD_FMT::format("{}", us) == "µs"); + CHECK(MP_UNITS_STD_FMT::format("{}", m / s2) == "m/s²"); + } + + SECTION("Portable text output") + { + CHECK(MP_UNITS_STD_FMT::format("{:P}", km / h) == "km/h"); + CHECK(MP_UNITS_STD_FMT::format("{:P}", si::kilo) == "kohm"); + CHECK(MP_UNITS_STD_FMT::format("{:P}", us) == "us"); + CHECK(MP_UNITS_STD_FMT::format("{:P}", m / s2) == "m/s^2"); + } + } + + SECTION("unit formatting should print solidus according to specs") + { + SECTION("Solidus for only one element in denominator") + { + CHECK(MP_UNITS_STD_FMT::format("{:1}", km / h) == "km/h"); + CHECK(MP_UNITS_STD_FMT::format("{:1}", m / s2) == "m/s²"); + CHECK(MP_UNITS_STD_FMT::format("{:1}", kg / m / s2) == "kg m⁻¹ s⁻²"); + } + + SECTION("Solidus for only one element in denominator is used by default") + { + CHECK(MP_UNITS_STD_FMT::format("{}", km / h) == "km/h"); + CHECK(MP_UNITS_STD_FMT::format("{}", m / s2) == "m/s²"); + CHECK(MP_UNITS_STD_FMT::format("{}", kg / m / s2) == "kg m⁻¹ s⁻²"); + } + + SECTION("Always use solidus") + { + CHECK(MP_UNITS_STD_FMT::format("{:a}", km / h) == "km/h"); + CHECK(MP_UNITS_STD_FMT::format("{:a}", m / s2) == "m/s²"); + CHECK(MP_UNITS_STD_FMT::format("{:a}", kg / m / s2) == "kg/(m s²)"); + } + + SECTION("Never use solidus") + { + CHECK(MP_UNITS_STD_FMT::format("{:n}", km / h) == "km h⁻¹"); + CHECK(MP_UNITS_STD_FMT::format("{:n}", m / s2) == "m s⁻²"); + CHECK(MP_UNITS_STD_FMT::format("{:n}", kg / m / s2) == "kg m⁻¹ s⁻²"); + } + } + + SECTION("Unit formatting should user proper separator") + { + SECTION("Space") + { + CHECK(MP_UNITS_STD_FMT::format("{:s}", kg * m / s2) == "kg m/s²"); + CHECK(MP_UNITS_STD_FMT::format("{:s}", kg / m / s2) == "kg m⁻¹ s⁻²"); + CHECK(MP_UNITS_STD_FMT::format("{:sa}", kg / m / s2) == "kg/(m s²)"); + } + + SECTION("Space is used by default") + { + CHECK(MP_UNITS_STD_FMT::format("{}", kg * m / s2) == "kg m/s²"); + CHECK(MP_UNITS_STD_FMT::format("{}", kg / m / s2) == "kg m⁻¹ s⁻²"); + CHECK(MP_UNITS_STD_FMT::format("{:a}", kg / m / s2) == "kg/(m s²)"); + } + + SECTION("Dot") + { + CHECK(MP_UNITS_STD_FMT::format("{:d}", kg * m / s2) == "kg⋅m/s²"); + CHECK(MP_UNITS_STD_FMT::format("{:d}", kg / m / s2) == "kg⋅m⁻¹⋅s⁻²"); + CHECK(MP_UNITS_STD_FMT::format("{:ad}", kg / m / s2) == "kg/(m⋅s²)"); + } + } +} + +TEST_CASE("unit formatting error handling", "[unit][fmt][exception]") +{ + SECTION("unknown unit modifiers should throw") + { + SECTION("only the invalid modifier") + { + REQUIRE_THROWS_MATCHES(MP_UNITS_STD_FMT::vformat("{:x}", MP_UNITS_STD_FMT::make_format_args(m)), + MP_UNITS_STD_FMT::format_error, + Catch::Matchers::Message("invalid unit modifier specified")); + } + + SECTION("invalid modifier in the front") + { + REQUIRE_THROWS_MATCHES(MP_UNITS_STD_FMT::vformat("{:xUda}", MP_UNITS_STD_FMT::make_format_args(m)), + MP_UNITS_STD_FMT::format_error, + Catch::Matchers::Message("invalid unit modifier specified")); + } + + SECTION("invalid modifier in the end") + { + REQUIRE_THROWS_MATCHES(MP_UNITS_STD_FMT::vformat("{:Udax}", MP_UNITS_STD_FMT::make_format_args(m)), + MP_UNITS_STD_FMT::format_error, + Catch::Matchers::Message("invalid unit modifier specified")); + } + + SECTION("invalid modifier in the middle") + { + REQUIRE_THROWS_MATCHES(MP_UNITS_STD_FMT::vformat("{:Udxa}", MP_UNITS_STD_FMT::make_format_args(m)), + MP_UNITS_STD_FMT::format_error, + Catch::Matchers::Message("invalid unit modifier specified")); + } + } + + SECTION("repeated unit modifiers should throw") + { + SECTION("text encoding") + { + REQUIRE_THROWS_MATCHES( + MP_UNITS_STD_FMT::vformat("{:UdaU}", MP_UNITS_STD_FMT::make_format_args(m)), MP_UNITS_STD_FMT::format_error, + Catch::Matchers::Message("only one of 'UAP' unit modifiers may be used in the format spec")); + REQUIRE_THROWS_MATCHES( + MP_UNITS_STD_FMT::vformat("{:dUaU}", MP_UNITS_STD_FMT::make_format_args(m)), MP_UNITS_STD_FMT::format_error, + Catch::Matchers::Message("only one of 'UAP' unit modifiers may be used in the format spec")); + REQUIRE_THROWS_MATCHES( + MP_UNITS_STD_FMT::vformat("{:dUUa}", MP_UNITS_STD_FMT::make_format_args(m)), MP_UNITS_STD_FMT::format_error, + Catch::Matchers::Message("only one of 'UAP' unit modifiers may be used in the format spec")); + } + + SECTION("solidus") + { + REQUIRE_THROWS_MATCHES( + MP_UNITS_STD_FMT::vformat("{:aUda}", MP_UNITS_STD_FMT::make_format_args(m)), MP_UNITS_STD_FMT::format_error, + Catch::Matchers::Message("only one of '1an' unit modifiers may be used in the format spec")); + REQUIRE_THROWS_MATCHES( + MP_UNITS_STD_FMT::vformat("{:daUa}", MP_UNITS_STD_FMT::make_format_args(m)), MP_UNITS_STD_FMT::format_error, + Catch::Matchers::Message("only one of '1an' unit modifiers may be used in the format spec")); + REQUIRE_THROWS_MATCHES( + MP_UNITS_STD_FMT::vformat("{:daaU}", MP_UNITS_STD_FMT::make_format_args(m)), MP_UNITS_STD_FMT::format_error, + Catch::Matchers::Message("only one of '1an' unit modifiers may be used in the format spec")); + } + + SECTION("separator") + { + REQUIRE_THROWS_MATCHES( + MP_UNITS_STD_FMT::vformat("{:dUad}", MP_UNITS_STD_FMT::make_format_args(m)), MP_UNITS_STD_FMT::format_error, + Catch::Matchers::Message("only one of 'sd' unit modifiers may be used in the format spec")); + REQUIRE_THROWS_MATCHES( + MP_UNITS_STD_FMT::vformat("{:dadU}", MP_UNITS_STD_FMT::make_format_args(m)), MP_UNITS_STD_FMT::format_error, + Catch::Matchers::Message("only one of 'sd' unit modifiers may be used in the format spec")); + REQUIRE_THROWS_MATCHES( + MP_UNITS_STD_FMT::vformat("{:addU}", MP_UNITS_STD_FMT::make_format_args(m)), MP_UNITS_STD_FMT::format_error, + Catch::Matchers::Message("only one of 'sd' unit modifiers may be used in the format spec")); + } + } + + SECTION("more then one modifier of the same kind should throw") + { + SECTION("text encoding") + { + REQUIRE_THROWS_MATCHES( + MP_UNITS_STD_FMT::vformat("{:UdaP}", MP_UNITS_STD_FMT::make_format_args(m)), MP_UNITS_STD_FMT::format_error, + Catch::Matchers::Message("only one of 'UAP' unit modifiers may be used in the format spec")); + REQUIRE_THROWS_MATCHES( + MP_UNITS_STD_FMT::vformat("{:dPaU}", MP_UNITS_STD_FMT::make_format_args(m)), MP_UNITS_STD_FMT::format_error, + Catch::Matchers::Message("only one of 'UAP' unit modifiers may be used in the format spec")); + REQUIRE_THROWS_MATCHES( + MP_UNITS_STD_FMT::vformat("{:dPUa}", MP_UNITS_STD_FMT::make_format_args(m)), MP_UNITS_STD_FMT::format_error, + Catch::Matchers::Message("only one of 'UAP' unit modifiers may be used in the format spec")); + } + + SECTION("solidus") + { + REQUIRE_THROWS_MATCHES( + MP_UNITS_STD_FMT::vformat("{:aUdn}", MP_UNITS_STD_FMT::make_format_args(m)), MP_UNITS_STD_FMT::format_error, + Catch::Matchers::Message("only one of '1an' unit modifiers may be used in the format spec")); + REQUIRE_THROWS_MATCHES( + MP_UNITS_STD_FMT::vformat("{:dnUa}", MP_UNITS_STD_FMT::make_format_args(m)), MP_UNITS_STD_FMT::format_error, + Catch::Matchers::Message("only one of '1an' unit modifiers may be used in the format spec")); + REQUIRE_THROWS_MATCHES( + MP_UNITS_STD_FMT::vformat("{:da1U}", MP_UNITS_STD_FMT::make_format_args(m)), MP_UNITS_STD_FMT::format_error, + Catch::Matchers::Message("only one of '1an' unit modifiers may be used in the format spec")); + } + + SECTION("separator") + { + REQUIRE_THROWS_MATCHES( + MP_UNITS_STD_FMT::vformat("{:dUas}", MP_UNITS_STD_FMT::make_format_args(m)), MP_UNITS_STD_FMT::format_error, + Catch::Matchers::Message("only one of 'sd' unit modifiers may be used in the format spec")); + REQUIRE_THROWS_MATCHES( + MP_UNITS_STD_FMT::vformat("{:sadU}", MP_UNITS_STD_FMT::make_format_args(m)), MP_UNITS_STD_FMT::format_error, + Catch::Matchers::Message("only one of 'sd' unit modifiers may be used in the format spec")); + REQUIRE_THROWS_MATCHES( + MP_UNITS_STD_FMT::vformat("{:adsU}", MP_UNITS_STD_FMT::make_format_args(m)), MP_UNITS_STD_FMT::format_error, + Catch::Matchers::Message("only one of 'sd' unit modifiers may be used in the format spec")); + } + } + + SECTION("half_high_dot separator requested for portable encoding should throw") + { + REQUIRE_THROWS_MATCHES(MP_UNITS_STD_FMT::vformat("{:dPa}", MP_UNITS_STD_FMT::make_format_args(m)), + MP_UNITS_STD_FMT::format_error, + Catch::Matchers::Message("half_high_dot unit separator allowed only for UTF-8 encoding")); + } +} + +TEST_CASE("default quantity formatting", "[quantity][ostream][fmt]") { std::ostringstream os; @@ -375,266 +639,7 @@ TEST_CASE("operator<< on a quantity", "[text][ostream][fmt]") } } -TEST_CASE("quantity format string with only %N should print quantity value only", "[text][fmt]") -{ - SECTION("integral representation") - { - SECTION("positive value") { CHECK(MP_UNITS_STD_FMT::format("{:%N}", 123 * isq::speed[km / h]) == "123"); } - - SECTION("negative value") - { - CHECK(MP_UNITS_STD_FMT::format("{:%N}", 5 * isq::length[m] - 10 * isq::length[m]) == "-5"); - } - } - - SECTION("floating-point representation") - { - SECTION("positive value") - { - CHECK(MP_UNITS_STD_FMT::format("{:%N}", 221. * isq::length[km] / (2 * isq::time[h])) == "110.5"); - } - - SECTION("negative value") - { - CHECK(MP_UNITS_STD_FMT::format("{:%N}", 3.14 * isq::length[m] - 10 * isq::length[m]) == "-6.859999999999999"); - } - - SECTION("nan") - { - CHECK(MP_UNITS_STD_FMT::format("{:%N}", std::numeric_limits::quiet_NaN() * isq::length[m]) == "nan"); - } - - SECTION("inf") - { - CHECK(MP_UNITS_STD_FMT::format("{:%N}", std::numeric_limits::infinity() * isq::length[m]) == "inf"); - } - - SECTION("-inf") - { - CHECK(MP_UNITS_STD_FMT::format("{:%N}", -std::numeric_limits::infinity() * isq::length[m]) == "-inf"); - } - } -} - -TEST_CASE("quantity format string with only %U should print quantity unit symbol only", "[text][fmt]") -{ - CHECK(MP_UNITS_STD_FMT::format("{:%U}", 123 * isq::speed[km / h]) == "km/h"); - CHECK(MP_UNITS_STD_FMT::format("{:%U}", 123 * isq::resistance[si::kilo]) == "kΩ"); - CHECK(MP_UNITS_STD_FMT::format("{:%U}", 123 * isq::time[us]) == "µs"); - CHECK(MP_UNITS_STD_FMT::format("{:%U}", 123 * isq::acceleration[m / s2]) == "m/s²"); - CHECK(MP_UNITS_STD_FMT::format("{:%U}", 123 * percent) == "%"); -} - -TEST_CASE("Unit formatting should use proper text encoding") -{ - SECTION("Unicode text output") - { - CHECK(MP_UNITS_STD_FMT::format("{:U}", km / h) == "km/h"); - CHECK(MP_UNITS_STD_FMT::format("{:U}", si::kilo) == "kΩ"); - CHECK(MP_UNITS_STD_FMT::format("{:U}", us) == "µs"); - CHECK(MP_UNITS_STD_FMT::format("{:U}", m / s2) == "m/s²"); - } - - SECTION("Unicode text output is used by default") - { - CHECK(MP_UNITS_STD_FMT::format("{}", km / h) == "km/h"); - CHECK(MP_UNITS_STD_FMT::format("{}", si::kilo) == "kΩ"); - CHECK(MP_UNITS_STD_FMT::format("{}", us) == "µs"); - CHECK(MP_UNITS_STD_FMT::format("{}", m / s2) == "m/s²"); - } - - SECTION("Portable text output") - { - CHECK(MP_UNITS_STD_FMT::format("{:P}", km / h) == "km/h"); - CHECK(MP_UNITS_STD_FMT::format("{:P}", si::kilo) == "kohm"); - CHECK(MP_UNITS_STD_FMT::format("{:P}", us) == "us"); - CHECK(MP_UNITS_STD_FMT::format("{:P}", m / s2) == "m/s^2"); - } -} - -TEST_CASE("Unit formatting should print solidus according to specs") -{ - SECTION("Solidus for only one element in denominator") - { - CHECK(MP_UNITS_STD_FMT::format("{:1}", km / h) == "km/h"); - CHECK(MP_UNITS_STD_FMT::format("{:1}", m / s2) == "m/s²"); - CHECK(MP_UNITS_STD_FMT::format("{:1}", kg / m / s2) == "kg m⁻¹ s⁻²"); - } - - SECTION("Solidus for only one element in denominator is used by default") - { - CHECK(MP_UNITS_STD_FMT::format("{}", km / h) == "km/h"); - CHECK(MP_UNITS_STD_FMT::format("{}", m / s2) == "m/s²"); - CHECK(MP_UNITS_STD_FMT::format("{}", kg / m / s2) == "kg m⁻¹ s⁻²"); - } - - SECTION("Always use solidus") - { - CHECK(MP_UNITS_STD_FMT::format("{:a}", km / h) == "km/h"); - CHECK(MP_UNITS_STD_FMT::format("{:a}", m / s2) == "m/s²"); - CHECK(MP_UNITS_STD_FMT::format("{:a}", kg / m / s2) == "kg/(m s²)"); - } - - SECTION("Never use solidus") - { - CHECK(MP_UNITS_STD_FMT::format("{:n}", km / h) == "km h⁻¹"); - CHECK(MP_UNITS_STD_FMT::format("{:n}", m / s2) == "m s⁻²"); - CHECK(MP_UNITS_STD_FMT::format("{:n}", kg / m / s2) == "kg m⁻¹ s⁻²"); - } -} - -TEST_CASE("Unit formatting should user proper separator") -{ - SECTION("Space") - { - CHECK(MP_UNITS_STD_FMT::format("{:s}", kg * m / s2) == "kg m/s²"); - CHECK(MP_UNITS_STD_FMT::format("{:s}", kg / m / s2) == "kg m⁻¹ s⁻²"); - CHECK(MP_UNITS_STD_FMT::format("{:sa}", kg / m / s2) == "kg/(m s²)"); - } - - SECTION("Space is used by default") - { - CHECK(MP_UNITS_STD_FMT::format("{}", kg * m / s2) == "kg m/s²"); - CHECK(MP_UNITS_STD_FMT::format("{}", kg / m / s2) == "kg m⁻¹ s⁻²"); - CHECK(MP_UNITS_STD_FMT::format("{:a}", kg / m / s2) == "kg/(m s²)"); - } - - SECTION("Dot") - { - CHECK(MP_UNITS_STD_FMT::format("{:d}", kg * m / s2) == "kg⋅m/s²"); - CHECK(MP_UNITS_STD_FMT::format("{:d}", kg / m / s2) == "kg⋅m⁻¹⋅s⁻²"); - CHECK(MP_UNITS_STD_FMT::format("{:ad}", kg / m / s2) == "kg/(m⋅s²)"); - } -} - -TEST_CASE("unknown unit modifiers should throw", "[text][fmt][exception]") -{ - SECTION("only the invalid modifier") - { - REQUIRE_THROWS_MATCHES(MP_UNITS_STD_FMT::vformat("{:x}", MP_UNITS_STD_FMT::make_format_args(m)), - MP_UNITS_STD_FMT::format_error, Catch::Matchers::Message("invalid unit modifier specified")); - } - - SECTION("invalid modifier in the front") - { - REQUIRE_THROWS_MATCHES(MP_UNITS_STD_FMT::vformat("{:xUda}", MP_UNITS_STD_FMT::make_format_args(m)), - MP_UNITS_STD_FMT::format_error, Catch::Matchers::Message("invalid unit modifier specified")); - } - - SECTION("invalid modifier in the end") - { - REQUIRE_THROWS_MATCHES(MP_UNITS_STD_FMT::vformat("{:Udax}", MP_UNITS_STD_FMT::make_format_args(m)), - MP_UNITS_STD_FMT::format_error, Catch::Matchers::Message("invalid unit modifier specified")); - } - - SECTION("invalid modifier in the middle") - { - REQUIRE_THROWS_MATCHES(MP_UNITS_STD_FMT::vformat("{:Udxa}", MP_UNITS_STD_FMT::make_format_args(m)), - MP_UNITS_STD_FMT::format_error, Catch::Matchers::Message("invalid unit modifier specified")); - } -} - -TEST_CASE("repeated unit modifiers should throw", "[text][fmt][exception]") -{ - SECTION("text encoding") - { - REQUIRE_THROWS_MATCHES(MP_UNITS_STD_FMT::vformat("{:UdaU}", MP_UNITS_STD_FMT::make_format_args(m)), - MP_UNITS_STD_FMT::format_error, - Catch::Matchers::Message("only one of 'UAP' unit modifiers may be used in the format spec")); - REQUIRE_THROWS_MATCHES(MP_UNITS_STD_FMT::vformat("{:dUaU}", MP_UNITS_STD_FMT::make_format_args(m)), - MP_UNITS_STD_FMT::format_error, - Catch::Matchers::Message("only one of 'UAP' unit modifiers may be used in the format spec")); - REQUIRE_THROWS_MATCHES(MP_UNITS_STD_FMT::vformat("{:dUUa}", MP_UNITS_STD_FMT::make_format_args(m)), - MP_UNITS_STD_FMT::format_error, - Catch::Matchers::Message("only one of 'UAP' unit modifiers may be used in the format spec")); - } - - SECTION("solidus") - { - REQUIRE_THROWS_MATCHES(MP_UNITS_STD_FMT::vformat("{:aUda}", MP_UNITS_STD_FMT::make_format_args(m)), - MP_UNITS_STD_FMT::format_error, - Catch::Matchers::Message("only one of '1an' unit modifiers may be used in the format spec")); - REQUIRE_THROWS_MATCHES(MP_UNITS_STD_FMT::vformat("{:daUa}", MP_UNITS_STD_FMT::make_format_args(m)), - MP_UNITS_STD_FMT::format_error, - Catch::Matchers::Message("only one of '1an' unit modifiers may be used in the format spec")); - REQUIRE_THROWS_MATCHES(MP_UNITS_STD_FMT::vformat("{:daaU}", MP_UNITS_STD_FMT::make_format_args(m)), - MP_UNITS_STD_FMT::format_error, - Catch::Matchers::Message("only one of '1an' unit modifiers may be used in the format spec")); - } - - SECTION("separator") - { - REQUIRE_THROWS_MATCHES(MP_UNITS_STD_FMT::vformat("{:dUad}", MP_UNITS_STD_FMT::make_format_args(m)), - MP_UNITS_STD_FMT::format_error, - Catch::Matchers::Message("only one of 'sd' unit modifiers may be used in the format spec")); - REQUIRE_THROWS_MATCHES(MP_UNITS_STD_FMT::vformat("{:dadU}", MP_UNITS_STD_FMT::make_format_args(m)), - MP_UNITS_STD_FMT::format_error, - Catch::Matchers::Message("only one of 'sd' unit modifiers may be used in the format spec")); - REQUIRE_THROWS_MATCHES(MP_UNITS_STD_FMT::vformat("{:addU}", MP_UNITS_STD_FMT::make_format_args(m)), - MP_UNITS_STD_FMT::format_error, - Catch::Matchers::Message("only one of 'sd' unit modifiers may be used in the format spec")); - } -} - -TEST_CASE("more then one modifier of the same kind should throw", "[text][fmt][exception]") -{ - SECTION("text encoding") - { - REQUIRE_THROWS_MATCHES(MP_UNITS_STD_FMT::vformat("{:UdaP}", MP_UNITS_STD_FMT::make_format_args(m)), - MP_UNITS_STD_FMT::format_error, - Catch::Matchers::Message("only one of 'UAP' unit modifiers may be used in the format spec")); - REQUIRE_THROWS_MATCHES(MP_UNITS_STD_FMT::vformat("{:dPaU}", MP_UNITS_STD_FMT::make_format_args(m)), - MP_UNITS_STD_FMT::format_error, - Catch::Matchers::Message("only one of 'UAP' unit modifiers may be used in the format spec")); - REQUIRE_THROWS_MATCHES(MP_UNITS_STD_FMT::vformat("{:dPUa}", MP_UNITS_STD_FMT::make_format_args(m)), - MP_UNITS_STD_FMT::format_error, - Catch::Matchers::Message("only one of 'UAP' unit modifiers may be used in the format spec")); - } - - SECTION("solidus") - { - REQUIRE_THROWS_MATCHES(MP_UNITS_STD_FMT::vformat("{:aUdn}", MP_UNITS_STD_FMT::make_format_args(m)), - MP_UNITS_STD_FMT::format_error, - Catch::Matchers::Message("only one of '1an' unit modifiers may be used in the format spec")); - REQUIRE_THROWS_MATCHES(MP_UNITS_STD_FMT::vformat("{:dnUa}", MP_UNITS_STD_FMT::make_format_args(m)), - MP_UNITS_STD_FMT::format_error, - Catch::Matchers::Message("only one of '1an' unit modifiers may be used in the format spec")); - REQUIRE_THROWS_MATCHES(MP_UNITS_STD_FMT::vformat("{:da1U}", MP_UNITS_STD_FMT::make_format_args(m)), - MP_UNITS_STD_FMT::format_error, - Catch::Matchers::Message("only one of '1an' unit modifiers may be used in the format spec")); - } - - SECTION("separator") - { - REQUIRE_THROWS_MATCHES(MP_UNITS_STD_FMT::vformat("{:dUas}", MP_UNITS_STD_FMT::make_format_args(m)), - MP_UNITS_STD_FMT::format_error, - Catch::Matchers::Message("only one of 'sd' unit modifiers may be used in the format spec")); - REQUIRE_THROWS_MATCHES(MP_UNITS_STD_FMT::vformat("{:sadU}", MP_UNITS_STD_FMT::make_format_args(m)), - MP_UNITS_STD_FMT::format_error, - Catch::Matchers::Message("only one of 'sd' unit modifiers may be used in the format spec")); - REQUIRE_THROWS_MATCHES(MP_UNITS_STD_FMT::vformat("{:adsU}", MP_UNITS_STD_FMT::make_format_args(m)), - MP_UNITS_STD_FMT::format_error, - Catch::Matchers::Message("only one of 'sd' unit modifiers may be used in the format spec")); - } -} - -TEST_CASE("half_high_dot separator requested for portable encoding should throw", "[text][fmt][exception]") -{ - REQUIRE_THROWS_MATCHES(MP_UNITS_STD_FMT::vformat("{:dPa}", MP_UNITS_STD_FMT::make_format_args(m)), - MP_UNITS_STD_FMT::format_error, - Catch::Matchers::Message("half_high_dot unit separator allowed only for UTF-8 encoding")); -} - -TEST_CASE("%U and %N can be put anywhere in a format string", "[text][fmt]") -{ - SECTION("no space") { CHECK(MP_UNITS_STD_FMT::format("{:%N%U}", 123 * isq::speed[km / h]) == "123km/h"); } - - SECTION("separator") { CHECK(MP_UNITS_STD_FMT::format("{:%N###%U}", 123 * isq::speed[km / h]) == "123###km/h"); } - - SECTION("opposite order") { CHECK(MP_UNITS_STD_FMT::format("{:%U %N}", 123 * isq::speed[km / h]) == "km/h 123"); } -} - -TEST_CASE("quantity fill and align specification", "[text][fmt][ostream]") +TEST_CASE("quantity fill and align specification", "[quantity][ostream][fmt]") { SECTION("ostream") { @@ -726,356 +731,373 @@ TEST_CASE("quantity fill and align specification", "[text][fmt][ostream]") } } -TEST_CASE("sign specification", "[text][fmt]") +TEST_CASE("quantity subentities selection", "[quantity][fmt]") { - auto inf = std::numeric_limits::infinity() * si::metre; - auto nan = std::numeric_limits::quiet_NaN() * si::metre; + SECTION("quantity format string with only %N should print quantity value only") + { + SECTION("integral representation") + { + SECTION("positive value") { CHECK(MP_UNITS_STD_FMT::format("{:%N}", 123 * isq::speed[km / h]) == "123"); } - SECTION("full format {:%N%?%U} on a quantity") + SECTION("negative value") + { + CHECK(MP_UNITS_STD_FMT::format("{:%N}", 5 * isq::length[m] - 10 * isq::length[m]) == "-5"); + } + } + + SECTION("floating-point representation") + { + SECTION("positive value") + { + CHECK(MP_UNITS_STD_FMT::format("{:%N}", 221. * isq::length[km] / (2 * isq::time[h])) == "110.5"); + } + + SECTION("negative value") + { + CHECK(MP_UNITS_STD_FMT::format("{:%N}", 3.14 * isq::length[m] - 10 * isq::length[m]) == "-6.859999999999999"); + } + + SECTION("nan") + { + CHECK(MP_UNITS_STD_FMT::format("{:%N}", std::numeric_limits::quiet_NaN() * isq::length[m]) == "nan"); + } + + SECTION("inf") + { + CHECK(MP_UNITS_STD_FMT::format("{:%N}", std::numeric_limits::infinity() * isq::length[m]) == "inf"); + } + + SECTION("-inf") + { + CHECK(MP_UNITS_STD_FMT::format("{:%N}", -std::numeric_limits::infinity() * isq::length[m]) == "-inf"); + } + } + } + + SECTION("quantity format string with only %U should print quantity unit symbol only") { - CHECK(MP_UNITS_STD_FMT::format("{0:%N%U},{0:%N%U:N[+]},{0:%N%U:N[-]},{0:%N%U:N[ ]}", 1 * isq::length[m]) == - "1m,+1m,1m, 1m"); - CHECK(MP_UNITS_STD_FMT::format("{0:%N%U},{0:%N%U:N[+]},{0:%N%U:N[-]},{0:%N%U:N[ ]}", -1 * isq::length[m]) == - "-1m,-1m,-1m,-1m"); - CHECK(MP_UNITS_STD_FMT::format("{0:%N%U},{0:%N%U:N[+]},{0:%N%U:N[-]},{0:%N%U:N[ ]}", inf) == - "infm,+infm,infm, infm"); - CHECK(MP_UNITS_STD_FMT::format("{0:%N%U},{0:%N%U:N[+]},{0:%N%U:N[-]},{0:%N%U:N[ ]}", nan) == - "nanm,+nanm,nanm, nanm"); + CHECK(MP_UNITS_STD_FMT::format("{:%U}", 123 * isq::speed[km / h]) == "km/h"); + CHECK(MP_UNITS_STD_FMT::format("{:%U}", 123 * isq::resistance[si::kilo]) == "kΩ"); + CHECK(MP_UNITS_STD_FMT::format("{:%U}", 123 * isq::time[us]) == "µs"); + CHECK(MP_UNITS_STD_FMT::format("{:%U}", 123 * isq::acceleration[m / s2]) == "m/s²"); + CHECK(MP_UNITS_STD_FMT::format("{:%U}", 123 * percent) == "%"); } - SECTION("value only format {:%N} on a quantity") + SECTION("%U and %N can be put anywhere in a format string") { - CHECK(MP_UNITS_STD_FMT::format("{0:%N},{0:%N:N[+]},{0:%N:N[-]},{0:%N:N[ ]}", 1 * isq::length[m]) == "1,+1,1, 1"); - CHECK(MP_UNITS_STD_FMT::format("{0:%N},{0:%N:N[+]},{0:%N:N[-]},{0:%N:N[ ]}", -1 * isq::length[m]) == "-1,-1,-1,-1"); - CHECK(MP_UNITS_STD_FMT::format("{0:%N},{0:%N:N[+]},{0:%N:N[-]},{0:%N:N[ ]}", inf) == "inf,+inf,inf, inf"); - CHECK(MP_UNITS_STD_FMT::format("{0:%N},{0:%N:N[+]},{0:%N:N[-]},{0:%N:N[ ]}", nan) == "nan,+nan,nan, nan"); + SECTION("no space") { CHECK(MP_UNITS_STD_FMT::format("{:%N%U}", 123 * isq::speed[km / h]) == "123km/h"); } + + SECTION("separator") { CHECK(MP_UNITS_STD_FMT::format("{:%N###%U}", 123 * isq::speed[km / h]) == "123###km/h"); } + + SECTION("opposite order") { CHECK(MP_UNITS_STD_FMT::format("{:%U %N}", 123 * isq::speed[km / h]) == "km/h 123"); } } } -TEST_CASE("precision specification", "[text][fmt]") +// TODO provide basic tests if format string when provided in a quantity formatter are passed to respective dimensions +// and units formatters (detail formatting tests for dimensions and units are done separately) + +TEST_CASE("quantity numerical value formatting for `std` arithmetic types", "[quantity][fmt]") { - SECTION("full format on a quantity") + SECTION("sign specification") { - SECTION("default spec") - { - CHECK(MP_UNITS_STD_FMT::format("{::N[.0f]}", 1.2345 * isq::length[m]) == "1 m"); - CHECK(MP_UNITS_STD_FMT::format("{::N[.1f]}", 1.2345 * isq::length[m]) == "1.2 m"); - CHECK(MP_UNITS_STD_FMT::format("{::N[.2f]}", 1.2345 * isq::length[m]) == "1.23 m"); - CHECK(MP_UNITS_STD_FMT::format("{::N[.3f]}", 1.2345 * isq::length[m]) == "1.234 m"); - CHECK(MP_UNITS_STD_FMT::format("{::N[.4f]}", 1.2345 * isq::length[m]) == "1.2345 m"); - CHECK(MP_UNITS_STD_FMT::format("{::N[.5f]}", 1.2345 * isq::length[m]) == "1.23450 m"); - CHECK(MP_UNITS_STD_FMT::format("{::N[.10f]}", 1.2345 * isq::length[m]) == "1.2345000000 m"); - } + auto inf = std::numeric_limits::infinity() * si::metre; + auto nan = std::numeric_limits::quiet_NaN() * si::metre; - SECTION("explicit spec") + SECTION("full format {:%N%?%U} on a quantity") { - CHECK(MP_UNITS_STD_FMT::format("{:%N%?%U:N[.0f]}", 1.2345 * isq::length[m]) == "1 m"); - CHECK(MP_UNITS_STD_FMT::format("{:%N%?%U:N[.1f]}", 1.2345 * isq::length[m]) == "1.2 m"); - CHECK(MP_UNITS_STD_FMT::format("{:%N%?%U:N[.2f]}", 1.2345 * isq::length[m]) == "1.23 m"); - CHECK(MP_UNITS_STD_FMT::format("{:%N%?%U:N[.3f]}", 1.2345 * isq::length[m]) == "1.234 m"); - CHECK(MP_UNITS_STD_FMT::format("{:%N%?%U:N[.4f]}", 1.2345 * isq::length[m]) == "1.2345 m"); - CHECK(MP_UNITS_STD_FMT::format("{:%N%?%U:N[.5f]}", 1.2345 * isq::length[m]) == "1.23450 m"); - CHECK(MP_UNITS_STD_FMT::format("{:%N%?%U:N[.10f]}", 1.2345 * isq::length[m]) == "1.2345000000 m"); + CHECK(MP_UNITS_STD_FMT::format("{0:%N%U},{0:%N%U:N[+]},{0:%N%U:N[-]},{0:%N%U:N[ ]}", 1 * isq::length[m]) == + "1m,+1m,1m, 1m"); + CHECK(MP_UNITS_STD_FMT::format("{0:%N%U},{0:%N%U:N[+]},{0:%N%U:N[-]},{0:%N%U:N[ ]}", -1 * isq::length[m]) == + "-1m,-1m,-1m,-1m"); + CHECK(MP_UNITS_STD_FMT::format("{0:%N%U},{0:%N%U:N[+]},{0:%N%U:N[-]},{0:%N%U:N[ ]}", inf) == + "infm,+infm,infm, infm"); + CHECK(MP_UNITS_STD_FMT::format("{0:%N%U},{0:%N%U:N[+]},{0:%N%U:N[-]},{0:%N%U:N[ ]}", nan) == + "nanm,+nanm,nanm, nanm"); } - SECTION("modified spec") + SECTION("value only format {:%N} on a quantity") { - CHECK(MP_UNITS_STD_FMT::format("{:%N%U:N[.0f]}", 1.2345 * isq::length[m]) == "1m"); - CHECK(MP_UNITS_STD_FMT::format("{:%N%U:N[.1f]}", 1.2345 * isq::length[m]) == "1.2m"); - CHECK(MP_UNITS_STD_FMT::format("{:%N%U:N[.2f]}", 1.2345 * isq::length[m]) == "1.23m"); - CHECK(MP_UNITS_STD_FMT::format("{:%N%U:N[.3f]}", 1.2345 * isq::length[m]) == "1.234m"); - CHECK(MP_UNITS_STD_FMT::format("{:%N%U:N[.4f]}", 1.2345 * isq::length[m]) == "1.2345m"); - CHECK(MP_UNITS_STD_FMT::format("{:%N%U:N[.5f]}", 1.2345 * isq::length[m]) == "1.23450m"); - CHECK(MP_UNITS_STD_FMT::format("{:%N%U:N[.10f]}", 1.2345 * isq::length[m]) == "1.2345000000m"); + CHECK(MP_UNITS_STD_FMT::format("{0:%N},{0:%N:N[+]},{0:%N:N[-]},{0:%N:N[ ]}", 1 * isq::length[m]) == "1,+1,1, 1"); + CHECK(MP_UNITS_STD_FMT::format("{0:%N},{0:%N:N[+]},{0:%N:N[-]},{0:%N:N[ ]}", -1 * isq::length[m]) == + "-1,-1,-1,-1"); + CHECK(MP_UNITS_STD_FMT::format("{0:%N},{0:%N:N[+]},{0:%N:N[-]},{0:%N:N[ ]}", inf) == "inf,+inf,inf, inf"); + CHECK(MP_UNITS_STD_FMT::format("{0:%N},{0:%N:N[+]},{0:%N:N[-]},{0:%N:N[ ]}", nan) == "nan,+nan,nan, nan"); } } - SECTION("value only format {:%N} on a quantity") + SECTION("precision specification") { - CHECK(MP_UNITS_STD_FMT::format("{:%N:N[.0f]}", 1.2345 * isq::length[m]) == "1"); - CHECK(MP_UNITS_STD_FMT::format("{:%N:N[.1f]}", 1.2345 * isq::length[m]) == "1.2"); - CHECK(MP_UNITS_STD_FMT::format("{:%N:N[.2f]}", 1.2345 * isq::length[m]) == "1.23"); - CHECK(MP_UNITS_STD_FMT::format("{:%N:N[.3f]}", 1.2345 * isq::length[m]) == "1.234"); - CHECK(MP_UNITS_STD_FMT::format("{:%N:N[.4f]}", 1.2345 * isq::length[m]) == "1.2345"); - CHECK(MP_UNITS_STD_FMT::format("{:%N:N[.5f]}", 1.2345 * isq::length[m]) == "1.23450"); - CHECK(MP_UNITS_STD_FMT::format("{:%N:N[.10f]}", 1.2345 * isq::length[m]) == "1.2345000000"); + SECTION("full format on a quantity") + { + SECTION("default spec") + { + CHECK(MP_UNITS_STD_FMT::format("{::N[.0f]}", 1.2345 * isq::length[m]) == "1 m"); + CHECK(MP_UNITS_STD_FMT::format("{::N[.1f]}", 1.2345 * isq::length[m]) == "1.2 m"); + CHECK(MP_UNITS_STD_FMT::format("{::N[.2f]}", 1.2345 * isq::length[m]) == "1.23 m"); + CHECK(MP_UNITS_STD_FMT::format("{::N[.3f]}", 1.2345 * isq::length[m]) == "1.234 m"); + CHECK(MP_UNITS_STD_FMT::format("{::N[.4f]}", 1.2345 * isq::length[m]) == "1.2345 m"); + CHECK(MP_UNITS_STD_FMT::format("{::N[.5f]}", 1.2345 * isq::length[m]) == "1.23450 m"); + CHECK(MP_UNITS_STD_FMT::format("{::N[.10f]}", 1.2345 * isq::length[m]) == "1.2345000000 m"); + } + + SECTION("explicit spec") + { + CHECK(MP_UNITS_STD_FMT::format("{:%N%?%U:N[.0f]}", 1.2345 * isq::length[m]) == "1 m"); + CHECK(MP_UNITS_STD_FMT::format("{:%N%?%U:N[.1f]}", 1.2345 * isq::length[m]) == "1.2 m"); + CHECK(MP_UNITS_STD_FMT::format("{:%N%?%U:N[.2f]}", 1.2345 * isq::length[m]) == "1.23 m"); + CHECK(MP_UNITS_STD_FMT::format("{:%N%?%U:N[.3f]}", 1.2345 * isq::length[m]) == "1.234 m"); + CHECK(MP_UNITS_STD_FMT::format("{:%N%?%U:N[.4f]}", 1.2345 * isq::length[m]) == "1.2345 m"); + CHECK(MP_UNITS_STD_FMT::format("{:%N%?%U:N[.5f]}", 1.2345 * isq::length[m]) == "1.23450 m"); + CHECK(MP_UNITS_STD_FMT::format("{:%N%?%U:N[.10f]}", 1.2345 * isq::length[m]) == "1.2345000000 m"); + } + + SECTION("modified spec") + { + CHECK(MP_UNITS_STD_FMT::format("{:%N%U:N[.0f]}", 1.2345 * isq::length[m]) == "1m"); + CHECK(MP_UNITS_STD_FMT::format("{:%N%U:N[.1f]}", 1.2345 * isq::length[m]) == "1.2m"); + CHECK(MP_UNITS_STD_FMT::format("{:%N%U:N[.2f]}", 1.2345 * isq::length[m]) == "1.23m"); + CHECK(MP_UNITS_STD_FMT::format("{:%N%U:N[.3f]}", 1.2345 * isq::length[m]) == "1.234m"); + CHECK(MP_UNITS_STD_FMT::format("{:%N%U:N[.4f]}", 1.2345 * isq::length[m]) == "1.2345m"); + CHECK(MP_UNITS_STD_FMT::format("{:%N%U:N[.5f]}", 1.2345 * isq::length[m]) == "1.23450m"); + CHECK(MP_UNITS_STD_FMT::format("{:%N%U:N[.10f]}", 1.2345 * isq::length[m]) == "1.2345000000m"); + } + } + + SECTION("value only format {:%N} on a quantity") + { + CHECK(MP_UNITS_STD_FMT::format("{:%N:N[.0f]}", 1.2345 * isq::length[m]) == "1"); + CHECK(MP_UNITS_STD_FMT::format("{:%N:N[.1f]}", 1.2345 * isq::length[m]) == "1.2"); + CHECK(MP_UNITS_STD_FMT::format("{:%N:N[.2f]}", 1.2345 * isq::length[m]) == "1.23"); + CHECK(MP_UNITS_STD_FMT::format("{:%N:N[.3f]}", 1.2345 * isq::length[m]) == "1.234"); + CHECK(MP_UNITS_STD_FMT::format("{:%N:N[.4f]}", 1.2345 * isq::length[m]) == "1.2345"); + CHECK(MP_UNITS_STD_FMT::format("{:%N:N[.5f]}", 1.2345 * isq::length[m]) == "1.23450"); + CHECK(MP_UNITS_STD_FMT::format("{:%N:N[.10f]}", 1.2345 * isq::length[m]) == "1.2345000000"); + } } -} -TEST_CASE("type specification", "[text][fmt]") -{ - SECTION("full format {:%N%?%U} on a quantity") + SECTION("type specification") { - SECTION("default spec") + SECTION("full format {:%N%?%U} on a quantity") { - CHECK(MP_UNITS_STD_FMT::format("{::N[b]}", 42 * isq::length[m]) == "101010 m"); - CHECK(MP_UNITS_STD_FMT::format("{::N[B]}", 42 * isq::length[m]) == "101010 m"); - CHECK(MP_UNITS_STD_FMT::format("{::N[d]}", 42 * isq::length[m]) == "42 m"); - CHECK(MP_UNITS_STD_FMT::format("{::N[o]}", 42 * isq::length[m]) == "52 m"); - CHECK(MP_UNITS_STD_FMT::format("{::N[x]}", 42 * isq::length[m]) == "2a m"); - CHECK(MP_UNITS_STD_FMT::format("{::N[X]}", 42 * isq::length[m]) == "2A m"); + SECTION("default spec") + { + CHECK(MP_UNITS_STD_FMT::format("{::N[b]}", 42 * isq::length[m]) == "101010 m"); + CHECK(MP_UNITS_STD_FMT::format("{::N[B]}", 42 * isq::length[m]) == "101010 m"); + CHECK(MP_UNITS_STD_FMT::format("{::N[d]}", 42 * isq::length[m]) == "42 m"); + CHECK(MP_UNITS_STD_FMT::format("{::N[o]}", 42 * isq::length[m]) == "52 m"); + CHECK(MP_UNITS_STD_FMT::format("{::N[x]}", 42 * isq::length[m]) == "2a m"); + CHECK(MP_UNITS_STD_FMT::format("{::N[X]}", 42 * isq::length[m]) == "2A m"); #if MP_UNITS_USE_FMTLIB - CHECK(MP_UNITS_STD_FMT::format("{::N[a]}", 1.2345678 * isq::length[m]) == "0x1.3c0ca2a5b1d5dp+0 m"); - CHECK(MP_UNITS_STD_FMT::format("{::N[.3a]}", 1.2345678 * isq::length[m]) == "0x1.3c1p+0 m"); - CHECK(MP_UNITS_STD_FMT::format("{::N[A]}", 1.2345678 * isq::length[m]) == "0X1.3C0CA2A5B1D5DP+0 m"); - CHECK(MP_UNITS_STD_FMT::format("{::N[.3A]}", 1.2345678 * isq::length[m]) == "0X1.3C1P+0 m"); + CHECK(MP_UNITS_STD_FMT::format("{::N[a]}", 1.2345678 * isq::length[m]) == "0x1.3c0ca2a5b1d5dp+0 m"); + CHECK(MP_UNITS_STD_FMT::format("{::N[.3a]}", 1.2345678 * isq::length[m]) == "0x1.3c1p+0 m"); + CHECK(MP_UNITS_STD_FMT::format("{::N[A]}", 1.2345678 * isq::length[m]) == "0X1.3C0CA2A5B1D5DP+0 m"); + CHECK(MP_UNITS_STD_FMT::format("{::N[.3A]}", 1.2345678 * isq::length[m]) == "0X1.3C1P+0 m"); #else - CHECK(MP_UNITS_STD_FMT::format("{::N[a]}", 1.2345678 * isq::length[m]) == "1.3c0ca2a5b1d5dp+0 m"); - CHECK(MP_UNITS_STD_FMT::format("{::N[.3a]}", 1.2345678 * isq::length[m]) == "1.3c1p+0 m"); - CHECK(MP_UNITS_STD_FMT::format("{::N[A]}", 1.2345678 * isq::length[m]) == "1.3C0CA2A5B1D5DP+0 m"); - CHECK(MP_UNITS_STD_FMT::format("{::N[.3A]}", 1.2345678 * isq::length[m]) == "1.3C1P+0 m"); + CHECK(MP_UNITS_STD_FMT::format("{::N[a]}", 1.2345678 * isq::length[m]) == "1.3c0ca2a5b1d5dp+0 m"); + CHECK(MP_UNITS_STD_FMT::format("{::N[.3a]}", 1.2345678 * isq::length[m]) == "1.3c1p+0 m"); + CHECK(MP_UNITS_STD_FMT::format("{::N[A]}", 1.2345678 * isq::length[m]) == "1.3C0CA2A5B1D5DP+0 m"); + CHECK(MP_UNITS_STD_FMT::format("{::N[.3A]}", 1.2345678 * isq::length[m]) == "1.3C1P+0 m"); #endif - CHECK(MP_UNITS_STD_FMT::format("{::N[e]}", 1.2345678 * isq::length[m]) == "1.234568e+00 m"); - CHECK(MP_UNITS_STD_FMT::format("{::N[.3e]}", 1.2345678 * isq::length[m]) == "1.235e+00 m"); - CHECK(MP_UNITS_STD_FMT::format("{::N[E]}", 1.2345678 * isq::length[m]) == "1.234568E+00 m"); - CHECK(MP_UNITS_STD_FMT::format("{::N[.3E]}", 1.2345678 * isq::length[m]) == "1.235E+00 m"); - CHECK(MP_UNITS_STD_FMT::format("{::N[g]}", 1.2345678 * isq::length[m]) == "1.23457 m"); - CHECK(MP_UNITS_STD_FMT::format("{::N[g]}", 1.2345678e8 * isq::length[m]) == "1.23457e+08 m"); - CHECK(MP_UNITS_STD_FMT::format("{::N[.3g]}", 1.2345678 * isq::length[m]) == "1.23 m"); - CHECK(MP_UNITS_STD_FMT::format("{::N[.3g]}", 1.2345678e8 * isq::length[m]) == "1.23e+08 m"); - CHECK(MP_UNITS_STD_FMT::format("{::N[G]}", 1.2345678 * isq::length[m]) == "1.23457 m"); - CHECK(MP_UNITS_STD_FMT::format("{::N[G]}", 1.2345678e8 * isq::length[m]) == "1.23457E+08 m"); - CHECK(MP_UNITS_STD_FMT::format("{::N[.3G]}", 1.2345678 * isq::length[m]) == "1.23 m"); - CHECK(MP_UNITS_STD_FMT::format("{::N[.3G]}", 1.2345678e8 * isq::length[m]) == "1.23E+08 m"); - } + CHECK(MP_UNITS_STD_FMT::format("{::N[e]}", 1.2345678 * isq::length[m]) == "1.234568e+00 m"); + CHECK(MP_UNITS_STD_FMT::format("{::N[.3e]}", 1.2345678 * isq::length[m]) == "1.235e+00 m"); + CHECK(MP_UNITS_STD_FMT::format("{::N[E]}", 1.2345678 * isq::length[m]) == "1.234568E+00 m"); + CHECK(MP_UNITS_STD_FMT::format("{::N[.3E]}", 1.2345678 * isq::length[m]) == "1.235E+00 m"); + CHECK(MP_UNITS_STD_FMT::format("{::N[g]}", 1.2345678 * isq::length[m]) == "1.23457 m"); + CHECK(MP_UNITS_STD_FMT::format("{::N[g]}", 1.2345678e8 * isq::length[m]) == "1.23457e+08 m"); + CHECK(MP_UNITS_STD_FMT::format("{::N[.3g]}", 1.2345678 * isq::length[m]) == "1.23 m"); + CHECK(MP_UNITS_STD_FMT::format("{::N[.3g]}", 1.2345678e8 * isq::length[m]) == "1.23e+08 m"); + CHECK(MP_UNITS_STD_FMT::format("{::N[G]}", 1.2345678 * isq::length[m]) == "1.23457 m"); + CHECK(MP_UNITS_STD_FMT::format("{::N[G]}", 1.2345678e8 * isq::length[m]) == "1.23457E+08 m"); + CHECK(MP_UNITS_STD_FMT::format("{::N[.3G]}", 1.2345678 * isq::length[m]) == "1.23 m"); + CHECK(MP_UNITS_STD_FMT::format("{::N[.3G]}", 1.2345678e8 * isq::length[m]) == "1.23E+08 m"); + } - SECTION("explicit spec") - { - CHECK(MP_UNITS_STD_FMT::format("{:%N%?%U:N[b]}", 42 * isq::length[m]) == "101010 m"); - CHECK(MP_UNITS_STD_FMT::format("{:%N%?%U:N[B]}", 42 * isq::length[m]) == "101010 m"); - CHECK(MP_UNITS_STD_FMT::format("{:%N%?%U:N[d]}", 42 * isq::length[m]) == "42 m"); - CHECK(MP_UNITS_STD_FMT::format("{:%N%?%U:N[o]}", 42 * isq::length[m]) == "52 m"); - CHECK(MP_UNITS_STD_FMT::format("{:%N%?%U:N[x]}", 42 * isq::length[m]) == "2a m"); - CHECK(MP_UNITS_STD_FMT::format("{:%N%?%U:N[X]}", 42 * isq::length[m]) == "2A m"); + SECTION("explicit spec") + { + CHECK(MP_UNITS_STD_FMT::format("{:%N%?%U:N[b]}", 42 * isq::length[m]) == "101010 m"); + CHECK(MP_UNITS_STD_FMT::format("{:%N%?%U:N[B]}", 42 * isq::length[m]) == "101010 m"); + CHECK(MP_UNITS_STD_FMT::format("{:%N%?%U:N[d]}", 42 * isq::length[m]) == "42 m"); + CHECK(MP_UNITS_STD_FMT::format("{:%N%?%U:N[o]}", 42 * isq::length[m]) == "52 m"); + CHECK(MP_UNITS_STD_FMT::format("{:%N%?%U:N[x]}", 42 * isq::length[m]) == "2a m"); + CHECK(MP_UNITS_STD_FMT::format("{:%N%?%U:N[X]}", 42 * isq::length[m]) == "2A m"); #if MP_UNITS_USE_FMTLIB - CHECK(MP_UNITS_STD_FMT::format("{:%N%?%U:N[a]}", 1.2345678 * isq::length[m]) == "0x1.3c0ca2a5b1d5dp+0 m"); - CHECK(MP_UNITS_STD_FMT::format("{:%N%?%U:N[.3a]}", 1.2345678 * isq::length[m]) == "0x1.3c1p+0 m"); - CHECK(MP_UNITS_STD_FMT::format("{:%N%?%U:N[A]}", 1.2345678 * isq::length[m]) == "0X1.3C0CA2A5B1D5DP+0 m"); - CHECK(MP_UNITS_STD_FMT::format("{:%N%?%U:N[.3A]}", 1.2345678 * isq::length[m]) == "0X1.3C1P+0 m"); + CHECK(MP_UNITS_STD_FMT::format("{:%N%?%U:N[a]}", 1.2345678 * isq::length[m]) == "0x1.3c0ca2a5b1d5dp+0 m"); + CHECK(MP_UNITS_STD_FMT::format("{:%N%?%U:N[.3a]}", 1.2345678 * isq::length[m]) == "0x1.3c1p+0 m"); + CHECK(MP_UNITS_STD_FMT::format("{:%N%?%U:N[A]}", 1.2345678 * isq::length[m]) == "0X1.3C0CA2A5B1D5DP+0 m"); + CHECK(MP_UNITS_STD_FMT::format("{:%N%?%U:N[.3A]}", 1.2345678 * isq::length[m]) == "0X1.3C1P+0 m"); #else - CHECK(MP_UNITS_STD_FMT::format("{:%N%?%U:N[a]}", 1.2345678 * isq::length[m]) == "1.3c0ca2a5b1d5dp+0 m"); - CHECK(MP_UNITS_STD_FMT::format("{:%N%?%U:N[.3a]}", 1.2345678 * isq::length[m]) == "1.3c1p+0 m"); - CHECK(MP_UNITS_STD_FMT::format("{:%N%?%U:N[A]}", 1.2345678 * isq::length[m]) == "1.3C0CA2A5B1D5DP+0 m"); - CHECK(MP_UNITS_STD_FMT::format("{:%N%?%U:N[.3A]}", 1.2345678 * isq::length[m]) == "1.3C1P+0 m"); + CHECK(MP_UNITS_STD_FMT::format("{:%N%?%U:N[a]}", 1.2345678 * isq::length[m]) == "1.3c0ca2a5b1d5dp+0 m"); + CHECK(MP_UNITS_STD_FMT::format("{:%N%?%U:N[.3a]}", 1.2345678 * isq::length[m]) == "1.3c1p+0 m"); + CHECK(MP_UNITS_STD_FMT::format("{:%N%?%U:N[A]}", 1.2345678 * isq::length[m]) == "1.3C0CA2A5B1D5DP+0 m"); + CHECK(MP_UNITS_STD_FMT::format("{:%N%?%U:N[.3A]}", 1.2345678 * isq::length[m]) == "1.3C1P+0 m"); #endif - CHECK(MP_UNITS_STD_FMT::format("{:%N%?%U:N[e]}", 1.2345678 * isq::length[m]) == "1.234568e+00 m"); - CHECK(MP_UNITS_STD_FMT::format("{:%N%?%U:N[.3e]}", 1.2345678 * isq::length[m]) == "1.235e+00 m"); - CHECK(MP_UNITS_STD_FMT::format("{:%N%?%U:N[E]}", 1.2345678 * isq::length[m]) == "1.234568E+00 m"); - CHECK(MP_UNITS_STD_FMT::format("{:%N%?%U:N[.3E]}", 1.2345678 * isq::length[m]) == "1.235E+00 m"); - CHECK(MP_UNITS_STD_FMT::format("{:%N%?%U:N[g]}", 1.2345678 * isq::length[m]) == "1.23457 m"); - CHECK(MP_UNITS_STD_FMT::format("{:%N%?%U:N[g]}", 1.2345678e8 * isq::length[m]) == "1.23457e+08 m"); - CHECK(MP_UNITS_STD_FMT::format("{:%N%?%U:N[.3g]}", 1.2345678 * isq::length[m]) == "1.23 m"); - CHECK(MP_UNITS_STD_FMT::format("{:%N%?%U:N[.3g]}", 1.2345678e8 * isq::length[m]) == "1.23e+08 m"); - CHECK(MP_UNITS_STD_FMT::format("{:%N%?%U:N[G]}", 1.2345678 * isq::length[m]) == "1.23457 m"); - CHECK(MP_UNITS_STD_FMT::format("{:%N%?%U:N[G]}", 1.2345678e8 * isq::length[m]) == "1.23457E+08 m"); - CHECK(MP_UNITS_STD_FMT::format("{:%N%?%U:N[.3G]}", 1.2345678 * isq::length[m]) == "1.23 m"); - CHECK(MP_UNITS_STD_FMT::format("{:%N%?%U:N[.3G]}", 1.2345678e8 * isq::length[m]) == "1.23E+08 m"); - } + CHECK(MP_UNITS_STD_FMT::format("{:%N%?%U:N[e]}", 1.2345678 * isq::length[m]) == "1.234568e+00 m"); + CHECK(MP_UNITS_STD_FMT::format("{:%N%?%U:N[.3e]}", 1.2345678 * isq::length[m]) == "1.235e+00 m"); + CHECK(MP_UNITS_STD_FMT::format("{:%N%?%U:N[E]}", 1.2345678 * isq::length[m]) == "1.234568E+00 m"); + CHECK(MP_UNITS_STD_FMT::format("{:%N%?%U:N[.3E]}", 1.2345678 * isq::length[m]) == "1.235E+00 m"); + CHECK(MP_UNITS_STD_FMT::format("{:%N%?%U:N[g]}", 1.2345678 * isq::length[m]) == "1.23457 m"); + CHECK(MP_UNITS_STD_FMT::format("{:%N%?%U:N[g]}", 1.2345678e8 * isq::length[m]) == "1.23457e+08 m"); + CHECK(MP_UNITS_STD_FMT::format("{:%N%?%U:N[.3g]}", 1.2345678 * isq::length[m]) == "1.23 m"); + CHECK(MP_UNITS_STD_FMT::format("{:%N%?%U:N[.3g]}", 1.2345678e8 * isq::length[m]) == "1.23e+08 m"); + CHECK(MP_UNITS_STD_FMT::format("{:%N%?%U:N[G]}", 1.2345678 * isq::length[m]) == "1.23457 m"); + CHECK(MP_UNITS_STD_FMT::format("{:%N%?%U:N[G]}", 1.2345678e8 * isq::length[m]) == "1.23457E+08 m"); + CHECK(MP_UNITS_STD_FMT::format("{:%N%?%U:N[.3G]}", 1.2345678 * isq::length[m]) == "1.23 m"); + CHECK(MP_UNITS_STD_FMT::format("{:%N%?%U:N[.3G]}", 1.2345678e8 * isq::length[m]) == "1.23E+08 m"); + } - SECTION("modified spec") - { - CHECK(MP_UNITS_STD_FMT::format("{:%N%U:N[b]}", 42 * isq::length[m]) == "101010m"); - CHECK(MP_UNITS_STD_FMT::format("{:%N%U:N[B]}", 42 * isq::length[m]) == "101010m"); - CHECK(MP_UNITS_STD_FMT::format("{:%N%U:N[d]}", 42 * isq::length[m]) == "42m"); - CHECK(MP_UNITS_STD_FMT::format("{:%N%U:N[o]}", 42 * isq::length[m]) == "52m"); - CHECK(MP_UNITS_STD_FMT::format("{:%N%U:N[x]}", 42 * isq::length[m]) == "2am"); - CHECK(MP_UNITS_STD_FMT::format("{:%N%U:N[X]}", 42 * isq::length[m]) == "2Am"); + SECTION("modified spec") + { + CHECK(MP_UNITS_STD_FMT::format("{:%N%U:N[b]}", 42 * isq::length[m]) == "101010m"); + CHECK(MP_UNITS_STD_FMT::format("{:%N%U:N[B]}", 42 * isq::length[m]) == "101010m"); + CHECK(MP_UNITS_STD_FMT::format("{:%N%U:N[d]}", 42 * isq::length[m]) == "42m"); + CHECK(MP_UNITS_STD_FMT::format("{:%N%U:N[o]}", 42 * isq::length[m]) == "52m"); + CHECK(MP_UNITS_STD_FMT::format("{:%N%U:N[x]}", 42 * isq::length[m]) == "2am"); + CHECK(MP_UNITS_STD_FMT::format("{:%N%U:N[X]}", 42 * isq::length[m]) == "2Am"); #if MP_UNITS_USE_FMTLIB - CHECK(MP_UNITS_STD_FMT::format("{:%N%U:N[a]}", 1.2345678 * isq::length[m]) == "0x1.3c0ca2a5b1d5dp+0m"); - CHECK(MP_UNITS_STD_FMT::format("{:%N%U:N[.3a]}", 1.2345678 * isq::length[m]) == "0x1.3c1p+0m"); - CHECK(MP_UNITS_STD_FMT::format("{:%N%U:N[A]}", 1.2345678 * isq::length[m]) == "0X1.3C0CA2A5B1D5DP+0m"); - CHECK(MP_UNITS_STD_FMT::format("{:%N%U:N[.3A]}", 1.2345678 * isq::length[m]) == "0X1.3C1P+0m"); + CHECK(MP_UNITS_STD_FMT::format("{:%N%U:N[a]}", 1.2345678 * isq::length[m]) == "0x1.3c0ca2a5b1d5dp+0m"); + CHECK(MP_UNITS_STD_FMT::format("{:%N%U:N[.3a]}", 1.2345678 * isq::length[m]) == "0x1.3c1p+0m"); + CHECK(MP_UNITS_STD_FMT::format("{:%N%U:N[A]}", 1.2345678 * isq::length[m]) == "0X1.3C0CA2A5B1D5DP+0m"); + CHECK(MP_UNITS_STD_FMT::format("{:%N%U:N[.3A]}", 1.2345678 * isq::length[m]) == "0X1.3C1P+0m"); #else - CHECK(MP_UNITS_STD_FMT::format("{:%N%U:N[a]}", 1.2345678 * isq::length[m]) == "1.3c0ca2a5b1d5dp+0m"); - CHECK(MP_UNITS_STD_FMT::format("{:%N%U:N[.3a]}", 1.2345678 * isq::length[m]) == "1.3c1p+0m"); - CHECK(MP_UNITS_STD_FMT::format("{:%N%U:N[A]}", 1.2345678 * isq::length[m]) == "1.3C0CA2A5B1D5DP+0m"); - CHECK(MP_UNITS_STD_FMT::format("{:%N%U:N[.3A]}", 1.2345678 * isq::length[m]) == "1.3C1P+0m"); + CHECK(MP_UNITS_STD_FMT::format("{:%N%U:N[a]}", 1.2345678 * isq::length[m]) == "1.3c0ca2a5b1d5dp+0m"); + CHECK(MP_UNITS_STD_FMT::format("{:%N%U:N[.3a]}", 1.2345678 * isq::length[m]) == "1.3c1p+0m"); + CHECK(MP_UNITS_STD_FMT::format("{:%N%U:N[A]}", 1.2345678 * isq::length[m]) == "1.3C0CA2A5B1D5DP+0m"); + CHECK(MP_UNITS_STD_FMT::format("{:%N%U:N[.3A]}", 1.2345678 * isq::length[m]) == "1.3C1P+0m"); #endif - CHECK(MP_UNITS_STD_FMT::format("{:%N%U:N[e]}", 1.2345678 * isq::length[m]) == "1.234568e+00m"); - CHECK(MP_UNITS_STD_FMT::format("{:%N%U:N[.3e]}", 1.2345678 * isq::length[m]) == "1.235e+00m"); - CHECK(MP_UNITS_STD_FMT::format("{:%N%U:N[E]}", 1.2345678 * isq::length[m]) == "1.234568E+00m"); - CHECK(MP_UNITS_STD_FMT::format("{:%N%U:N[.3E]}", 1.2345678 * isq::length[m]) == "1.235E+00m"); - CHECK(MP_UNITS_STD_FMT::format("{:%N%U:N[g]}", 1.2345678 * isq::length[m]) == "1.23457m"); - CHECK(MP_UNITS_STD_FMT::format("{:%N%U:N[g]}", 1.2345678e8 * isq::length[m]) == "1.23457e+08m"); - CHECK(MP_UNITS_STD_FMT::format("{:%N%U:N[.3g]}", 1.2345678 * isq::length[m]) == "1.23m"); - CHECK(MP_UNITS_STD_FMT::format("{:%N%U:N[.3g]}", 1.2345678e8 * isq::length[m]) == "1.23e+08m"); - CHECK(MP_UNITS_STD_FMT::format("{:%N%U:N[G]}", 1.2345678 * isq::length[m]) == "1.23457m"); - CHECK(MP_UNITS_STD_FMT::format("{:%N%U:N[G]}", 1.2345678e8 * isq::length[m]) == "1.23457E+08m"); - CHECK(MP_UNITS_STD_FMT::format("{:%N%U:N[.3G]}", 1.2345678 * isq::length[m]) == "1.23m"); - CHECK(MP_UNITS_STD_FMT::format("{:%N%U:N[.3G]}", 1.2345678e8 * isq::length[m]) == "1.23E+08m"); + CHECK(MP_UNITS_STD_FMT::format("{:%N%U:N[e]}", 1.2345678 * isq::length[m]) == "1.234568e+00m"); + CHECK(MP_UNITS_STD_FMT::format("{:%N%U:N[.3e]}", 1.2345678 * isq::length[m]) == "1.235e+00m"); + CHECK(MP_UNITS_STD_FMT::format("{:%N%U:N[E]}", 1.2345678 * isq::length[m]) == "1.234568E+00m"); + CHECK(MP_UNITS_STD_FMT::format("{:%N%U:N[.3E]}", 1.2345678 * isq::length[m]) == "1.235E+00m"); + CHECK(MP_UNITS_STD_FMT::format("{:%N%U:N[g]}", 1.2345678 * isq::length[m]) == "1.23457m"); + CHECK(MP_UNITS_STD_FMT::format("{:%N%U:N[g]}", 1.2345678e8 * isq::length[m]) == "1.23457e+08m"); + CHECK(MP_UNITS_STD_FMT::format("{:%N%U:N[.3g]}", 1.2345678 * isq::length[m]) == "1.23m"); + CHECK(MP_UNITS_STD_FMT::format("{:%N%U:N[.3g]}", 1.2345678e8 * isq::length[m]) == "1.23e+08m"); + CHECK(MP_UNITS_STD_FMT::format("{:%N%U:N[G]}", 1.2345678 * isq::length[m]) == "1.23457m"); + CHECK(MP_UNITS_STD_FMT::format("{:%N%U:N[G]}", 1.2345678e8 * isq::length[m]) == "1.23457E+08m"); + CHECK(MP_UNITS_STD_FMT::format("{:%N%U:N[.3G]}", 1.2345678 * isq::length[m]) == "1.23m"); + CHECK(MP_UNITS_STD_FMT::format("{:%N%U:N[.3G]}", 1.2345678e8 * isq::length[m]) == "1.23E+08m"); + } } - } - SECTION("value only format {:%N} on a quantity") - { - CHECK(MP_UNITS_STD_FMT::format("{:%N:N[b]}", 42 * isq::length[m]) == "101010"); - CHECK(MP_UNITS_STD_FMT::format("{:%N:N[B]}", 42 * isq::length[m]) == "101010"); - CHECK(MP_UNITS_STD_FMT::format("{:%N:N[d]}", 42 * isq::length[m]) == "42"); - CHECK(MP_UNITS_STD_FMT::format("{:%N:N[o]}", 42 * isq::length[m]) == "52"); - CHECK(MP_UNITS_STD_FMT::format("{:%N:N[x]}", 42 * isq::length[m]) == "2a"); - CHECK(MP_UNITS_STD_FMT::format("{:%N:N[X]}", 42 * isq::length[m]) == "2A"); + SECTION("value only format {:%N} on a quantity") + { + CHECK(MP_UNITS_STD_FMT::format("{:%N:N[b]}", 42 * isq::length[m]) == "101010"); + CHECK(MP_UNITS_STD_FMT::format("{:%N:N[B]}", 42 * isq::length[m]) == "101010"); + CHECK(MP_UNITS_STD_FMT::format("{:%N:N[d]}", 42 * isq::length[m]) == "42"); + CHECK(MP_UNITS_STD_FMT::format("{:%N:N[o]}", 42 * isq::length[m]) == "52"); + CHECK(MP_UNITS_STD_FMT::format("{:%N:N[x]}", 42 * isq::length[m]) == "2a"); + CHECK(MP_UNITS_STD_FMT::format("{:%N:N[X]}", 42 * isq::length[m]) == "2A"); #if MP_UNITS_USE_FMTLIB - CHECK(MP_UNITS_STD_FMT::format("{:%N:N[a]}", 1.2345678 * isq::length[m]) == "0x1.3c0ca2a5b1d5dp+0"); - CHECK(MP_UNITS_STD_FMT::format("{:%N:N[.3a]}", 1.2345678 * isq::length[m]) == "0x1.3c1p+0"); - CHECK(MP_UNITS_STD_FMT::format("{:%N:N[A]}", 1.2345678 * isq::length[m]) == "0X1.3C0CA2A5B1D5DP+0"); - CHECK(MP_UNITS_STD_FMT::format("{:%N:N[.3A]}", 1.2345678 * isq::length[m]) == "0X1.3C1P+0"); + CHECK(MP_UNITS_STD_FMT::format("{:%N:N[a]}", 1.2345678 * isq::length[m]) == "0x1.3c0ca2a5b1d5dp+0"); + CHECK(MP_UNITS_STD_FMT::format("{:%N:N[.3a]}", 1.2345678 * isq::length[m]) == "0x1.3c1p+0"); + CHECK(MP_UNITS_STD_FMT::format("{:%N:N[A]}", 1.2345678 * isq::length[m]) == "0X1.3C0CA2A5B1D5DP+0"); + CHECK(MP_UNITS_STD_FMT::format("{:%N:N[.3A]}", 1.2345678 * isq::length[m]) == "0X1.3C1P+0"); #else - CHECK(MP_UNITS_STD_FMT::format("{:%N:N[a]}", 1.2345678 * isq::length[m]) == "1.3c0ca2a5b1d5dp+0"); - CHECK(MP_UNITS_STD_FMT::format("{:%N:N[.3a]}", 1.2345678 * isq::length[m]) == "1.3c1p+0"); - CHECK(MP_UNITS_STD_FMT::format("{:%N:N[A]}", 1.2345678 * isq::length[m]) == "1.3C0CA2A5B1D5DP+0"); - CHECK(MP_UNITS_STD_FMT::format("{:%N:N[.3A]}", 1.2345678 * isq::length[m]) == "1.3C1P+0"); + CHECK(MP_UNITS_STD_FMT::format("{:%N:N[a]}", 1.2345678 * isq::length[m]) == "1.3c0ca2a5b1d5dp+0"); + CHECK(MP_UNITS_STD_FMT::format("{:%N:N[.3a]}", 1.2345678 * isq::length[m]) == "1.3c1p+0"); + CHECK(MP_UNITS_STD_FMT::format("{:%N:N[A]}", 1.2345678 * isq::length[m]) == "1.3C0CA2A5B1D5DP+0"); + CHECK(MP_UNITS_STD_FMT::format("{:%N:N[.3A]}", 1.2345678 * isq::length[m]) == "1.3C1P+0"); #endif - CHECK(MP_UNITS_STD_FMT::format("{:%N:N[e]}", 1.2345678 * isq::length[m]) == "1.234568e+00"); - CHECK(MP_UNITS_STD_FMT::format("{:%N:N[.3e]}", 1.2345678 * isq::length[m]) == "1.235e+00"); - CHECK(MP_UNITS_STD_FMT::format("{:%N:N[E]}", 1.2345678 * isq::length[m]) == "1.234568E+00"); - CHECK(MP_UNITS_STD_FMT::format("{:%N:N[.3E]}", 1.2345678 * isq::length[m]) == "1.235E+00"); - CHECK(MP_UNITS_STD_FMT::format("{:%N:N[g]}", 1.2345678 * isq::length[m]) == "1.23457"); - CHECK(MP_UNITS_STD_FMT::format("{:%N:N[g]}", 1.2345678e8 * isq::length[m]) == "1.23457e+08"); - CHECK(MP_UNITS_STD_FMT::format("{:%N:N[.3g]}", 1.2345678 * isq::length[m]) == "1.23"); - CHECK(MP_UNITS_STD_FMT::format("{:%N:N[.3g]}", 1.2345678e8 * isq::length[m]) == "1.23e+08"); - CHECK(MP_UNITS_STD_FMT::format("{:%N:N[G]}", 1.2345678 * isq::length[m]) == "1.23457"); - CHECK(MP_UNITS_STD_FMT::format("{:%N:N[G]}", 1.2345678e8 * isq::length[m]) == "1.23457E+08"); - CHECK(MP_UNITS_STD_FMT::format("{:%N:N[.3G]}", 1.2345678 * isq::length[m]) == "1.23"); - CHECK(MP_UNITS_STD_FMT::format("{:%N:N[.3G]}", 1.2345678e8 * isq::length[m]) == "1.23E+08"); + CHECK(MP_UNITS_STD_FMT::format("{:%N:N[e]}", 1.2345678 * isq::length[m]) == "1.234568e+00"); + CHECK(MP_UNITS_STD_FMT::format("{:%N:N[.3e]}", 1.2345678 * isq::length[m]) == "1.235e+00"); + CHECK(MP_UNITS_STD_FMT::format("{:%N:N[E]}", 1.2345678 * isq::length[m]) == "1.234568E+00"); + CHECK(MP_UNITS_STD_FMT::format("{:%N:N[.3E]}", 1.2345678 * isq::length[m]) == "1.235E+00"); + CHECK(MP_UNITS_STD_FMT::format("{:%N:N[g]}", 1.2345678 * isq::length[m]) == "1.23457"); + CHECK(MP_UNITS_STD_FMT::format("{:%N:N[g]}", 1.2345678e8 * isq::length[m]) == "1.23457e+08"); + CHECK(MP_UNITS_STD_FMT::format("{:%N:N[.3g]}", 1.2345678 * isq::length[m]) == "1.23"); + CHECK(MP_UNITS_STD_FMT::format("{:%N:N[.3g]}", 1.2345678e8 * isq::length[m]) == "1.23e+08"); + CHECK(MP_UNITS_STD_FMT::format("{:%N:N[G]}", 1.2345678 * isq::length[m]) == "1.23457"); + CHECK(MP_UNITS_STD_FMT::format("{:%N:N[G]}", 1.2345678e8 * isq::length[m]) == "1.23457E+08"); + CHECK(MP_UNITS_STD_FMT::format("{:%N:N[.3G]}", 1.2345678 * isq::length[m]) == "1.23"); + CHECK(MP_UNITS_STD_FMT::format("{:%N:N[.3G]}", 1.2345678e8 * isq::length[m]) == "1.23E+08"); + } } -} -TEST_CASE("different base types with the # specifier", "[text][fmt]") -{ - SECTION("full format {:%N%?%U} on a quantity") + SECTION("different base types with the # specifier") { - SECTION("default spec") + SECTION("full format {:%N%?%U} on a quantity") { - CHECK(MP_UNITS_STD_FMT::format("{::N[#b]}", 42 * isq::length[m]) == "0b101010 m"); - CHECK(MP_UNITS_STD_FMT::format("{::N[#B]}", 42 * isq::length[m]) == "0B101010 m"); - CHECK(MP_UNITS_STD_FMT::format("{::N[#o]}", 42 * isq::length[m]) == "052 m"); - CHECK(MP_UNITS_STD_FMT::format("{::N[#x]}", 42 * isq::length[m]) == "0x2a m"); - CHECK(MP_UNITS_STD_FMT::format("{::N[#X]}", 42 * isq::length[m]) == "0X2A m"); - } + SECTION("default spec") + { + CHECK(MP_UNITS_STD_FMT::format("{::N[#b]}", 42 * isq::length[m]) == "0b101010 m"); + CHECK(MP_UNITS_STD_FMT::format("{::N[#B]}", 42 * isq::length[m]) == "0B101010 m"); + CHECK(MP_UNITS_STD_FMT::format("{::N[#o]}", 42 * isq::length[m]) == "052 m"); + CHECK(MP_UNITS_STD_FMT::format("{::N[#x]}", 42 * isq::length[m]) == "0x2a m"); + CHECK(MP_UNITS_STD_FMT::format("{::N[#X]}", 42 * isq::length[m]) == "0X2A m"); + } - SECTION("explicit spec") - { - CHECK(MP_UNITS_STD_FMT::format("{:%N%?%U:N[#b]}", 42 * isq::length[m]) == "0b101010 m"); - CHECK(MP_UNITS_STD_FMT::format("{:%N%?%U:N[#B]}", 42 * isq::length[m]) == "0B101010 m"); - CHECK(MP_UNITS_STD_FMT::format("{:%N%?%U:N[#o]}", 42 * isq::length[m]) == "052 m"); - CHECK(MP_UNITS_STD_FMT::format("{:%N%?%U:N[#x]}", 42 * isq::length[m]) == "0x2a m"); - CHECK(MP_UNITS_STD_FMT::format("{:%N%?%U:N[#X]}", 42 * isq::length[m]) == "0X2A m"); + SECTION("explicit spec") + { + CHECK(MP_UNITS_STD_FMT::format("{:%N%?%U:N[#b]}", 42 * isq::length[m]) == "0b101010 m"); + CHECK(MP_UNITS_STD_FMT::format("{:%N%?%U:N[#B]}", 42 * isq::length[m]) == "0B101010 m"); + CHECK(MP_UNITS_STD_FMT::format("{:%N%?%U:N[#o]}", 42 * isq::length[m]) == "052 m"); + CHECK(MP_UNITS_STD_FMT::format("{:%N%?%U:N[#x]}", 42 * isq::length[m]) == "0x2a m"); + CHECK(MP_UNITS_STD_FMT::format("{:%N%?%U:N[#X]}", 42 * isq::length[m]) == "0X2A m"); + } + + SECTION("modified spec") + { + CHECK(MP_UNITS_STD_FMT::format("{:%N%U:N[#b]}", 42 * isq::length[m]) == "0b101010m"); + CHECK(MP_UNITS_STD_FMT::format("{:%N%U:N[#B]}", 42 * isq::length[m]) == "0B101010m"); + CHECK(MP_UNITS_STD_FMT::format("{:%N%U:N[#o]}", 42 * isq::length[m]) == "052m"); + CHECK(MP_UNITS_STD_FMT::format("{:%N%U:N[#x]}", 42 * isq::length[m]) == "0x2am"); + CHECK(MP_UNITS_STD_FMT::format("{:%N%U:N[#X]}", 42 * isq::length[m]) == "0X2Am"); + } } - SECTION("modified spec") + SECTION("value only format {:%N} on a quantity") { - CHECK(MP_UNITS_STD_FMT::format("{:%N%U:N[#b]}", 42 * isq::length[m]) == "0b101010m"); - CHECK(MP_UNITS_STD_FMT::format("{:%N%U:N[#B]}", 42 * isq::length[m]) == "0B101010m"); - CHECK(MP_UNITS_STD_FMT::format("{:%N%U:N[#o]}", 42 * isq::length[m]) == "052m"); - CHECK(MP_UNITS_STD_FMT::format("{:%N%U:N[#x]}", 42 * isq::length[m]) == "0x2am"); - CHECK(MP_UNITS_STD_FMT::format("{:%N%U:N[#X]}", 42 * isq::length[m]) == "0X2Am"); + CHECK(MP_UNITS_STD_FMT::format("{:%N:N[#b]}", 42 * isq::length[m]) == "0b101010"); + CHECK(MP_UNITS_STD_FMT::format("{:%N:N[#B]}", 42 * isq::length[m]) == "0B101010"); + CHECK(MP_UNITS_STD_FMT::format("{:%N:N[#o]}", 42 * isq::length[m]) == "052"); + CHECK(MP_UNITS_STD_FMT::format("{:%N:N[#x]}", 42 * isq::length[m]) == "0x2a"); + CHECK(MP_UNITS_STD_FMT::format("{:%N:N[#X]}", 42 * isq::length[m]) == "0X2A"); } } - SECTION("value only format {:%N} on a quantity") + SECTION("localization with the 'L' specifier") { - CHECK(MP_UNITS_STD_FMT::format("{:%N:N[#b]}", 42 * isq::length[m]) == "0b101010"); - CHECK(MP_UNITS_STD_FMT::format("{:%N:N[#B]}", 42 * isq::length[m]) == "0B101010"); - CHECK(MP_UNITS_STD_FMT::format("{:%N:N[#o]}", 42 * isq::length[m]) == "052"); - CHECK(MP_UNITS_STD_FMT::format("{:%N:N[#x]}", 42 * isq::length[m]) == "0x2a"); - CHECK(MP_UNITS_STD_FMT::format("{:%N:N[#X]}", 42 * isq::length[m]) == "0X2A"); - } -} + struct group2 : std::numpunct { + [[nodiscard]] char do_thousands_sep() const override { return '_'; } + [[nodiscard]] std::string do_grouping() const override { return "\2"; } + }; -TEST_CASE("localization with the 'L' specifier", "[text][fmt][localization]") -{ - struct group2 : std::numpunct { - [[nodiscard]] char do_thousands_sep() const override { return '_'; } - [[nodiscard]] std::string do_grouping() const override { return "\2"; } - }; + struct group3 : std::numpunct { + [[nodiscard]] char do_thousands_sep() const override { return '\''; } + [[nodiscard]] std::string do_grouping() const override { return "\3"; } + }; - struct group3 : std::numpunct { - [[nodiscard]] char do_thousands_sep() const override { return '\''; } - [[nodiscard]] std::string do_grouping() const override { return "\3"; } - }; + const std::locale grp2{std::locale::classic(), new group2}; + const std::locale grp3{std::locale::classic(), new group3}; - const std::locale grp2{std::locale::classic(), new group2}; - const std::locale grp3{std::locale::classic(), new group3}; - - SECTION("full format on a quantity") - { - SECTION("default spec") + SECTION("full format on a quantity") { - CHECK(MP_UNITS_STD_FMT::format(grp2, "{::N[L]}", 299'792'458 * isq::speed[m / s]) == "2_99_79_24_58 m/s"); - CHECK(MP_UNITS_STD_FMT::format(grp3, "{::N[L]}", 299'792'458 * isq::speed[m / s]) == "299'792'458 m/s"); - } + SECTION("default spec") + { + CHECK(MP_UNITS_STD_FMT::format(grp2, "{::N[L]}", 299'792'458 * isq::speed[m / s]) == "2_99_79_24_58 m/s"); + CHECK(MP_UNITS_STD_FMT::format(grp3, "{::N[L]}", 299'792'458 * isq::speed[m / s]) == "299'792'458 m/s"); + } - SECTION("explicit spec") - { - CHECK(MP_UNITS_STD_FMT::format(grp2, "{:%N%?%U:N[L]}", 299'792'458 * isq::speed[m / s]) == "2_99_79_24_58 m/s"); - CHECK(MP_UNITS_STD_FMT::format(grp3, "{:%N%?%U:N[L]}", 299'792'458 * isq::speed[m / s]) == "299'792'458 m/s"); - } + SECTION("explicit spec") + { + CHECK(MP_UNITS_STD_FMT::format(grp2, "{:%N%?%U:N[L]}", 299'792'458 * isq::speed[m / s]) == "2_99_79_24_58 m/s"); + CHECK(MP_UNITS_STD_FMT::format(grp3, "{:%N%?%U:N[L]}", 299'792'458 * isq::speed[m / s]) == "299'792'458 m/s"); + } - SECTION("modified spec") - { - CHECK(MP_UNITS_STD_FMT::format(grp2, "{:%N%U:N[L]}", 299'792'458 * isq::speed[m / s]) == "2_99_79_24_58m/s"); - CHECK(MP_UNITS_STD_FMT::format(grp3, "{:%N%U:N[L]}", 299'792'458 * isq::speed[m / s]) == "299'792'458m/s"); + SECTION("modified spec") + { + CHECK(MP_UNITS_STD_FMT::format(grp2, "{:%N%U:N[L]}", 299'792'458 * isq::speed[m / s]) == "2_99_79_24_58m/s"); + CHECK(MP_UNITS_STD_FMT::format(grp3, "{:%N%U:N[L]}", 299'792'458 * isq::speed[m / s]) == "299'792'458m/s"); + } } } } -TEST_CASE("unit_symbol", "[text]") -{ - using enum text_encoding; - using enum unit_symbol_solidus; - using enum unit_symbol_separator; - - std::ostringstream os; - - SECTION("default formatting") - { - os << unit_symbol(m / s2); - CHECK(os.str() == "m/s²"); - } - - SECTION("Portable mode") - { - os << unit_symbol(m / s2); - CHECK(os.str() == "m/s^2"); - } - - SECTION("solidus") - { - os << unit_symbol(m / s2); - CHECK(os.str() == "m s⁻²"); - } - - SECTION("separator") - { - os << unit_symbol(m / s2); - CHECK(os.str() == "m⋅s⁻²"); - } -} - -TEST_CASE("dimension_symbol", "[text]") -{ - using enum text_encoding; - - std::ostringstream os; - - SECTION("default formatting") - { - os << dimension_symbol(isq::power.dimension); - CHECK(os.str() == "L²MT⁻³"); - } - - SECTION("Portable mode") - { - os << dimension_symbol(isq::power.dimension); - CHECK(os.str() == "L^2MT^-3"); - } -} - -TEST_CASE("value_cast", "[text][ostream]") +TEST_CASE("check if `value_cast` properly changes the numerical value of a quantity", "[value_cast][ostream]") { std::ostringstream os; diff --git a/test/runtime/math_test.cpp b/test/runtime/math_test.cpp index 79018bff8..994c9eebb 100644 --- a/test/runtime/math_test.cpp +++ b/test/runtime/math_test.cpp @@ -43,486 +43,488 @@ using namespace mp_units::si::unit_symbols; // classical -TEST_CASE("'pow()' 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") - { - 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]); - } -} - -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()' 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]); } - } - - SECTION("'abs()' on a positive 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]); } - } -} - -TEST_CASE("numeric_limits functions", "[limits]") -{ - SECTION("'epsilon' works as expected using default floating type") - { - REQUIRE(epsilon(isq::length[m]).numerical_value_in(m) == - std::numeric_limits::epsilon()); - } - SECTION("'epsilon' works as expected using integers") - { - REQUIRE(epsilon(isq::length[m]).numerical_value_in(m) == - std::numeric_limits::epsilon()); - } -} - -TEST_CASE("floor functions", "[floor]") -{ - SECTION("floor 1 second with target unit second should be 1 second") - { - REQUIRE(floor(1 * isq::time[s]) == 1 * isq::time[s]); - } - SECTION("floor 1000 milliseconds with target unit second should be 1 second") - { - REQUIRE(floor(1000 * isq::time[ms]) == 1 * isq::time[s]); - } - SECTION("floor 1001 milliseconds with target unit second should be 1 second") - { - REQUIRE(floor(1001 * isq::time[ms]) == 1 * isq::time[s]); - } - SECTION("floor 1999 milliseconds with target unit second should be 1 second") - { - REQUIRE(floor(1999 * isq::time[ms]) == 1 * isq::time[s]); - } - SECTION("floor -1000 milliseconds with target unit second should be -1 second") - { - REQUIRE(floor(-1000 * isq::time[ms]) == -1 * isq::time[s]); - } - SECTION("floor -999 milliseconds with target unit second should be -1 second") - { - REQUIRE(floor(-999 * isq::time[ms]) == -1 * isq::time[s]); - } - SECTION("floor 1.3 seconds with target unit second should be 1 second") - { - REQUIRE(floor(1.3 * isq::time[s]) == 1 * isq::time[s]); - } - SECTION("floor -1.3 seconds with target unit second should be -2 seconds") - { - REQUIRE(floor(-1.3 * isq::time[s]) == -2 * isq::time[s]); - } - SECTION("floor 1001. milliseconds with target unit second should be 1 second") - { - REQUIRE(floor(1001. * isq::time[ms]) == 1 * isq::time[s]); - } - SECTION("floor 1999. milliseconds with target unit second should be 1 second") - { - REQUIRE(floor(1999. * isq::time[ms]) == 1 * isq::time[s]); - } - SECTION("floor -1000. milliseconds with target unit second should be -1 second") - { - REQUIRE(floor(-1000. * isq::time[ms]) == -1 * isq::time[s]); - } - SECTION("floor -999. milliseconds with target unit second should be -1 second") - { - REQUIRE(floor(-999. * isq::time[ms]) == -1 * isq::time[s]); - } - - // 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") - { - REQUIRE(ceil(1 * isq::time[s]) == 1 * isq::time[s]); - } - SECTION("ceil 1000 milliseconds with target unit second should be 1 second") - { - REQUIRE(ceil(1000 * isq::time[ms]) == 1 * isq::time[s]); - } - SECTION("ceil 1001 milliseconds with target unit second should be 2 seconds") - { - REQUIRE(ceil(1001 * isq::time[ms]) == 2 * isq::time[s]); - } - SECTION("ceil 1999 milliseconds with target unit second should be 2 seconds") - { - REQUIRE(ceil(1999 * isq::time[ms]) == 2 * isq::time[s]); - } - SECTION("ceil -1000 milliseconds with target unit second should be -1 second") - { - REQUIRE(ceil(-1000 * isq::time[ms]) == -1 * isq::time[s]); - } - SECTION("ceil -999 milliseconds with target unit second should be 0 seconds") - { - REQUIRE(ceil(-999 * isq::time[ms]) == 0 * isq::time[s]); - } - SECTION("ceil 1.3 seconds with target unit second should be 2 seconds") - { - REQUIRE(ceil(1.3 * isq::time[s]) == 2 * isq::time[s]); - } - SECTION("ceil -1.3 seconds with target unit second should be -1 second") - { - REQUIRE(ceil(-1.3 * isq::time[s]) == -1 * isq::time[s]); - } - SECTION("ceil 1001. milliseconds with target unit second should be 2 seconds") - { - REQUIRE(ceil(1001. * isq::time[ms]) == 2 * isq::time[s]); - } - SECTION("ceil 1999. milliseconds with target unit second should be 2 seconds") - { - REQUIRE(ceil(1999. * isq::time[ms]) == 2 * isq::time[s]); - } - SECTION("ceil -1000. milliseconds with target unit second should be -1 second") - { - REQUIRE(ceil(-1000. * isq::time[ms]) == -1 * isq::time[s]); - } - SECTION("ceil -999. milliseconds with target unit second should be 0 seconds") + SECTION("'pow()' on quantity changes the value and the dimension accordingly") { - REQUIRE(ceil(-999. * isq::time[ms]) == 0 * isq::time[s]); - } -} + SECTION("'pow<0>(q)' returns '1'") { CHECK(pow<0>(2 * isq::length[m]) == 1 * one); } -TEST_CASE("round functions", "[round]") -{ - SECTION("round 1 second with target unit second should be 1 second") - { - REQUIRE(round(1 * isq::time[s]) == 1 * isq::time[s]); - } - SECTION("round 1000 milliseconds with target unit second should be 1 second") - { - REQUIRE(round(1000 * isq::time[ms]) == 1 * isq::time[s]); - } - SECTION("round 1001 milliseconds with target unit second should be 1 second") - { - REQUIRE(round(1001 * isq::time[ms]) == 1 * isq::time[s]); - } - SECTION("round 1499 milliseconds with target unit second should be 1 second") - { - REQUIRE(round(1499 * isq::time[ms]) == 1 * isq::time[s]); - } - SECTION("round 1500 milliseconds with target unit second should be 2 seconds") - { - REQUIRE(round(1500 * isq::time[ms]) == 2 * isq::time[s]); - } - SECTION("round 1999 milliseconds with target unit second should be 2 seconds") - { - REQUIRE(round(1999 * isq::time[ms]) == 2 * isq::time[s]); - } - SECTION("round -1000 milliseconds with target unit second should be -1 second") - { - REQUIRE(round(-1000 * isq::time[ms]) == -1 * isq::time[s]); - } - SECTION("round -1001 milliseconds with target unit second should be -1 second") - { - REQUIRE(round(-1001 * isq::time[ms]) == -1 * isq::time[s]); - } - SECTION("round -1499 milliseconds with target unit second should be -1 second") - { - REQUIRE(round(-1499 * isq::time[ms]) == -1 * isq::time[s]); - } - SECTION("round -1500 milliseconds with target unit second should be -2 seconds") - { - REQUIRE(round(-1500 * isq::time[ms]) == -2 * isq::time[s]); - } - SECTION("round -1999 milliseconds with target unit second should be -2 seconds") - { - REQUIRE(round(-1999 * isq::time[ms]) == -2 * isq::time[s]); - } - SECTION("round 1000. milliseconds with target unit second should be 1 second") - { - REQUIRE(round(1000. * isq::time[ms]) == 1 * isq::time[s]); - } - SECTION("round 1001. milliseconds with target unit second should be 1 second") - { - REQUIRE(round(1001. * isq::time[ms]) == 1 * isq::time[s]); - } - SECTION("round 1499. milliseconds with target unit second should be 1 second") - { - REQUIRE(round(1499. * isq::time[ms]) == 1 * isq::time[s]); - } - SECTION("round 1500. milliseconds with target unit second should be 2 seconds") - { - REQUIRE(round(1500. * isq::time[ms]) == 2 * isq::time[s]); - } - SECTION("round 1999. milliseconds with target unit second should be 2 seconds") - { - REQUIRE(round(1999. * isq::time[ms]) == 2 * isq::time[s]); - } - SECTION("round -1000. milliseconds with target unit second should be -1 second") - { - REQUIRE(round(-1000. * isq::time[ms]) == -1 * isq::time[s]); - } - SECTION("round -1001. milliseconds with target unit second should be -1 second") - { - REQUIRE(round(-1001. * isq::time[ms]) == -1 * isq::time[s]); - } - SECTION("round -1499. milliseconds with target unit second should be -1 second") - { - REQUIRE(round(-1499. * isq::time[ms]) == -1 * isq::time[s]); - } - SECTION("round -1500. milliseconds with target unit second should be -2 seconds") - { - REQUIRE(round(-1500. * isq::time[ms]) == -2 * isq::time[s]); - } - SECTION("round -1999. milliseconds with target unit second should be -2 seconds") - { - REQUIRE(round(-1999. * isq::time[ms]) == -2 * isq::time[s]); - } -} + SECTION("'pow<1>(q)' returns 'q'") { CHECK(pow<1>(2 * isq::length[m]) == 2 * isq::length[m]); } -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]); - } -} + SECTION("'pow<2>(q)' squares both the value and a dimension") + { + CHECK(pow<2>(2 * isq::length[m]) == 4 * isq::area[m2]); + } -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)); + SECTION("'pow<3>(q)' cubes both the value and a dimension") + { + CHECK(pow<3>(2 * isq::length[m]) == 8 * isq::volume[m3]); + } } - SECTION("cos") + SECTION("'sqrt()' on quantity changes the value and the dimension accordingly") { - 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)); + REQUIRE(sqrt(4 * isq::area[m2]) == 2 * isq::length[m]); } - SECTION("tan") + SECTION("'cbrt()' on quantity changes the value and the dimension accordingly") { - 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)); + REQUIRE(cbrt(8 * isq::volume[m3]) == 2 * isq::length[m]); } -} -TEST_CASE("SI inverse trigonometric functions", "[inv trig][si]") -{ - SECTION("asin") + SECTION("'fma()' 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(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("acos") + SECTION("fmod functions") { - 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("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("atan") + SECTION("remainder functions") { - 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("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("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("'isfinite()' accepts dimensioned arguments") { REQUIRE(isfinite(4.0 * isq::length[m])); } + SECTION("'isinf()' accepts dimensioned arguments") { REQUIRE(!isinf(4.0 * 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("'isnan()' accepts dimensioned arguments") { REQUIRE(!isnan(4.0 * isq::length[m])); } - 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)); - } -} - -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])); - } - - 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])); - } -} - -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("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])); - } -} + + SECTION("'pow()' on quantity changes the value and the dimension accordingly") + { + REQUIRE(pow<1, 4>(16 * isq::area[m2]) == sqrt(4 * isq::length[m])); + } + + // TODO add tests for exp() + + SECTION("absolute functions on quantity returns the absolute value") + { + 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]); } + } + + SECTION("'abs()' on a positive 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]); } + } + } + + SECTION("numeric_limits functions") + { + SECTION("'epsilon' works as expected using default floating type") + { + REQUIRE(epsilon(isq::length[m]).numerical_value_in(m) == + std::numeric_limits::epsilon()); + } + SECTION("'epsilon' works as expected using integers") + { + REQUIRE(epsilon(isq::length[m]).numerical_value_in(m) == + std::numeric_limits::epsilon()); + } + } + + SECTION("floor functions") + { + SECTION("floor 1 second with target unit second should be 1 second") + { + REQUIRE(floor(1 * isq::time[s]) == 1 * isq::time[s]); + } + SECTION("floor 1000 milliseconds with target unit second should be 1 second") + { + REQUIRE(floor(1000 * isq::time[ms]) == 1 * isq::time[s]); + } + SECTION("floor 1001 milliseconds with target unit second should be 1 second") + { + REQUIRE(floor(1001 * isq::time[ms]) == 1 * isq::time[s]); + } + SECTION("floor 1999 milliseconds with target unit second should be 1 second") + { + REQUIRE(floor(1999 * isq::time[ms]) == 1 * isq::time[s]); + } + SECTION("floor -1000 milliseconds with target unit second should be -1 second") + { + REQUIRE(floor(-1000 * isq::time[ms]) == -1 * isq::time[s]); + } + SECTION("floor -999 milliseconds with target unit second should be -1 second") + { + REQUIRE(floor(-999 * isq::time[ms]) == -1 * isq::time[s]); + } + SECTION("floor 1.3 seconds with target unit second should be 1 second") + { + REQUIRE(floor(1.3 * isq::time[s]) == 1 * isq::time[s]); + } + SECTION("floor -1.3 seconds with target unit second should be -2 seconds") + { + REQUIRE(floor(-1.3 * isq::time[s]) == -2 * isq::time[s]); + } + SECTION("floor 1001. milliseconds with target unit second should be 1 second") + { + REQUIRE(floor(1001. * isq::time[ms]) == 1 * isq::time[s]); + } + SECTION("floor 1999. milliseconds with target unit second should be 1 second") + { + REQUIRE(floor(1999. * isq::time[ms]) == 1 * isq::time[s]); + } + SECTION("floor -1000. milliseconds with target unit second should be -1 second") + { + REQUIRE(floor(-1000. * isq::time[ms]) == -1 * isq::time[s]); + } + SECTION("floor -999. milliseconds with target unit second should be -1 second") + { + REQUIRE(floor(-999. * isq::time[ms]) == -1 * isq::time[s]); + } + + // TODO Add tests for `N`, `kN` and `kg * m / s2` i `kg * km / s2` + } + + SECTION("ceil functions") + { + SECTION("ceil 1 second with target unit second should be 1 second") + { + REQUIRE(ceil(1 * isq::time[s]) == 1 * isq::time[s]); + } + SECTION("ceil 1000 milliseconds with target unit second should be 1 second") + { + REQUIRE(ceil(1000 * isq::time[ms]) == 1 * isq::time[s]); + } + SECTION("ceil 1001 milliseconds with target unit second should be 2 seconds") + { + REQUIRE(ceil(1001 * isq::time[ms]) == 2 * isq::time[s]); + } + SECTION("ceil 1999 milliseconds with target unit second should be 2 seconds") + { + REQUIRE(ceil(1999 * isq::time[ms]) == 2 * isq::time[s]); + } + SECTION("ceil -1000 milliseconds with target unit second should be -1 second") + { + REQUIRE(ceil(-1000 * isq::time[ms]) == -1 * isq::time[s]); + } + SECTION("ceil -999 milliseconds with target unit second should be 0 seconds") + { + REQUIRE(ceil(-999 * isq::time[ms]) == 0 * isq::time[s]); + } + SECTION("ceil 1.3 seconds with target unit second should be 2 seconds") + { + REQUIRE(ceil(1.3 * isq::time[s]) == 2 * isq::time[s]); + } + SECTION("ceil -1.3 seconds with target unit second should be -1 second") + { + REQUIRE(ceil(-1.3 * isq::time[s]) == -1 * isq::time[s]); + } + SECTION("ceil 1001. milliseconds with target unit second should be 2 seconds") + { + REQUIRE(ceil(1001. * isq::time[ms]) == 2 * isq::time[s]); + } + SECTION("ceil 1999. milliseconds with target unit second should be 2 seconds") + { + REQUIRE(ceil(1999. * isq::time[ms]) == 2 * isq::time[s]); + } + SECTION("ceil -1000. milliseconds with target unit second should be -1 second") + { + REQUIRE(ceil(-1000. * isq::time[ms]) == -1 * isq::time[s]); + } + SECTION("ceil -999. milliseconds with target unit second should be 0 seconds") + { + REQUIRE(ceil(-999. * isq::time[ms]) == 0 * isq::time[s]); + } + } + + SECTION("round functions") + { + SECTION("round 1 second with target unit second should be 1 second") + { + REQUIRE(round(1 * isq::time[s]) == 1 * isq::time[s]); + } + SECTION("round 1000 milliseconds with target unit second should be 1 second") + { + REQUIRE(round(1000 * isq::time[ms]) == 1 * isq::time[s]); + } + SECTION("round 1001 milliseconds with target unit second should be 1 second") + { + REQUIRE(round(1001 * isq::time[ms]) == 1 * isq::time[s]); + } + SECTION("round 1499 milliseconds with target unit second should be 1 second") + { + REQUIRE(round(1499 * isq::time[ms]) == 1 * isq::time[s]); + } + SECTION("round 1500 milliseconds with target unit second should be 2 seconds") + { + REQUIRE(round(1500 * isq::time[ms]) == 2 * isq::time[s]); + } + SECTION("round 1999 milliseconds with target unit second should be 2 seconds") + { + REQUIRE(round(1999 * isq::time[ms]) == 2 * isq::time[s]); + } + SECTION("round -1000 milliseconds with target unit second should be -1 second") + { + REQUIRE(round(-1000 * isq::time[ms]) == -1 * isq::time[s]); + } + SECTION("round -1001 milliseconds with target unit second should be -1 second") + { + REQUIRE(round(-1001 * isq::time[ms]) == -1 * isq::time[s]); + } + SECTION("round -1499 milliseconds with target unit second should be -1 second") + { + REQUIRE(round(-1499 * isq::time[ms]) == -1 * isq::time[s]); + } + SECTION("round -1500 milliseconds with target unit second should be -2 seconds") + { + REQUIRE(round(-1500 * isq::time[ms]) == -2 * isq::time[s]); + } + SECTION("round -1999 milliseconds with target unit second should be -2 seconds") + { + REQUIRE(round(-1999 * isq::time[ms]) == -2 * isq::time[s]); + } + SECTION("round 1000. milliseconds with target unit second should be 1 second") + { + REQUIRE(round(1000. * isq::time[ms]) == 1 * isq::time[s]); + } + SECTION("round 1001. milliseconds with target unit second should be 1 second") + { + REQUIRE(round(1001. * isq::time[ms]) == 1 * isq::time[s]); + } + SECTION("round 1499. milliseconds with target unit second should be 1 second") + { + REQUIRE(round(1499. * isq::time[ms]) == 1 * isq::time[s]); + } + SECTION("round 1500. milliseconds with target unit second should be 2 seconds") + { + REQUIRE(round(1500. * isq::time[ms]) == 2 * isq::time[s]); + } + SECTION("round 1999. milliseconds with target unit second should be 2 seconds") + { + REQUIRE(round(1999. * isq::time[ms]) == 2 * isq::time[s]); + } + SECTION("round -1000. milliseconds with target unit second should be -1 second") + { + REQUIRE(round(-1000. * isq::time[ms]) == -1 * isq::time[s]); + } + SECTION("round -1001. milliseconds with target unit second should be -1 second") + { + REQUIRE(round(-1001. * isq::time[ms]) == -1 * isq::time[s]); + } + SECTION("round -1499. milliseconds with target unit second should be -1 second") + { + REQUIRE(round(-1499. * isq::time[ms]) == -1 * isq::time[s]); + } + SECTION("round -1500. milliseconds with target unit second should be -2 seconds") + { + REQUIRE(round(-1500. * isq::time[ms]) == -2 * isq::time[s]); + } + SECTION("round -1999. milliseconds with target unit second should be -2 seconds") + { + REQUIRE(round(-1999. * isq::time[ms]) == -2 * isq::time[s]); + } + } + + 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("SI trigonometric functions") + { + 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("SI inverse trigonometric functions") + { + 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])); + } + } +} \ No newline at end of file diff --git a/test/runtime/quantity_test.cpp b/test/runtime/quantity_test.cpp index 14dec787c..fcfdbad82 100644 --- a/test/runtime/quantity_test.cpp +++ b/test/runtime/quantity_test.cpp @@ -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); + } +} \ No newline at end of file