Merge branch 'master' into chiphogg/prime-wheel

This commit is contained in:
Chip Hogg committed 2022-03-19 16:01:32 +00:00
commit 48b6280486
145 files changed
+5823 -3539

No files matched your search

+186 -158
View File
@@ -20,10 +20,10 @@
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
#include <units/random.h>
#include <units/isq/si/length.h>
#include <array>
#include <catch2/catch.hpp>
#include <units/isq/si/length.h>
#include <units/random.h>
#include <array>
#include <initializer_list>
#include <random>
#include <vector>
@@ -39,16 +39,17 @@ TEST_CASE("uniform_int_distribution")
SECTION("default")
{
auto dist = units::uniform_int_distribution<q>();
CHECK(dist.a() == q::zero());
CHECK(dist.b() == q::max());
auto dist = units::uniform_int_distribution<q>();
CHECK(dist.a() == q::zero());
CHECK(dist.b() == q::max());
}
SECTION ("parametrized") {
SECTION("parametrized")
{
constexpr rep a = 2;
constexpr rep b = 5;
auto stl_dist = std::uniform_int_distribution(a, b);
auto units_dist = units::uniform_int_distribution(q(a), q(b));
@@ -66,16 +67,17 @@ TEST_CASE("uniform_real_distribution")
SECTION("default")
{
auto dist = units::uniform_real_distribution<q>();
CHECK(dist.a() == q::zero());
CHECK(dist.b() == q::one());
auto dist = units::uniform_real_distribution<q>();
CHECK(dist.a() == q::zero());
CHECK(dist.b() == q::one());
}
SECTION ("parametrized") {
SECTION("parametrized")
{
constexpr rep a = 2.0;
constexpr rep b = 5.0;
auto stl_dist = std::uniform_real_distribution(a, b);
auto units_dist = units::uniform_real_distribution(q(a), q(b));
@@ -93,16 +95,17 @@ TEST_CASE("binomial_distribution")
SECTION("default")
{
auto dist = units::binomial_distribution<q>();
CHECK(dist.p() == 0.5);
CHECK(dist.t() == q::one());
auto dist = units::binomial_distribution<q>();
CHECK(dist.p() == 0.5);
CHECK(dist.t() == q::one());
}
SECTION ("parametrized") {
SECTION("parametrized")
{
constexpr rep t = 5;
constexpr double p = 0.25;
auto stl_dist = std::binomial_distribution(t, p);
auto units_dist = units::binomial_distribution(q(t), p);
@@ -120,16 +123,17 @@ TEST_CASE("negative_binomial_distribution")
SECTION("default")
{
auto dist = units::negative_binomial_distribution<q>();
CHECK(dist.p() == 0.5);
CHECK(dist.k() == q::one());
auto dist = units::negative_binomial_distribution<q>();
CHECK(dist.p() == 0.5);
CHECK(dist.k() == q::one());
}
SECTION ("parametrized") {
SECTION("parametrized")
{
constexpr rep k = 5;
constexpr double p = 0.25;
auto stl_dist = std::negative_binomial_distribution(k, p);
auto units_dist = units::negative_binomial_distribution(q(k), p);
@@ -147,14 +151,15 @@ TEST_CASE("geometric_distribution")
SECTION("default")
{
auto dist = units::geometric_distribution<q>();
CHECK(dist.p() == 0.5);
auto dist = units::geometric_distribution<q>();
CHECK(dist.p() == 0.5);
}
SECTION ("parametrized") {
SECTION("parametrized")
{
constexpr double p = 0.25;
auto stl_dist = std::geometric_distribution<rep>(p);
auto units_dist = units::geometric_distribution<q>(p);
@@ -171,14 +176,15 @@ TEST_CASE("poisson_distribution")
SECTION("default")
{
auto dist = units::poisson_distribution<q>();
CHECK(dist.mean() == 1.0);
auto dist = units::poisson_distribution<q>();
CHECK(dist.mean() == 1.0);
}
SECTION ("parametrized") {
SECTION("parametrized")
{
constexpr double mean = 5.0;
auto stl_dist = std::poisson_distribution<rep>(mean);
auto units_dist = units::poisson_distribution<q>(mean);
@@ -195,14 +201,15 @@ TEST_CASE("exponential_distribution")
SECTION("default")
{
auto dist = units::exponential_distribution<q>();
CHECK(dist.lambda() == 1.0);
auto dist = units::exponential_distribution<q>();
CHECK(dist.lambda() == 1.0);
}
SECTION ("parametrized") {
SECTION("parametrized")
{
constexpr double lambda = 2.0;
auto stl_dist = std::exponential_distribution<rep>(lambda);
auto units_dist = units::exponential_distribution<q>(lambda);
@@ -219,16 +226,17 @@ TEST_CASE("gamma_distribution")
SECTION("default")
{
auto dist = units::gamma_distribution<q>();
CHECK(dist.alpha() == 1.0);
CHECK(dist.beta() == 1.0);
auto dist = units::gamma_distribution<q>();
CHECK(dist.alpha() == 1.0);
CHECK(dist.beta() == 1.0);
}
SECTION ("parametrized") {
SECTION("parametrized")
{
constexpr double alpha = 5.0;
constexpr double beta = 2.0;
auto stl_dist = std::gamma_distribution<rep>(alpha, beta);
auto units_dist = units::gamma_distribution<q>(alpha, beta);
@@ -246,16 +254,17 @@ TEST_CASE("weibull_distribution")
SECTION("default")
{
auto dist = units::weibull_distribution<q>();
CHECK(dist.a() == 1.0);
CHECK(dist.b() == 1.0);
auto dist = units::weibull_distribution<q>();
CHECK(dist.a() == 1.0);
CHECK(dist.b() == 1.0);
}
SECTION ("parametrized") {
SECTION("parametrized")
{
constexpr rep a = 5.0;
constexpr rep b = 2.0;
auto stl_dist = std::weibull_distribution(a, b);
auto units_dist = units::weibull_distribution<q>(a, b);
@@ -273,16 +282,17 @@ TEST_CASE("extreme_value_distribution")
SECTION("default")
{
auto dist = units::extreme_value_distribution<q>();
CHECK(dist.a() == q::zero());
CHECK(dist.b() == 1.0);
auto dist = units::extreme_value_distribution<q>();
CHECK(dist.a() == q::zero());
CHECK(dist.b() == 1.0);
}
SECTION ("parametrized") {
SECTION("parametrized")
{
constexpr rep a = 5.0;
constexpr rep b = 2.0;
auto stl_dist = std::extreme_value_distribution(a, b);
auto units_dist = units::extreme_value_distribution<q>(q(a), b);
@@ -300,20 +310,20 @@ TEST_CASE("normal_distribution")
SECTION("default")
{
auto dist = units::normal_distribution<q>();
CHECK(dist.mean() == q::zero());
CHECK(dist.stddev() == q::one());
auto dist = units::normal_distribution<q>();
CHECK(dist.mean() == q::zero());
CHECK(dist.stddev() == q::one());
}
SECTION("parametrized")
{
constexpr rep mean = 5.0;
constexpr rep stddev = 2.0;
auto stl_dist = std::normal_distribution(mean, stddev);
auto units_dist = units::normal_distribution(q(mean), q(stddev));
CHECK(units_dist.mean() == q(stl_dist.mean()));
CHECK(units_dist.stddev() == q(stl_dist.stddev()));
CHECK(units_dist.min() == q(stl_dist.min()));
@@ -328,20 +338,20 @@ TEST_CASE("lognormal_distribution")
SECTION("default")
{
auto dist = units::lognormal_distribution<q>();
CHECK(dist.m() == q::zero());
CHECK(dist.s() == q::one());
auto dist = units::lognormal_distribution<q>();
CHECK(dist.m() == q::zero());
CHECK(dist.s() == q::one());
}
SECTION("parametrized")
{
constexpr rep m = 5.0;
constexpr rep s = 2.0;
auto stl_dist = std::lognormal_distribution(m, s);
auto units_dist = units::lognormal_distribution(q(m), q(s));
CHECK(units_dist.m() == q(stl_dist.m()));
CHECK(units_dist.s() == q(stl_dist.s()));
CHECK(units_dist.min() == q(stl_dist.min()));
@@ -356,18 +366,18 @@ TEST_CASE("chi_squared_distribution")
SECTION("default")
{
auto dist = units::chi_squared_distribution<q>();
CHECK(dist.n() == 1.0);
auto dist = units::chi_squared_distribution<q>();
CHECK(dist.n() == 1.0);
}
SECTION("parametrized")
{
constexpr rep n = 5.0;
auto stl_dist = std::chi_squared_distribution(n);
auto units_dist = units::chi_squared_distribution<q>(n);
CHECK(units_dist.n() == stl_dist.n());
CHECK(units_dist.min() == q(stl_dist.min()));
CHECK(units_dist.max() == q(stl_dist.max()));
@@ -381,16 +391,17 @@ TEST_CASE("cauchy_distribution")
SECTION("default")
{
auto dist = units::cauchy_distribution<q>();
CHECK(dist.a() == q::zero());
CHECK(dist.b() == q::one());
auto dist = units::cauchy_distribution<q>();
CHECK(dist.a() == q::zero());
CHECK(dist.b() == q::one());
}
SECTION ("parametrized") {
SECTION("parametrized")
{
constexpr rep a = 5.0;
constexpr rep b = 2.0;
auto stl_dist = std::cauchy_distribution(a, b);
auto units_dist = units::cauchy_distribution(q(a), q(b));
@@ -408,16 +419,17 @@ TEST_CASE("fisher_f_distribution")
SECTION("default")
{
auto dist = units::fisher_f_distribution<q>();
CHECK(dist.m() == 1.0);
CHECK(dist.n() == 1.0);
auto dist = units::fisher_f_distribution<q>();
CHECK(dist.m() == 1.0);
CHECK(dist.n() == 1.0);
}
SECTION ("parametrized") {
SECTION("parametrized")
{
constexpr rep m = 5.0;
constexpr rep n = 2.0;
auto stl_dist = std::fisher_f_distribution<rep>(m, n);
auto units_dist = units::fisher_f_distribution<q>(m, n);
@@ -435,14 +447,15 @@ TEST_CASE("student_t_distribution")
SECTION("default")
{
auto dist = units::student_t_distribution<q>();
CHECK(dist.n() == 1.0);
auto dist = units::student_t_distribution<q>();
CHECK(dist.n() == 1.0);
}
SECTION ("parametrized") {
SECTION("parametrized")
{
constexpr rep n = 2.0;
auto stl_dist = std::student_t_distribution<rep>(n);
auto units_dist = units::student_t_distribution<q>(n);
@@ -459,36 +472,39 @@ TEST_CASE("discrete_distribution")
SECTION("default")
{
auto stl_dist = std::discrete_distribution<rep>();
auto units_dist = units::discrete_distribution<q>();
CHECK(units_dist.min() == q(stl_dist.min()));
CHECK(units_dist.max() == q(stl_dist.max()));
CHECK(units_dist.probabilities() == stl_dist.probabilities());
auto stl_dist = std::discrete_distribution<rep>();
auto units_dist = units::discrete_distribution<q>();
CHECK(units_dist.min() == q(stl_dist.min()));
CHECK(units_dist.max() == q(stl_dist.max()));
CHECK(units_dist.probabilities() == stl_dist.probabilities());
}
SECTION ("parametrized_input_it") {
SECTION("parametrized_input_it")
{
constexpr std::array<double, 3> weights = {1.0, 2.0, 3.0};
auto stl_dist = std::discrete_distribution<rep>(weights.cbegin(), weights.cend());
auto units_dist = units::discrete_distribution<q>(weights.cbegin(), weights.cend());
CHECK(units_dist.probabilities() == stl_dist.probabilities());
}
SECTION ("parametrized_initializer_list") {
SECTION("parametrized_initializer_list")
{
std::initializer_list<double> weights = {1.0, 2.0, 3.0};
auto stl_dist = std::discrete_distribution<rep>(weights);
auto units_dist = units::discrete_distribution<q>(weights);
CHECK(units_dist.probabilities() == stl_dist.probabilities());
}
SECTION ("parametrized_range") {
SECTION("parametrized_range")
{
constexpr std::size_t count = 3;
constexpr double xmin = 1, xmax = 3;
auto stl_dist = std::discrete_distribution<rep>(count, xmin, xmax, [](double val) { return val; });
auto units_dist = units::discrete_distribution<q>(count, xmin, xmax, [](double val) { return val; });
@@ -506,34 +522,38 @@ TEST_CASE("piecewise_constant_distribution")
SECTION("default")
{
auto stl_dist = std::piecewise_constant_distribution<rep>();
auto units_dist = units::piecewise_constant_distribution<q>();
CHECK(units_dist.min() == q(stl_dist.min()));
CHECK(units_dist.max() == q(stl_dist.max()));
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_constant_distribution<rep>();
auto units_dist = units::piecewise_constant_distribution<q>();
CHECK(units_dist.min() == q(stl_dist.min()));
CHECK(units_dist.max() == q(stl_dist.max()));
CHECK(stl_dist.intervals().size() == 2);
CHECK(units_dist.intervals().size() == 2);
CHECK(stl_dist.densities().size() == 1);
CHECK(units_dist.densities().size() == 1);
}
SECTION ("parametrized_input_it") {
SECTION("parametrized_input_it")
{
constexpr std::array<rep, 3> intervals_rep = {1.0, 2.0, 3.0};
constexpr std::array<q, 3> intervals_qty = {1.0_q_m, 2.0_q_m, 3.0_q_m};
constexpr std::array<rep, 3> weights = {1.0, 2.0, 3.0};
auto stl_dist = std::piecewise_constant_distribution<rep>(intervals_rep.cbegin(), intervals_rep.cend(), weights.cbegin());
auto units_dist = units::piecewise_constant_distribution<q>(intervals_qty.cbegin(), intervals_qty.cend(), weights.cbegin());
auto stl_dist =
std::piecewise_constant_distribution<rep>(intervals_rep.cbegin(), intervals_rep.cend(), weights.cbegin());
auto units_dist =
units::piecewise_constant_distribution<q>(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") {
SECTION("parametrized_initializer_list")
{
std::initializer_list<rep> intervals_rep = {1.0, 2.0, 3.0};
std::initializer_list<q> intervals_qty = {1.0_q_m, 2.0_q_m, 3.0_q_m};
auto stl_dist = std::piecewise_constant_distribution<rep>(intervals_rep, [](rep val) { return val; });
auto units_dist = units::piecewise_constant_distribution<q>(intervals_qty, [](q qty) { return qty.number(); });
@@ -541,13 +561,15 @@ TEST_CASE("piecewise_constant_distribution")
CHECK(units_dist.densities() == stl_dist.densities());
}
SECTION ("parametrized_range") {
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_q_m, xmax_qty = 3.0_q_m;
auto stl_dist = std::piecewise_constant_distribution<rep>(nw, xmin_rep, xmax_rep, [](rep val) { return val; });
auto units_dist = units::piecewise_constant_distribution<q>(nw, xmin_qty, xmax_qty, [](q qty) { return qty.number(); });
auto units_dist =
units::piecewise_constant_distribution<q>(nw, xmin_qty, xmax_qty, [](q qty) { return qty.number(); });
CHECK(units_dist.intervals() == intervals_qty_vec);
CHECK(units_dist.densities() == stl_dist.densities());
@@ -564,34 +586,38 @@ TEST_CASE("piecewise_linear_distribution")
SECTION("default")
{
auto stl_dist = std::piecewise_linear_distribution<rep>();
auto units_dist = units::piecewise_linear_distribution<q>();
CHECK(units_dist.min() == q(stl_dist.min()));
CHECK(units_dist.max() == q(stl_dist.max()));
CHECK(stl_dist.intervals().size() == 2);
CHECK(units_dist.intervals().size() == 2);
CHECK(stl_dist.densities().size() == 2);
CHECK(units_dist.densities().size() == 2);
auto stl_dist = std::piecewise_linear_distribution<rep>();
auto units_dist = units::piecewise_linear_distribution<q>();
CHECK(units_dist.min() == q(stl_dist.min()));
CHECK(units_dist.max() == q(stl_dist.max()));
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") {
SECTION("parametrized_input_it")
{
constexpr std::array<rep, 3> intervals_rep = {1.0, 2.0, 3.0};
constexpr std::array<q, 3> intervals_qty = {1.0_q_m, 2.0_q_m, 3.0_q_m};
constexpr std::array<rep, 3> weights = {1.0, 2.0, 3.0};
auto stl_dist = std::piecewise_linear_distribution<rep>(intervals_rep.cbegin(), intervals_rep.cend(), weights.cbegin());
auto units_dist = units::piecewise_linear_distribution<q>(intervals_qty.cbegin(), intervals_qty.cend(), weights.cbegin());
auto stl_dist =
std::piecewise_linear_distribution<rep>(intervals_rep.cbegin(), intervals_rep.cend(), weights.cbegin());
auto units_dist =
units::piecewise_linear_distribution<q>(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") {
SECTION("parametrized_initializer_list")
{
std::initializer_list<rep> intervals_rep = {1.0, 2.0, 3.0};
std::initializer_list<q> intervals_qty = {1.0_q_m, 2.0_q_m, 3.0_q_m};
auto stl_dist = std::piecewise_linear_distribution<rep>(intervals_rep, [](rep val) { return val; });
auto units_dist = units::piecewise_linear_distribution<q>(intervals_qty, [](q qty) { return qty.number(); });
@@ -599,13 +625,15 @@ TEST_CASE("piecewise_linear_distribution")
CHECK(units_dist.densities() == stl_dist.densities());
}
SECTION ("parametrized_range") {
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_q_m, xmax_qty = 3.0_q_m;
auto stl_dist = std::piecewise_linear_distribution<rep>(nw, xmin_rep, xmax_rep, [](rep val) { return val; });
auto units_dist = units::piecewise_linear_distribution<q>(nw, xmin_qty, xmax_qty, [](q qty) { return qty.number(); });
auto units_dist =
units::piecewise_linear_distribution<q>(nw, xmin_qty, xmax_qty, [](q qty) { return qty.number(); });
CHECK(units_dist.intervals() == intervals_qty_vec);
CHECK(units_dist.densities() == stl_dist.densities());
File diff suppressed because it is too large. Load diff
+13 -46
View File
@@ -20,7 +20,8 @@
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
#include <units/bits/external/hacks.h> // IWYU pragma: keep
#include <catch2/catch.hpp>
#include <units/bits/external/hacks.h> // IWYU pragma: keep
#include <units/format.h>
#include <units/isq/iec80000/iec80000.h>
#include <units/isq/si/iau/iau.h>
@@ -29,7 +30,6 @@
#include <units/isq/si/si.h>
#include <units/isq/si/typographic/typographic.h>
#include <units/isq/si/uscs/uscs.h>
#include <catch2/catch.hpp>
using namespace units::isq::si;
using namespace units::isq::si::references;
@@ -80,10 +80,7 @@ TEST_CASE("std::format on synthesized unit symbols", "[text][fmt]")
CHECK(STD_FMT::format("{}", 1_q_point_prn) == "1 point(prn)");
}
SECTION("mass")
{
CHECK(STD_FMT::format("{}", 1_q_kg) == "1 kg");
}
SECTION("mass") { CHECK(STD_FMT::format("{}", 1_q_kg) == "1 kg"); }
SECTION("area")
{
@@ -189,15 +186,9 @@ TEST_CASE("std::format on synthesized unit symbols", "[text][fmt]")
CHECK(STD_FMT::format("{}", 1_q_GW) == "1 GW");
}
SECTION("surface tension")
{
CHECK(STD_FMT::format("{}", 1_q_N_per_m) == "1 N/m");
}
SECTION("surface tension") { CHECK(STD_FMT::format("{}", 1_q_N_per_m) == "1 N/m"); }
SECTION("magnetic induction")
{
CHECK(STD_FMT::format("{}", 1_q_T) == "1 T");
}
SECTION("magnetic induction") { CHECK(STD_FMT::format("{}", 1_q_T) == "1 T"); }
SECTION("magnetic flux")
{
@@ -230,10 +221,7 @@ TEST_CASE("std::format on synthesized unit symbols", "[text][fmt]")
CHECK(STD_FMT::format("{}", 1_q_mGy) == "1 mGy");
}
SECTION("addition with common ratio")
{
CHECK(STD_FMT::format("{}", 1_q_in + 1_q_yd) == "37 in");
}
SECTION("addition with common ratio") { CHECK(STD_FMT::format("{}", 1_q_in + 1_q_yd) == "37 in"); }
SECTION("current density")
{
@@ -259,10 +247,7 @@ TEST_CASE("std::format on synthesized unit symbols", "[text][fmt]")
CHECK(STD_FMT::format("{:%Q %Aq}", 1_q_Pa_s) == "1 Pa s");
}
SECTION("heat capacity")
{
CHECK(STD_FMT::format("{}", 1_q_J_per_K) == "1 J/K");
}
SECTION("heat capacity") { CHECK(STD_FMT::format("{}", 1_q_J_per_K) == "1 J/K"); }
SECTION("specific heat capacity")
{
@@ -282,10 +267,7 @@ TEST_CASE("std::format on synthesized unit symbols", "[text][fmt]")
CHECK(STD_FMT::format("{:%Q %Aq}", 1_q_W_per_m_K) == "1 W m^-1 K^-1");
}
SECTION("electric field strength")
{
CHECK(STD_FMT::format("{}", 1_q_V_per_m) == "1 V/m");
}
SECTION("electric field strength") { CHECK(STD_FMT::format("{}", 1_q_V_per_m) == "1 V/m"); }
SECTION("charge density")
{
@@ -295,25 +277,13 @@ TEST_CASE("std::format on synthesized unit symbols", "[text][fmt]")
CHECK(STD_FMT::format("{:%Q %Aq}", 1_q_C_per_m2) == "1 C/m^2");
}
SECTION("permittivity")
{
CHECK(STD_FMT::format("{}", 1_q_F_per_m) == "1 F/m");
}
SECTION("permittivity") { CHECK(STD_FMT::format("{}", 1_q_F_per_m) == "1 F/m"); }
SECTION("permeability")
{
CHECK(STD_FMT::format("{}", 1_q_H_per_m) == "1 H/m");
}
SECTION("permeability") { CHECK(STD_FMT::format("{}", 1_q_H_per_m) == "1 H/m"); }
SECTION("molar energy")
{
CHECK(STD_FMT::format("{}", 1_q_J_per_mol) == "1 J/mol");
}
SECTION("molar energy") { CHECK(STD_FMT::format("{}", 1_q_J_per_mol) == "1 J/mol"); }
SECTION("torque")
{
CHECK(STD_FMT::format("{}", 1_q_N_m_per_rad) == "1 N ⋅ m/rad");
}
SECTION("torque") { CHECK(STD_FMT::format("{}", 1_q_N_m_per_rad) == "1 N ⋅ m/rad"); }
SECTION("storage_capacity")
{
@@ -332,10 +302,7 @@ TEST_CASE("std::format on synthesized unit symbols", "[text][fmt]")
CHECK(STD_FMT::format("{}", 1 * (TB / s)) == "1 TB/s");
}
SECTION("traffic_intesity")
{
CHECK(STD_FMT::format("{}", 1 * E) == "1 E");
}
SECTION("traffic_intesity") { CHECK(STD_FMT::format("{}", 1 * E) == "1 E"); }
SECTION("modulation_rate")
{
+98 -59
View File
@@ -65,25 +65,29 @@ void check_same_type_and_value(T actual, U expected)
TEST_CASE("base_power")
{
SECTION ("base rep deducible for integral base") {
SECTION("base rep deducible for integral base")
{
CHECK(base_power{2} == base_power<std::intmax_t>{2, ratio{1}});
CHECK(base_power{2, 3} == base_power<std::intmax_t>{2, ratio{3}});
CHECK(base_power{2, ratio{3, 4}} == base_power<std::intmax_t>{2, ratio{3, 4}});
}
SECTION ("get_base retrieves base for integral base") {
SECTION("get_base retrieves base for integral base")
{
CHECK(base_power{2}.get_base() == 2);
CHECK(base_power{3, 5}.get_base() == 3);
CHECK(base_power{5, ratio{1, 3}}.get_base() == 5);
}
SECTION ("get_base retrieves member value for non-integer base") {
SECTION("get_base retrieves member value for non-integer base")
{
CHECK(base_power<noninteger_base>{}.get_base() == 1.234L);
CHECK(base_power<noninteger_base>{2}.get_base() == 1.234L);
CHECK(base_power<noninteger_base>{ratio{5, 8}}.get_base() == 1.234L);
}
SECTION ("same-base values not equal if types are different") {
SECTION("same-base values not equal if types are different")
{
const auto a = base_power<noncanonical_two_base>{};
const auto b = base_power{2};
const auto c = base_power<other_noncanonical_two_base>{};
@@ -95,17 +99,20 @@ TEST_CASE("base_power")
CHECK(a != c);
}
SECTION ("same-type values not equal if bases are different") {
SECTION("same-type values not equal if bases are different")
{
CHECK(base_power{2} != base_power{3});
CHECK(base_power{2, ratio{5, 4}} != base_power{3, ratio{5, 4}});
}
SECTION ("same-type, same-base values not equal if powers are different") {
SECTION("same-type, same-base values not equal if powers are different")
{
CHECK(base_power{2} != base_power{2, 2});
CHECK(base_power<pi_base>{} != base_power<pi_base>{ratio{1, 3}});
}
SECTION ("product with inverse equals identity") {
SECTION("product with inverse equals identity")
{
auto check_product_with_inverse_is_identity = [](auto x) { CHECK(x * pow<-1>(x) == as_magnitude<1>()); };
check_product_with_inverse_is_identity(as_magnitude<3>());
@@ -113,7 +120,8 @@ TEST_CASE("base_power")
check_product_with_inverse_is_identity(pi_to_the<ratio{-22, 7}>());
}
SECTION ("pow() multiplies exponent") {
SECTION("pow() multiplies exponent")
{
CHECK(pow(base_power{2}, 0) == base_power{2, 0});
CHECK(pow(base_power{2, 3}, ratio{-1, 2}) == base_power{2, ratio{-3, 2}});
CHECK(pow(base_power<pi_base>{ratio{3, 2}}, ratio{1, 3}) == base_power<pi_base>{ratio{1, 2}});
@@ -122,7 +130,8 @@ TEST_CASE("base_power")
TEST_CASE("make_ratio performs prime factorization correctly")
{
SECTION ("Performs prime factorization when denominator is 1") {
SECTION("Performs prime factorization when denominator is 1")
{
CHECK(as_magnitude<1>() == magnitude<>{});
CHECK(as_magnitude<2>() == magnitude<base_power{2}>{});
CHECK(as_magnitude<3>() == magnitude<base_power{3}>{});
@@ -131,17 +140,17 @@ TEST_CASE("make_ratio performs prime factorization correctly")
CHECK(as_magnitude<792>() == magnitude<base_power{2, 3}, base_power{3, 2}, base_power{11}>{});
}
SECTION ("Supports fractions") {
CHECK(as_magnitude<ratio{5, 8}>() == magnitude<base_power{2, -3}, base_power{5}>{});
}
SECTION("Supports fractions") { CHECK(as_magnitude<ratio{5, 8}>() == magnitude<base_power{2, -3}, base_power{5}>{}); }
SECTION ("Supports nonzero exp") {
SECTION("Supports nonzero exp")
{
constexpr ratio r{3, 1, 2};
REQUIRE(r.exp == 2);
CHECK(as_magnitude<r>() == as_magnitude<300>());
}
SECTION ("Can handle prime factor which would be large enough to overflow int") {
SECTION("Can handle prime factor which would be large enough to overflow int")
{
// This was taken from a case which failed when we used `int` for our base to store prime numbers.
// The failure was due to a prime factor which is larger than 2^31.
as_magnitude<ratio(16'605'390'666'050, 10'000'000'000'000)>();
@@ -168,7 +177,8 @@ TEST_CASE("make_ratio performs prime factorization correctly")
TEST_CASE("magnitude converts to numerical value")
{
SECTION ("Positive integer powers of integer bases give integer values") {
SECTION("Positive integer powers of integer bases give integer values")
{
constexpr auto mag_412 = as_magnitude<412>();
check_same_type_and_value(get_value<int>(mag_412), 412);
check_same_type_and_value(get_value<std::size_t>(mag_412), std::size_t{412});
@@ -176,20 +186,23 @@ TEST_CASE("magnitude converts to numerical value")
check_same_type_and_value(get_value<double>(mag_412), 412.0);
}
SECTION ("Negative integer powers of integer bases compute correct values") {
SECTION("Negative integer powers of integer bases compute correct values")
{
constexpr auto mag_0p125 = as_magnitude<ratio{1, 8}>();
check_same_type_and_value(get_value<float>(mag_0p125), 0.125f);
check_same_type_and_value(get_value<double>(mag_0p125), 0.125);
}
SECTION ("pi to the 1 supplies correct values") {
SECTION("pi to the 1 supplies correct values")
{
constexpr auto pi = pi_to_the<1>();
check_same_type_and_value(get_value<float>(pi), std::numbers::pi_v<float>);
check_same_type_and_value(get_value<double>(pi), std::numbers::pi_v<double>);
check_same_type_and_value(get_value<long double>(pi), std::numbers::pi_v<long double>);
}
SECTION ("pi to arbitrary power performs computations in most accurate type at compile time") {
SECTION("pi to arbitrary power performs computations in most accurate type at compile time")
{
if constexpr (sizeof(float) < sizeof(long double)) {
constexpr auto pi_cubed = pi_to_the<3>();
@@ -203,7 +216,8 @@ TEST_CASE("magnitude converts to numerical value")
}
}
SECTION ("Impossible requests are prevented at compile time") {
SECTION("Impossible requests are prevented at compile time")
{
// Naturally, we cannot actually write a test to verify a compiler error. But any of these can
// be uncommented if desired to verify that it breaks the build.
@@ -228,18 +242,21 @@ TEST_CASE("magnitude converts to numerical value")
TEST_CASE("Equality works for magnitudes")
{
SECTION ("Equivalent ratios are equal") {
SECTION("Equivalent ratios are equal")
{
CHECK(as_magnitude<1>() == as_magnitude<1>());
CHECK(as_magnitude<3>() == as_magnitude<3>());
CHECK(as_magnitude<ratio{3, 4}>() == as_magnitude<ratio{9, 12}>());
}
SECTION ("Different ratios are unequal") {
SECTION("Different ratios are unequal")
{
CHECK(as_magnitude<3>() != as_magnitude<5>());
CHECK(as_magnitude<3>() != as_magnitude<ratio{3, 2}>());
}
SECTION ("Supports constexpr") {
SECTION("Supports constexpr")
{
constexpr auto eq = (as_magnitude<ratio{4, 5}>() == as_magnitude<ratio{4, 3}>());
CHECK(!eq);
}
@@ -247,20 +264,24 @@ TEST_CASE("Equality works for magnitudes")
TEST_CASE("Multiplication works for magnitudes")
{
SECTION ("Reciprocals reduce to null magnitude") {
SECTION("Reciprocals reduce to null magnitude")
{
CHECK(as_magnitude<ratio{3, 4}>() * as_magnitude<ratio{4, 3}>() == as_magnitude<1>());
}
SECTION ("Products work as expected") {
SECTION("Products work as expected")
{
CHECK(as_magnitude<ratio{4, 5}>() * as_magnitude<ratio{4, 3}>() == as_magnitude<ratio{16, 15}>());
}
SECTION ("Products handle pi correctly") {
SECTION("Products handle pi correctly")
{
CHECK(pi_to_the<1>() * as_magnitude<ratio{2, 3}>() * pi_to_the<ratio{-1, 2}>() ==
magnitude<base_power{2}, base_power{3, -1}, base_power<pi_base>{ratio{1, 2}}>{});
}
SECTION ("Supports constexpr") {
SECTION("Supports constexpr")
{
constexpr auto p = as_magnitude<ratio{4, 5}>() * as_magnitude<ratio{4, 3}>();
CHECK(p == as_magnitude<ratio{16, 15}>());
}
@@ -268,16 +289,19 @@ TEST_CASE("Multiplication works for magnitudes")
TEST_CASE("Division works for magnitudes")
{
SECTION ("Dividing anything by itself reduces to null magnitude") {
SECTION("Dividing anything by itself reduces to null magnitude")
{
CHECK(as_magnitude<ratio{3, 4}>() / as_magnitude<ratio{3, 4}>() == as_magnitude<1>());
CHECK(as_magnitude<15>() / as_magnitude<15>() == as_magnitude<1>());
}
SECTION ("Quotients work as expected") {
SECTION("Quotients work as expected")
{
CHECK(as_magnitude<ratio{4, 5}>() / as_magnitude<ratio{4, 3}>() == as_magnitude<ratio{3, 5}>());
}
SECTION ("Supports constexpr") {
SECTION("Supports constexpr")
{
constexpr auto q = as_magnitude<ratio{4, 5}>() / as_magnitude<ratio{4, 3}>();
CHECK(q == as_magnitude<ratio{3, 5}>());
}
@@ -285,28 +309,32 @@ TEST_CASE("Division works for magnitudes")
TEST_CASE("Can raise Magnitudes to rational powers")
{
SECTION ("Anything to the 0 is 1") {
SECTION("Anything to the 0 is 1")
{
CHECK(pow<0>(as_magnitude<1>()) == as_magnitude<1>());
CHECK(pow<0>(as_magnitude<123>()) == as_magnitude<1>());
CHECK(pow<0>(as_magnitude<ratio{3, 4}>()) == as_magnitude<1>());
CHECK(pow<0>(pi_to_the<ratio{-1, 2}>()) == as_magnitude<1>());
}
SECTION ("Anything to the 1 is itself") {
SECTION("Anything to the 1 is itself")
{
CHECK(pow<1>(as_magnitude<1>()) == as_magnitude<1>());
CHECK(pow<1>(as_magnitude<123>()) == as_magnitude<123>());
CHECK(pow<1>(as_magnitude<ratio{3, 4}>()) == as_magnitude<ratio{3, 4}>());
CHECK(pow<1>(pi_to_the<ratio{-1, 2}>()) == pi_to_the<ratio{-1, 2}>());
}
SECTION ("Can raise to arbitrary rational power") {
SECTION("Can raise to arbitrary rational power")
{
CHECK(pow<ratio{-8, 3}>(pi_to_the<ratio{-1, 2}>()) == pi_to_the<ratio{4, 3}>());
}
}
TEST_CASE("can distinguish integral, rational, and irrational magnitudes")
{
SECTION ("Integer magnitudes are integral and rational") {
SECTION("Integer magnitudes are integral and rational")
{
auto check_rational_and_integral = [](Magnitude auto m) {
CHECK(is_integral(m));
CHECK(is_rational(m));
@@ -319,7 +347,8 @@ TEST_CASE("can distinguish integral, rational, and irrational magnitudes")
check_rational_and_integral(as_magnitude<ratio{1, 1}>());
}
SECTION ("Fractional magnitudes are rational, but not integral") {
SECTION("Fractional magnitudes are rational, but not integral")
{
auto check_rational_but_not_integral = [](Magnitude auto m) {
CHECK(!is_integral(m));
CHECK(is_rational(m));
@@ -334,7 +363,8 @@ TEST_CASE("can distinguish integral, rational, and irrational magnitudes")
TEST_CASE("int_power computes integer powers")
{
SECTION ("handles floating point") {
SECTION("handles floating point")
{
check_same_type_and_value(int_power(0.123L, 0), 1.0L);
check_same_type_and_value(int_power(0.246f, 1), 0.246f);
check_same_type_and_value(int_power(0.5f, 3), 0.125f);
@@ -343,7 +373,8 @@ TEST_CASE("int_power computes integer powers")
CHECK(std::is_same_v<long double, decltype(compute_base_power<double>(base_power{10, 20}))>);
}
SECTION ("handles integral") {
SECTION("handles integral")
{
check_same_type_and_value(int_power(8, 0), 1);
check_same_type_and_value(int_power(9L, 1), 9L);
check_same_type_and_value(int_power(2, 10), 1024);
@@ -352,13 +383,15 @@ TEST_CASE("int_power computes integer powers")
TEST_CASE("Prime helper functions")
{
SECTION ("multiplicity") {
SECTION ("multiplicity")
{
CHECK(multiplicity(2, 8) == 3);
CHECK(multiplicity(2, 1024) == 10);
CHECK(multiplicity(11, 6655) == 3);
}
SECTION ("remove_power()") {
SECTION("remove_power()")
{
CHECK(remove_power(17, 0, 5) == 5);
CHECK(remove_power(2, 3, 24) == 3);
CHECK(remove_power(11, 3, 6655) == 5);
@@ -367,11 +400,10 @@ TEST_CASE("Prime helper functions")
TEST_CASE("Prime factorization")
{
SECTION ("1 factors into the null magnitude") {
CHECK(prime_factorization_v<1> == magnitude<>{});
}
SECTION("1 factors into the null magnitude") { CHECK(prime_factorization_v<1> == magnitude<>{}); }
SECTION ("Prime numbers factor into themselves") {
SECTION("Prime numbers factor into themselves")
{
CHECK(prime_factorization_v<2> == magnitude<base_power{2}>{});
CHECK(prime_factorization_v<3> == magnitude<base_power{3}>{});
CHECK(prime_factorization_v<5> == magnitude<base_power{5}>{});
@@ -381,24 +413,25 @@ TEST_CASE("Prime factorization")
CHECK(prime_factorization_v<41> == magnitude<base_power{41}>{});
}
SECTION ("Prime factorization finds factors and multiplicities") {
SECTION("Prime factorization finds factors and multiplicities")
{
CHECK(prime_factorization_v<792> == magnitude<base_power{2, 3}, base_power{3, 2}, base_power{11}>{});
}
}
TEST_CASE("is_prime detects primes")
{
SECTION ("Non-positive numbers are not prime") {
SECTION("Non-positive numbers are not prime")
{
CHECK(!is_prime(-1328));
CHECK(!is_prime(-1));
CHECK(!is_prime(0));
}
SECTION ("1 is not prime") {
CHECK(!is_prime(1));
}
SECTION("1 is not prime") { CHECK(!is_prime(1)); }
SECTION ("Discriminates between primes and non-primes") {
SECTION("Discriminates between primes and non-primes")
{
CHECK(is_prime(2));
CHECK(is_prime(3));
CHECK(!is_prime(4));
@@ -414,7 +447,8 @@ TEST_CASE("is_prime detects primes")
TEST_CASE("is_valid_base_power")
{
SECTION ("0 power is invalid") {
SECTION("0 power is invalid")
{
REQUIRE(is_valid_base_power(base_power{2}));
CHECK(!is_valid_base_power(base_power{2, 0}));
@@ -425,7 +459,8 @@ TEST_CASE("is_valid_base_power")
CHECK(!is_valid_base_power(base_power<pi_base>{0}));
}
SECTION ("non-prime integers are invalid") {
SECTION("non-prime integers are invalid")
{
CHECK(!is_valid_base_power(base_power{-8}));
CHECK(!is_valid_base_power(base_power{0}));
CHECK(!is_valid_base_power(base_power{1}));
@@ -436,7 +471,8 @@ TEST_CASE("is_valid_base_power")
CHECK(!is_valid_base_power(base_power{4}));
}
SECTION ("non-positive floating point bases are invalid") {
SECTION("non-positive floating point bases are invalid")
{
CHECK(!is_valid_base_power(base_power<invalid_zero_base>{}));
CHECK(!is_valid_base_power(base_power<invalid_negative_base>{}));
}
@@ -448,18 +484,21 @@ TEST_CASE("pairwise_all evaluates all pairs")
const auto all_pairs_return_false = pairwise_all{[](auto, auto) { return false; }};
const auto all_increasing = pairwise_all{std::less{}};
SECTION ("always true for empty tuples") {
SECTION("always true for empty tuples")
{
CHECK(all_pairs_return_true());
CHECK(all_pairs_return_false());
}
SECTION ("always true for single-element tuples") {
SECTION("always true for single-element tuples")
{
CHECK(all_pairs_return_true(1));
CHECK(all_pairs_return_false(3.14));
CHECK(all_pairs_return_true('x'));
}
SECTION ("true for longer tuples iff true for all neighbouring pairs") {
SECTION("true for longer tuples iff true for all neighbouring pairs")
{
CHECK(all_increasing(1, 1.5));
CHECK(all_increasing(1, 1.5, 2));
@@ -473,17 +512,17 @@ TEST_CASE("pairwise_all evaluates all pairs")
TEST_CASE("strictly_increasing")
{
SECTION ("Empty input is sorted") {
CHECK(strictly_increasing());
}
SECTION("Empty input is sorted") { CHECK(strictly_increasing()); }
SECTION ("Single-element input is sorted") {
SECTION("Single-element input is sorted")
{
CHECK(strictly_increasing(3));
CHECK(strictly_increasing(15.42));
CHECK(strictly_increasing('c'));
}
SECTION ("Multi-value inputs compare correctly") {
SECTION("Multi-value inputs compare correctly")
{
CHECK(strictly_increasing(3, 3.14));
CHECK(!strictly_increasing(3, 3.0));
CHECK(!strictly_increasing(4, 3.0));
+120 -97
View File
@@ -20,12 +20,12 @@
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
#include <units/math.h>
#include <catch2/catch.hpp>
#include <units/isq/si/area.h>
#include <units/isq/si/length.h>
#include <units/isq/si/volume.h>
#include <units/isq/si/time.h>
#include <catch2/catch.hpp>
#include <units/isq/si/volume.h>
#include <units/math.h>
#include <limits>
using namespace units;
@@ -36,21 +36,13 @@ using namespace units::isq::si;
TEST_CASE("'pow<N>()' on quantity changes the value and the dimension accordingly", "[math][pow]")
{
SECTION ("'pow<0>(q)' returns '1'") {
CHECK(pow<0>(2_q_m) == 1);
}
SECTION("'pow<0>(q)' returns '1'") { CHECK(pow<0>(2_q_m) == 1); }
SECTION ("'pow<1>(q)' returns 'q'") {
CHECK(pow<1>(2_q_m) == 2_q_m);
}
SECTION("'pow<1>(q)' returns 'q'") { CHECK(pow<1>(2_q_m) == 2_q_m); }
SECTION ("'pow<2>(q)' squares both the value and a dimension") {
CHECK(pow<2>(2_q_m) == 4_q_m2);
}
SECTION("'pow<2>(q)' squares both the value and a dimension") { CHECK(pow<2>(2_q_m) == 4_q_m2); }
SECTION ("'pow<3>(q)' cubes both the value and a dimension") {
CHECK(pow<3>(2_q_m) == 8_q_m3);
}
SECTION("'pow<3>(q)' cubes both the value and a dimension") { CHECK(pow<3>(2_q_m) == 8_q_m3); }
}
TEST_CASE("'sqrt()' on quantity changes the value and the dimension accordingly", "[math][sqrt]")
@@ -70,85 +62,86 @@ TEST_CASE("'pow<Num, Den>()' on quantity changes the value and the dimension acc
TEST_CASE("absolute functions on quantity returns the absolute value", "[math][abs][fabs]")
{
SECTION ("'abs()' on a negative quantity returns the abs")
SECTION("'abs()' on a negative quantity returns the abs")
{
SECTION ("integral representation")
{
REQUIRE(abs(-1_q_m) == 1_q_m);
}
SECTION("integral representation") { REQUIRE(abs(-1_q_m) == 1_q_m); }
SECTION ("floating-point representation")
{
REQUIRE(abs(-1._q_m) == 1_q_m);
}
SECTION("floating-point representation") { REQUIRE(abs(-1._q_m) == 1_q_m); }
}
SECTION ("'abs()' on a positive quantity returns the abs")
SECTION("'abs()' on a positive quantity returns the abs")
{
SECTION ("integral representation")
{
REQUIRE(abs(1_q_m) == 1_q_m);
}
SECTION("integral representation") { REQUIRE(abs(1_q_m) == 1_q_m); }
SECTION ("floating-point representation")
{
REQUIRE(abs(1._q_m) == 1_q_m);
}
SECTION("floating-point representation") { REQUIRE(abs(1._q_m) == 1_q_m); }
}
}
TEST_CASE("numeric_limits functions", "[limits]")
{
SECTION ("'epsilon' works as expected using default floating type") {
SECTION("'epsilon' works as expected using default floating type")
{
REQUIRE(epsilon<decltype(1._q_m)>().number() == std::numeric_limits<decltype(1._q_m)::rep>::epsilon());
}
SECTION ("'epsilon' works as expected using integers") {
SECTION("'epsilon' works as expected using integers")
{
REQUIRE(epsilon<decltype(1_q_m)>().number() == std::numeric_limits<decltype(1_q_m)::rep>::epsilon());
}
SECTION ("'epsilon' works as expected using mixed Rep types") {
SECTION("'epsilon' works as expected using mixed Rep types")
{
REQUIRE(epsilon<decltype(1_q_m)>().number() != std::numeric_limits<decltype(1._q_m)::rep>::epsilon());
}
}
TEST_CASE("floor functions", "[floor]")
{
SECTION ("floor 1 second with target unit second should be 1 second") {
REQUIRE(floor<si::second>(1_q_s) == 1_q_s);
}
SECTION ("floor 1000 milliseconds with target unit second should be 1 second") {
SECTION("floor 1 second with target unit second should be 1 second") { REQUIRE(floor<si::second>(1_q_s) == 1_q_s); }
SECTION("floor 1000 milliseconds with target unit second should be 1 second")
{
REQUIRE(floor<si::second>(1000_q_ms) == 1_q_s);
}
SECTION ("floor 1001 milliseconds with target unit second should be 1 second") {
SECTION("floor 1001 milliseconds with target unit second should be 1 second")
{
REQUIRE(floor<si::second>(1001_q_ms) == 1_q_s);
}
SECTION ("floor 1999 milliseconds with target unit second should be 1 second") {
SECTION("floor 1999 milliseconds with target unit second should be 1 second")
{
REQUIRE(floor<si::second>(1999_q_ms) == 1_q_s);
}
SECTION ("floor -1000 milliseconds with target unit second should be -1 second") {
SECTION("floor -1000 milliseconds with target unit second should be -1 second")
{
REQUIRE(floor<si::second>(-1000_q_ms) == -1_q_s);
}
SECTION ("floor -999 milliseconds with target unit second should be -1 second") {
SECTION("floor -999 milliseconds with target unit second should be -1 second")
{
REQUIRE(floor<si::second>(-999_q_ms) == -1_q_s);
}
SECTION ("floor 1.3 seconds with target unit second should be 1 second") {
SECTION("floor 1.3 seconds with target unit second should be 1 second")
{
REQUIRE(floor<si::second>(1.3_q_s) == 1_q_s);
}
SECTION ("floor -1.3 seconds with target unit second should be -2 seconds") {
SECTION("floor -1.3 seconds with target unit second should be -2 seconds")
{
REQUIRE(floor<si::second>(-1.3_q_s) == -2_q_s);
}
SECTION ("floor 1001. milliseconds with target unit second should be 1 second") {
SECTION("floor 1001. milliseconds with target unit second should be 1 second")
{
REQUIRE(floor<si::second>(1001._q_ms) == 1_q_s);
}
SECTION ("floor 1999. milliseconds with target unit second should be 1 second") {
SECTION("floor 1999. milliseconds with target unit second should be 1 second")
{
REQUIRE(floor<si::second>(1999._q_ms) == 1_q_s);
}
SECTION ("floor -1000. milliseconds with target unit second should be -1 second") {
SECTION("floor -1000. milliseconds with target unit second should be -1 second")
{
REQUIRE(floor<si::second>(-1000._q_ms) == -1_q_s);
}
SECTION ("floor -999. milliseconds with target unit second should be -1 second") {
SECTION("floor -999. milliseconds with target unit second should be -1 second")
{
REQUIRE(floor<si::second>(-999._q_ms) == -1_q_s);
}
SECTION ("floor 1 second with target quantity with unit type second should be 1 second") {
SECTION("floor 1 second with target quantity with unit type second should be 1 second")
{
using showtime = si::time<si::second, int>;
REQUIRE(floor<showtime>(showtime::one()) == showtime::one());
}
@@ -156,44 +149,53 @@ TEST_CASE("floor functions", "[floor]")
TEST_CASE("ceil functions", "[ceil]")
{
SECTION ("ceil 1 second with target unit second should be 1 second") {
REQUIRE(ceil<si::second>(1_q_s) == 1_q_s);
}
SECTION ("ceil 1000 milliseconds with target unit second should be 1 second") {
SECTION("ceil 1 second with target unit second should be 1 second") { REQUIRE(ceil<si::second>(1_q_s) == 1_q_s); }
SECTION("ceil 1000 milliseconds with target unit second should be 1 second")
{
REQUIRE(ceil<si::second>(1000_q_ms) == 1_q_s);
}
SECTION ("ceil 1001 milliseconds with target unit second should be 2 seconds") {
SECTION("ceil 1001 milliseconds with target unit second should be 2 seconds")
{
REQUIRE(ceil<si::second>(1001_q_ms) == 2_q_s);
}
SECTION ("ceil 1999 milliseconds with target unit second should be 2 seconds") {
SECTION("ceil 1999 milliseconds with target unit second should be 2 seconds")
{
REQUIRE(ceil<si::second>(1999_q_ms) == 2_q_s);
}
SECTION ("ceil -1000 milliseconds with target unit second should be -1 second") {
SECTION("ceil -1000 milliseconds with target unit second should be -1 second")
{
REQUIRE(ceil<si::second>(-1000_q_ms) == -1_q_s);
}
SECTION ("ceil -999 milliseconds with target unit second should be 0 seconds") {
SECTION("ceil -999 milliseconds with target unit second should be 0 seconds")
{
REQUIRE(ceil<si::second>(-999_q_ms) == 0_q_s);
}
SECTION ("ceil 1.3 seconds with target unit second should be 2 seconds") {
SECTION("ceil 1.3 seconds with target unit second should be 2 seconds")
{
REQUIRE(ceil<si::second>(1.3_q_s) == 2_q_s);
}
SECTION ("ceil -1.3 seconds with target unit second should be -1 second") {
SECTION("ceil -1.3 seconds with target unit second should be -1 second")
{
REQUIRE(ceil<si::second>(-1.3_q_s) == -1_q_s);
}
SECTION ("ceil 1001. milliseconds with target unit second should be 2 seconds") {
SECTION("ceil 1001. milliseconds with target unit second should be 2 seconds")
{
REQUIRE(ceil<si::second>(1001._q_ms) == 2_q_s);
}
SECTION ("ceil 1999. milliseconds with target unit second should be 2 seconds") {
SECTION("ceil 1999. milliseconds with target unit second should be 2 seconds")
{
REQUIRE(ceil<si::second>(1999._q_ms) == 2_q_s);
}
// TODO does not work, probably due to a bug in fpow10() see #311
// SECTION ("ceil -1000. milliseconds with target unit second should be -1 second") {
// REQUIRE(ceil<si::second>(-1000._q_ms) == -1_q_s);
// }
SECTION ("ceil -999. milliseconds with target unit second should be 0 seconds") {
// TODO does not work, probably due to a bug in fpow10() see #311
// SECTION ("ceil -1000. milliseconds with target unit second should be -1 second") {
// REQUIRE(ceil<si::second>(-1000._q_ms) == -1_q_s);
// }
SECTION("ceil -999. milliseconds with target unit second should be 0 seconds")
{
REQUIRE(ceil<si::second>(-999._q_ms) == 0_q_s);
}
SECTION ("ceil 1 second with target quantity with unit type second should be 1 second") {
SECTION("ceil 1 second with target quantity with unit type second should be 1 second")
{
using showtime = si::time<si::second, int>;
REQUIRE(ceil<showtime>(showtime::one()) == showtime::one());
}
@@ -201,70 +203,89 @@ TEST_CASE("ceil functions", "[ceil]")
TEST_CASE("round functions", "[round]")
{
SECTION ("round 1 second with target unit second should be 1 second") {
REQUIRE(round<si::second>(1_q_s) == 1_q_s);
}
SECTION ("round 1000 milliseconds with target unit second should be 1 second") {
SECTION("round 1 second with target unit second should be 1 second") { REQUIRE(round<si::second>(1_q_s) == 1_q_s); }
SECTION("round 1000 milliseconds with target unit second should be 1 second")
{
REQUIRE(round<si::second>(1000_q_ms) == 1_q_s);
}
SECTION ("round 1001 milliseconds with target unit second should be 1 second") {
SECTION("round 1001 milliseconds with target unit second should be 1 second")
{
REQUIRE(round<si::second>(1001_q_ms) == 1_q_s);
}
SECTION ("round 1499 milliseconds with target unit second should be 1 second") {
SECTION("round 1499 milliseconds with target unit second should be 1 second")
{
REQUIRE(round<si::second>(1499_q_ms) == 1_q_s);
}
SECTION ("round 1500 milliseconds with target unit second should be 2 seconds") {
SECTION("round 1500 milliseconds with target unit second should be 2 seconds")
{
REQUIRE(round<si::second>(1500_q_ms) == 2_q_s);
}
SECTION ("round 1999 milliseconds with target unit second should be 2 seconds") {
SECTION("round 1999 milliseconds with target unit second should be 2 seconds")
{
REQUIRE(round<si::second>(1999_q_ms) == 2_q_s);
}
SECTION ("round -1000 milliseconds with target unit second should be -1 second") {
SECTION("round -1000 milliseconds with target unit second should be -1 second")
{
REQUIRE(round<si::second>(-1000_q_ms) == -1_q_s);
}
SECTION ("round -1001 milliseconds with target unit second should be -1 second") {
SECTION("round -1001 milliseconds with target unit second should be -1 second")
{
REQUIRE(round<si::second>(-1001_q_ms) == -1_q_s);
}
SECTION ("round -1499 milliseconds with target unit second should be -1 second") {
SECTION("round -1499 milliseconds with target unit second should be -1 second")
{
REQUIRE(round<si::second>(-1499_q_ms) == -1_q_s);
}
SECTION ("round -1500 milliseconds with target unit second should be -2 seconds") {
SECTION("round -1500 milliseconds with target unit second should be -2 seconds")
{
REQUIRE(round<si::second>(-1500_q_ms) == -2_q_s);
}
SECTION ("round -1999 milliseconds with target unit second should be -2 seconds") {
SECTION("round -1999 milliseconds with target unit second should be -2 seconds")
{
REQUIRE(round<si::second>(-1999_q_ms) == -2_q_s);
}
SECTION ("round 1000. milliseconds with target unit second should be 1 second") {
SECTION("round 1000. milliseconds with target unit second should be 1 second")
{
REQUIRE(round<si::second>(1000._q_ms) == 1_q_s);
}
SECTION ("round 1001. milliseconds with target unit second should be 1 second") {
SECTION("round 1001. milliseconds with target unit second should be 1 second")
{
REQUIRE(round<si::second>(1001._q_ms) == 1_q_s);
}
SECTION ("round 1499. milliseconds with target unit second should be 1 second") {
SECTION("round 1499. milliseconds with target unit second should be 1 second")
{
REQUIRE(round<si::second>(1499._q_ms) == 1_q_s);
}
SECTION ("round 1500. milliseconds with target unit second should be 2 seconds") {
SECTION("round 1500. milliseconds with target unit second should be 2 seconds")
{
REQUIRE(round<si::second>(1500._q_ms) == 2_q_s);
}
SECTION ("round 1999. milliseconds with target unit second should be 2 seconds") {
SECTION("round 1999. milliseconds with target unit second should be 2 seconds")
{
REQUIRE(round<si::second>(1999._q_ms) == 2_q_s);
}
SECTION ("round -1000. milliseconds with target unit second should be -1 second") {
SECTION("round -1000. milliseconds with target unit second should be -1 second")
{
REQUIRE(round<si::second>(-1000._q_ms) == -1_q_s);
}
SECTION ("round -1001. milliseconds with target unit second should be -1 second") {
SECTION("round -1001. milliseconds with target unit second should be -1 second")
{
REQUIRE(round<si::second>(-1001._q_ms) == -1_q_s);
}
SECTION ("round -1499. milliseconds with target unit second should be -1 second") {
SECTION("round -1499. milliseconds with target unit second should be -1 second")
{
REQUIRE(round<si::second>(-1499._q_ms) == -1_q_s);
}
SECTION ("round -1500. milliseconds with target unit second should be -2 seconds") {
SECTION("round -1500. milliseconds with target unit second should be -2 seconds")
{
REQUIRE(round<si::second>(-1500._q_ms) == -2_q_s);
}
SECTION ("round -1999. milliseconds with target unit second should be -2 seconds") {
SECTION("round -1999. milliseconds with target unit second should be -2 seconds")
{
REQUIRE(round<si::second>(-1999._q_ms) == -2_q_s);
}
SECTION ("round 1 second with target quantity with unit type second should be 1 second") {
SECTION("round 1 second with target quantity with unit type second should be 1 second")
{
using showtime = si::time<si::second, int>;
REQUIRE(round<showtime>(showtime::one()) == showtime::one());
}
@@ -281,7 +302,7 @@ template<std::intmax_t N>
struct Pow {
constexpr static std::intmax_t exponent = N;
template<typename T>
[[nodiscard]] constexpr static auto pow(T const& v) noexcept
[[nodiscard]] constexpr static auto pow(const T& v) noexcept
{
return detail::pow_impl<N>(v);
}
@@ -301,8 +322,9 @@ struct RuntimeRoot : Pow<N> {
template<typename TestType>
static void root_test()
{
SECTION ("Roots are truncated down") {
auto base = GENERATE(range(1.0, 10.0, 1.0)); // doubles to guard against overflow
SECTION("Roots are truncated down")
{
auto base = GENERATE(range(1.0, 10.0, 1.0)); // doubles to guard against overflow
if (TestType::pow(base) < static_cast<double>(std::numeric_limits<std::intmax_t>::max())) {
const std::intmax_t x = TestType::pow(static_cast<std::intmax_t>(base));
@@ -313,7 +335,8 @@ static void root_test()
}
}
SECTION ("Roots are truncated correctly for very large inputs") {
SECTION("Roots are truncated correctly for very large inputs")
{
auto exponent = GENERATE(range(10, std::numeric_limits<std::intmax_t>::digits10, 1));
const auto large_val = static_cast<std::intmax_t>(std::pow(10, exponent));
const auto expected = static_cast<std::intmax_t>(std::pow(10, exponent / static_cast<double>(TestType::exponent)));