Merge branch 'master' into chiphogg/prime-wheel
This commit is contained in:
commit
48b6280486
145 files changed
+5823
-3539
No files matched your search
@@ -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());
|
||||
|
||||
+154
-495
File diff suppressed because it is too large.
Load diff
@@ -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")
|
||||
{
|
||||
|
||||
@@ -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));
|
||||
|
||||
@@ -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)));
|
||||
|
||||
@@ -100,4 +100,4 @@ static_assert(10_q_erg / 1_q_erg_per_s == 10_q_s);
|
||||
|
||||
static_assert(detail::unit_text<dim_power, erg_per_second>() == "erg/s");
|
||||
|
||||
}
|
||||
} // namespace
|
||||
@@ -34,9 +34,11 @@ using namespace units::isq;
|
||||
using namespace units::isq::si::literals;
|
||||
using namespace std::chrono_literals;
|
||||
using sys_seconds = std::chrono::time_point<std::chrono::system_clock, std::chrono::seconds>;
|
||||
using sys_days = std::chrono::time_point<std::chrono::system_clock,
|
||||
std::chrono::duration<long, std::ratio_multiply<std::ratio<24>, std::chrono::hours::period>>>;
|
||||
template<typename C, typename U, typename Rep = double> using time_point = quantity_point<clock_origin<C>, U, Rep>;
|
||||
using sys_days =
|
||||
std::chrono::time_point<std::chrono::system_clock,
|
||||
std::chrono::duration<long, std::ratio_multiply<std::ratio<24>, std::chrono::hours::period>>>;
|
||||
template<typename C, typename U, typename Rep = double>
|
||||
using time_point = quantity_point<clock_origin<C>, U, Rep>;
|
||||
|
||||
static_assert(QuantityLike<std::chrono::seconds>);
|
||||
static_assert(QuantityPointLike<sys_seconds>);
|
||||
@@ -50,8 +52,10 @@ static_assert(std::constructible_from<si::time<si::second, std::chrono::hours::r
|
||||
static_assert(!std::convertible_to<std::chrono::hours, si::time<si::second, std::chrono::hours::rep>>);
|
||||
static_assert(!std::constructible_from<si::time<si::hour, std::chrono::seconds::rep>, std::chrono::seconds>);
|
||||
static_assert(!std::convertible_to<std::chrono::seconds, si::time<si::hour, std::chrono::seconds::rep>>);
|
||||
static_assert(std::constructible_from<time_point<std::chrono::system_clock, si::second, sys_seconds::rep>, sys_seconds>);
|
||||
static_assert(!std::constructible_from<time_point<std::chrono::steady_clock, si::second, sys_seconds::rep>, sys_seconds>);
|
||||
static_assert(
|
||||
std::constructible_from<time_point<std::chrono::system_clock, si::second, sys_seconds::rep>, sys_seconds>);
|
||||
static_assert(
|
||||
!std::constructible_from<time_point<std::chrono::steady_clock, si::second, sys_seconds::rep>, sys_seconds>);
|
||||
static_assert(!std::convertible_to<sys_seconds, time_point<std::chrono::system_clock, si::second, sys_seconds::rep>>);
|
||||
static_assert(std::constructible_from<time_point<std::chrono::system_clock, si::day, sys_days::rep>, sys_days>);
|
||||
static_assert(!std::constructible_from<time_point<std::chrono::steady_clock, si::day, sys_days::rep>, sys_days>);
|
||||
@@ -80,8 +84,10 @@ static_assert(!std::convertible_to<sys_seconds, time_point<std::chrono::system_c
|
||||
// CTAD
|
||||
static_assert(is_same_v<decltype(quantity{1s}), si::time<si::second, std::chrono::seconds::rep>>);
|
||||
static_assert(is_same_v<decltype(quantity{1h}), si::time<si::hour, std::chrono::hours::rep>>);
|
||||
static_assert(is_same_v<decltype(quantity_point{sys_seconds{1s}}), time_point<std::chrono::system_clock, si::second, sys_seconds::rep>>);
|
||||
static_assert(is_same_v<decltype(quantity_point{sys_days{sys_days::duration{1}}}), time_point<std::chrono::system_clock, si::day, sys_days::rep>>);
|
||||
static_assert(is_same_v<decltype(quantity_point{sys_seconds{1s}}),
|
||||
time_point<std::chrono::system_clock, si::second, sys_seconds::rep>>);
|
||||
static_assert(is_same_v<decltype(quantity_point{sys_days{sys_days::duration{1}}}),
|
||||
time_point<std::chrono::system_clock, si::day, sys_days::rep>>);
|
||||
|
||||
// operators
|
||||
static_assert(quantity{1s} + 1_q_s == 2_q_s);
|
||||
|
||||
@@ -20,15 +20,15 @@
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
// SOFTWARE.
|
||||
|
||||
#include <units/chrono.h>
|
||||
#include <units/isq/si/cgs/length.h>
|
||||
#include <units/isq/si/cgs/speed.h> // IWYU pragma: keep
|
||||
#include <units/isq/si/cgs/speed.h> // IWYU pragma: keep
|
||||
#include <units/isq/si/fps/length.h>
|
||||
#include <units/isq/si/fps/speed.h> // IWYU pragma: keep
|
||||
#include <units/isq/si/length.h> // IWYU pragma: keep
|
||||
#include <units/isq/si/fps/speed.h> // IWYU pragma: keep
|
||||
#include <units/isq/si/length.h> // IWYU pragma: keep
|
||||
#include <units/isq/si/prefixes.h>
|
||||
#include <units/isq/si/speed.h>
|
||||
#include <units/quantity_point_kind.h>
|
||||
#include <units/chrono.h>
|
||||
#include <chrono>
|
||||
#include <complex>
|
||||
#include <mutex>
|
||||
@@ -141,9 +141,13 @@ static_assert(QuantityOf<si::cgs::length<si::metre>, si::dim_length>);
|
||||
static_assert(QuantityOf<si::cgs::length<si::cgs::centimetre>, si::fps::dim_length>);
|
||||
static_assert(!QuantityOf<si::cgs::length<si::cgs::centimetre>, si::dim_time>);
|
||||
|
||||
static_assert(QuantityPointOf<quantity_point<dynamic_origin<si::dim_time>, si::second, int>, dynamic_origin<si::dim_time>>);
|
||||
static_assert(QuantityPointOf<quantity_point<clock_origin<std::chrono::system_clock>, si::second, int>, clock_origin<std::chrono::system_clock>>);
|
||||
static_assert(!QuantityPointOf<quantity_point<dynamic_origin<si::dim_time>, si::second, int>, clock_origin<std::chrono::system_clock>>);
|
||||
static_assert(!QuantityPointOf<quantity_point<clock_origin<std::chrono::system_clock>, si::second, int>, dynamic_origin<si::dim_time>>);
|
||||
static_assert(
|
||||
QuantityPointOf<quantity_point<dynamic_origin<si::dim_time>, si::second, int>, dynamic_origin<si::dim_time>>);
|
||||
static_assert(QuantityPointOf<quantity_point<clock_origin<std::chrono::system_clock>, si::second, int>,
|
||||
clock_origin<std::chrono::system_clock>>);
|
||||
static_assert(!QuantityPointOf<quantity_point<dynamic_origin<si::dim_time>, si::second, int>,
|
||||
clock_origin<std::chrono::system_clock>>);
|
||||
static_assert(!QuantityPointOf<quantity_point<clock_origin<std::chrono::system_clock>, si::second, int>,
|
||||
dynamic_origin<si::dim_time>>);
|
||||
|
||||
} // namespace
|
||||
@@ -30,13 +30,13 @@ namespace {
|
||||
|
||||
/**
|
||||
* @brief Representation type meeting minimum requirements
|
||||
*
|
||||
*
|
||||
* This type with a default Mode = 0 provides the minimum set of requirements to
|
||||
* satisfy @c Representation concept which is used for quantity's representation type.
|
||||
*
|
||||
*
|
||||
* In case of Mode != 0 only one of mandatory operation is removed which should
|
||||
* result in @c Representation concept not being satisfied.
|
||||
*
|
||||
*
|
||||
* @tparam Mode a flag to disable specific type's operations
|
||||
*/
|
||||
template<int Mode = 0>
|
||||
@@ -44,38 +44,64 @@ class min_expl {
|
||||
std::intmax_t value_;
|
||||
public:
|
||||
// default construction
|
||||
min_expl() requires (Mode != 1) = default;
|
||||
min_expl()
|
||||
requires(Mode != 1)
|
||||
= default;
|
||||
|
||||
// construction from std::int64_t
|
||||
constexpr explicit min_expl(std::intmax_t v) noexcept requires (Mode != 2) : value_(v) {}
|
||||
constexpr explicit min_expl(std::intmax_t v) noexcept
|
||||
requires(Mode != 2)
|
||||
: value_(v)
|
||||
{
|
||||
}
|
||||
|
||||
// copy construction
|
||||
min_expl(const min_expl&) requires (Mode != 3) = default;
|
||||
min_expl(const min_expl&)
|
||||
requires(Mode != 3)
|
||||
= default;
|
||||
|
||||
// move construction
|
||||
min_expl(min_expl&&) requires (Mode != 4) = default;
|
||||
min_expl(min_expl&&) requires (Mode == 4) = delete;
|
||||
min_expl(min_expl&&)
|
||||
requires(Mode != 4)
|
||||
= default;
|
||||
min_expl(min_expl&&)
|
||||
requires(Mode == 4)
|
||||
= delete;
|
||||
|
||||
// copy assignment
|
||||
min_expl& operator=(const min_expl&) requires (Mode != 5) = default;
|
||||
min_expl& operator=(const min_expl&)
|
||||
requires(Mode != 5)
|
||||
= default;
|
||||
|
||||
// move assignment
|
||||
min_expl& operator=(min_expl&&) requires (Mode != 6) = default;
|
||||
min_expl& operator=(min_expl&&) requires (Mode == 6) = delete;
|
||||
min_expl& operator=(min_expl&&)
|
||||
requires(Mode != 6)
|
||||
= default;
|
||||
min_expl& operator=(min_expl&&)
|
||||
requires(Mode == 6)
|
||||
= delete;
|
||||
|
||||
// equality
|
||||
[[nodiscard]] bool operator==(const min_expl&) const requires (Mode != 7) = default;
|
||||
[[nodiscard]] bool operator==(const min_expl&) const
|
||||
requires(Mode != 7)
|
||||
= default;
|
||||
|
||||
// scalability - multiplication
|
||||
[[nodiscard]] friend constexpr min_expl operator*(const min_expl& lhs, const min_expl& rhs) requires (Mode != 8)
|
||||
{ return min_expl(lhs.value_ * rhs.value_); }
|
||||
[[nodiscard]] friend constexpr min_expl operator*(const min_expl& lhs, const min_expl& rhs)
|
||||
requires(Mode != 8)
|
||||
{
|
||||
return min_expl(lhs.value_ * rhs.value_);
|
||||
}
|
||||
|
||||
// scalability - division
|
||||
[[nodiscard]] friend constexpr min_expl operator/(const min_expl& lhs, const min_expl& rhs) requires (Mode != 9)
|
||||
{ return min_expl(lhs.value_ / rhs.value_); }
|
||||
[[nodiscard]] friend constexpr min_expl operator/(const min_expl& lhs, const min_expl& rhs)
|
||||
requires(Mode != 9)
|
||||
{
|
||||
return min_expl(lhs.value_ / rhs.value_);
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
} // namespace
|
||||
|
||||
template<int Mode>
|
||||
struct std::common_type<std::intmax_t, min_expl<Mode>> : std::type_identity<min_expl<Mode>> {};
|
||||
@@ -161,53 +187,57 @@ static_assert(!Representation<min_expl<9>>);
|
||||
// quantity's operators should mirror the representation type capabilities
|
||||
template<typename Rep>
|
||||
concept invalid_member_operations = requires(length<metre, Rep> lhs) {
|
||||
requires !requires { +lhs; };
|
||||
requires !requires { -lhs; };
|
||||
requires !requires { ++lhs; };
|
||||
requires !requires { lhs++; };
|
||||
requires !requires { --lhs; };
|
||||
requires !requires { lhs--; };
|
||||
requires !requires { +lhs; };
|
||||
requires !requires { -lhs; };
|
||||
requires !requires { ++lhs; };
|
||||
requires !requires { lhs++; };
|
||||
requires !requires { --lhs; };
|
||||
requires !requires { lhs--; };
|
||||
|
||||
requires !requires(length<metre, Rep> rhs) { lhs += rhs; };
|
||||
requires !requires(length<metre, Rep> rhs) { lhs -= rhs; };
|
||||
requires !requires(Rep rhs) { lhs *= rhs; };
|
||||
requires !requires(Rep rhs) { lhs /= rhs; };
|
||||
requires !requires(Rep rhs) { lhs %= rhs; };
|
||||
requires !requires(length<metre, Rep> rhs) { lhs %= rhs; };
|
||||
requires !requires(length<metre, Rep> rhs) { lhs += rhs; };
|
||||
requires !requires(length<metre, Rep> rhs) { lhs -= rhs; };
|
||||
requires !requires(Rep rhs) { lhs *= rhs; };
|
||||
requires !requires(Rep rhs) { lhs /= rhs; };
|
||||
requires !requires(Rep rhs) { lhs %= rhs; };
|
||||
requires !requires(length<metre, Rep> rhs) { lhs %= rhs; };
|
||||
|
||||
requires !requires(length<metre, Rep> rhs) { lhs + rhs; };
|
||||
requires !requires(length<metre, Rep> rhs) { lhs - rhs; };
|
||||
requires !requires(Rep rhs) { lhs % rhs; };
|
||||
requires !requires(length<metre, Rep> rhs) { lhs % rhs; };
|
||||
requires !requires(length<metre, Rep> rhs) { lhs < rhs; };
|
||||
requires !requires(length<metre, Rep> rhs) { lhs > rhs; };
|
||||
requires !requires(length<metre, Rep> rhs) { lhs <= rhs; };
|
||||
requires !requires(length<metre, Rep> rhs) { lhs >= rhs; };
|
||||
requires !requires(length<metre, Rep> rhs) { lhs + rhs; };
|
||||
requires !requires(length<metre, Rep> rhs) { lhs - rhs; };
|
||||
requires !requires(Rep rhs) { lhs % rhs; };
|
||||
requires !requires(length<metre, Rep> rhs) { lhs % rhs; };
|
||||
requires !requires(length<metre, Rep> rhs) { lhs < rhs; };
|
||||
requires !requires(length<metre, Rep> rhs) { lhs > rhs; };
|
||||
requires !requires(length<metre, Rep> rhs) { lhs <= rhs; };
|
||||
requires !requires(length<metre, Rep> rhs) { lhs >= rhs; };
|
||||
|
||||
requires !requires(length<metre, int> rhs) { lhs + rhs; };
|
||||
requires !requires(length<metre, int> rhs) { lhs - rhs; };
|
||||
requires !requires(int rhs) { lhs % rhs; };
|
||||
requires !requires(length<metre, int> rhs) { lhs % rhs; };
|
||||
requires !requires(length<metre, int> rhs) { lhs == rhs; };
|
||||
requires !requires(length<metre, int> rhs) { lhs != rhs; };
|
||||
requires !requires(length<metre, int> rhs) { lhs < rhs; };
|
||||
requires !requires(length<metre, int> rhs) { lhs > rhs; };
|
||||
requires !requires(length<metre, int> rhs) { lhs <= rhs; };
|
||||
requires !requires(length<metre, int> rhs) { lhs >= rhs; };
|
||||
requires !requires(length<metre, int> rhs) { lhs + rhs; };
|
||||
requires !requires(length<metre, int> rhs) { lhs - rhs; };
|
||||
requires !requires(int rhs) { lhs % rhs; };
|
||||
requires !requires(length<metre, int> rhs) { lhs % rhs; };
|
||||
requires !requires(length<metre, int> rhs) { lhs == rhs; };
|
||||
requires !requires(length<metre, int> rhs) { lhs != rhs; };
|
||||
requires !requires(length<metre, int> rhs) { lhs < rhs; };
|
||||
requires !requires(length<metre, int> rhs) { lhs > rhs; };
|
||||
requires !requires(length<metre, int> rhs) { lhs <= rhs; };
|
||||
requires !requires(length<metre, int> rhs) { lhs >= rhs; };
|
||||
|
||||
requires !requires(std::ostream os) { os << lhs; };
|
||||
};
|
||||
requires !requires(std::ostream os) { os << lhs; };
|
||||
};
|
||||
static_assert(invalid_member_operations<min_expl<>>);
|
||||
|
||||
// equality
|
||||
static_assert(length<kilometre, min_expl<>>(min_expl(2)) == length<metre, min_expl<>>(min_expl(2000)));
|
||||
static_assert(length<metre, min_expl<>>(min_expl(123)) * min_expl(2) == length<metre, min_expl<>>(min_expl(246)));
|
||||
static_assert(length<metre, min_expl<>>(min_expl(123)) * quantity{min_expl(2)} == length<metre, min_expl<>>(min_expl(246)));
|
||||
static_assert(length<metre, min_expl<>>(min_expl(123)) * quantity{min_expl(2)} ==
|
||||
length<metre, min_expl<>>(min_expl(246)));
|
||||
static_assert(min_expl(2) * length<metre, min_expl<>>(min_expl(123)) == length<metre, min_expl<>>(min_expl(246)));
|
||||
static_assert(quantity{min_expl(2)} * length<metre, min_expl<>>(min_expl(123)) == length<metre, min_expl<>>(min_expl(246)));
|
||||
static_assert(quantity{min_expl(2)} * length<metre, min_expl<>>(min_expl(123)) ==
|
||||
length<metre, min_expl<>>(min_expl(246)));
|
||||
static_assert(length<metre, min_expl<>>(min_expl(246)) / min_expl(2) == length<metre, min_expl<>>(min_expl(123)));
|
||||
static_assert(length<metre, min_expl<>>(min_expl(246)) / quantity{min_expl(2)} == length<metre, min_expl<>>(min_expl(123)));
|
||||
static_assert(length<metre, min_expl<>>(min_expl(246)) / length<metre, min_expl<>>(min_expl(2)) == quantity{min_expl(123)});
|
||||
static_assert(length<metre, min_expl<>>(min_expl(246)) / quantity{min_expl(2)} ==
|
||||
length<metre, min_expl<>>(min_expl(123)));
|
||||
static_assert(length<metre, min_expl<>>(min_expl(246)) / length<metre, min_expl<>>(min_expl(2)) ==
|
||||
quantity{min_expl(123)});
|
||||
static_assert(length<metre, min_expl<>>(min_expl(246)) / length<metre, min_expl<>>(min_expl(2)) == min_expl(123));
|
||||
|
||||
} // namespace
|
||||
@@ -28,9 +28,9 @@ namespace {
|
||||
|
||||
/**
|
||||
* @brief Implicitly constructible and convertible representation type
|
||||
*
|
||||
*
|
||||
* A wrapper type that is implicitly convertible from and to the contained type.
|
||||
*
|
||||
*
|
||||
* @tparam T element type
|
||||
*/
|
||||
template<typename T>
|
||||
@@ -42,11 +42,13 @@ public:
|
||||
min_impl() = default;
|
||||
constexpr min_impl(T v) noexcept : value_(v) {}
|
||||
template<typename U>
|
||||
constexpr min_impl(min_impl<U> i) noexcept : value_(static_cast<T>(i.value_)) {}
|
||||
constexpr min_impl(min_impl<U> i) noexcept : value_(static_cast<T>(i.value_))
|
||||
{
|
||||
}
|
||||
constexpr operator T() const noexcept { return value_; }
|
||||
};
|
||||
|
||||
}
|
||||
} // namespace
|
||||
|
||||
template<typename T, typename U>
|
||||
struct std::common_type<min_impl<T>, min_impl<U>> : std::common_type<T, U> {};
|
||||
@@ -125,7 +127,8 @@ static_assert(!std::convertible_to<min_impl<double>, dimensionless<percent, min_
|
||||
static_assert(std::constructible_from<dimensionless<percent, min_impl<double>>, min_impl<int>>);
|
||||
static_assert(!std::convertible_to<min_impl<int>, dimensionless<percent, min_impl<double>>>);
|
||||
|
||||
static_assert(!std::constructible_from<dimensionless<percent, min_impl<int>>, min_impl<double>>); // narrowing conversion
|
||||
static_assert(
|
||||
!std::constructible_from<dimensionless<percent, min_impl<int>>, min_impl<double>>); // narrowing conversion
|
||||
static_assert(!std::convertible_to<min_impl<double>, dimensionless<percent, min_impl<int>>>);
|
||||
|
||||
// implicit conversion tests
|
||||
@@ -191,7 +194,8 @@ static_assert(std::convertible_to<length<metre, min_impl<double>>, length<metre,
|
||||
static_assert(std::constructible_from<length<metre, min_impl<double>>, length<metre, min_impl<int>>>);
|
||||
static_assert(std::convertible_to<length<metre, min_impl<int>>, length<metre, min_impl<double>>>);
|
||||
|
||||
static_assert(!std::constructible_from<length<metre, min_impl<int>>, length<metre, min_impl<double>>>); // narrowing conversion
|
||||
static_assert(
|
||||
!std::constructible_from<length<metre, min_impl<int>>, length<metre, min_impl<double>>>); // narrowing conversion
|
||||
static_assert(!std::convertible_to<length<metre, min_impl<double>>, length<metre, min_impl<int>>>);
|
||||
|
||||
// T -> min_impl<T>
|
||||
@@ -204,7 +208,7 @@ static_assert(std::convertible_to<length<metre, double>, length<metre, min_impl<
|
||||
static_assert(std::constructible_from<length<metre, min_impl<double>>, length<metre, int>>);
|
||||
static_assert(std::convertible_to<length<metre, int>, length<metre, min_impl<double>>>);
|
||||
|
||||
static_assert(!std::constructible_from<length<metre, min_impl<int>>, length<metre, double>>); // narrowing conversion
|
||||
static_assert(!std::constructible_from<length<metre, min_impl<int>>, length<metre, double>>); // narrowing conversion
|
||||
static_assert(!std::convertible_to<length<metre, double>, length<metre, min_impl<int>>>);
|
||||
|
||||
// min_impl<T> -> T
|
||||
@@ -217,13 +221,14 @@ static_assert(std::convertible_to<length<metre, min_impl<double>>, length<metre,
|
||||
static_assert(std::constructible_from<length<metre, double>, length<metre, min_impl<int>>>);
|
||||
static_assert(std::convertible_to<length<metre, min_impl<int>>, length<metre, double>>);
|
||||
|
||||
static_assert(!std::constructible_from<length<metre, int>, length<metre, min_impl<double>>>); // narrowing conversion
|
||||
static_assert(!std::constructible_from<length<metre, int>, length<metre, min_impl<double>>>); // narrowing conversion
|
||||
static_assert(!std::convertible_to<length<metre, min_impl<double>>, length<metre, int>>);
|
||||
|
||||
|
||||
// arithmetic operators
|
||||
static_assert(length<metre, min_impl<int>>(1) + length<metre, min_impl<int>>(1) == length<metre, min_impl<int>>(2));
|
||||
static_assert(length<metre, min_impl<int>>(1) + length<metre, min_impl<double>>(1.5) == length<metre, min_impl<double>>(2.5));
|
||||
static_assert(length<metre, min_impl<int>>(1) + length<metre, min_impl<double>>(1.5) ==
|
||||
length<metre, min_impl<double>>(2.5));
|
||||
static_assert(length<metre, int>(1) + length<metre, min_impl<int>>(1) == length<metre, min_impl<int>>(2));
|
||||
static_assert(length<metre, int>(1) + length<metre, min_impl<double>>(1.5) == length<metre, min_impl<double>>(2.5));
|
||||
static_assert(length<metre, min_impl<int>>(1) + length<metre, int>(1) == length<metre, min_impl<int>>(2));
|
||||
@@ -231,26 +236,37 @@ static_assert(length<metre, min_impl<int>>(1) + length<metre, double>(1.5) == le
|
||||
static_assert(length<metre, min_impl<int>>(1) + length<metre, min_impl<int>>(1) == length<metre, int>(2));
|
||||
static_assert(length<metre, min_impl<int>>(1) + length<metre, min_impl<double>>(1.5) == length<metre, double>(2.5));
|
||||
|
||||
static_assert(length<kilometre, min_impl<int>>(1) + length<metre, min_impl<int>>(1) == length<metre, min_impl<int>>(1001));
|
||||
static_assert(length<kilometre, min_impl<int>>(1) + length<metre, min_impl<double>>(1.5) == length<metre, min_impl<double>>(1001.5));
|
||||
static_assert(length<kilometre, min_impl<int>>(1) + length<metre, min_impl<int>>(1) ==
|
||||
length<metre, min_impl<int>>(1001));
|
||||
static_assert(length<kilometre, min_impl<int>>(1) + length<metre, min_impl<double>>(1.5) ==
|
||||
length<metre, min_impl<double>>(1001.5));
|
||||
static_assert(length<kilometre, int>(1) + length<metre, min_impl<int>>(1) == length<metre, min_impl<int>>(1001));
|
||||
static_assert(length<kilometre, int>(1) + length<metre, min_impl<double>>(1.5) == length<metre, min_impl<double>>(1001.5));
|
||||
static_assert(length<kilometre, int>(1) + length<metre, min_impl<double>>(1.5) ==
|
||||
length<metre, min_impl<double>>(1001.5));
|
||||
static_assert(length<kilometre, min_impl<int>>(1) + length<metre, int>(1) == length<metre, min_impl<int>>(1001));
|
||||
static_assert(length<kilometre, min_impl<int>>(1) + length<metre, double>(1.5) == length<metre, min_impl<double>>(1001.5));
|
||||
static_assert(length<kilometre, min_impl<int>>(1) + length<metre, double>(1.5) ==
|
||||
length<metre, min_impl<double>>(1001.5));
|
||||
static_assert(length<kilometre, min_impl<int>>(1) + length<metre, min_impl<int>>(1) == length<metre, int>(1001));
|
||||
static_assert(length<kilometre, min_impl<int>>(1) + length<metre, min_impl<double>>(1.5) == length<metre, double>(1001.5));
|
||||
static_assert(length<kilometre, min_impl<int>>(1) + length<metre, min_impl<double>>(1.5) ==
|
||||
length<metre, double>(1001.5));
|
||||
|
||||
static_assert(length<metre, min_impl<int>>(1) + length<kilometre, min_impl<int>>(1) == length<metre, min_impl<int>>(1001));
|
||||
static_assert(length<metre, min_impl<int>>(1) + length<kilometre, min_impl<double>>(1.5) == length<metre, min_impl<double>>(1501));
|
||||
static_assert(length<metre, min_impl<int>>(1) + length<kilometre, min_impl<int>>(1) ==
|
||||
length<metre, min_impl<int>>(1001));
|
||||
static_assert(length<metre, min_impl<int>>(1) + length<kilometre, min_impl<double>>(1.5) ==
|
||||
length<metre, min_impl<double>>(1501));
|
||||
static_assert(length<metre, int>(1) + length<kilometre, min_impl<int>>(1) == length<metre, min_impl<int>>(1001));
|
||||
static_assert(length<metre, int>(1) + length<kilometre, min_impl<double>>(1.5) == length<metre, min_impl<double>>(1501));
|
||||
static_assert(length<metre, int>(1) + length<kilometre, min_impl<double>>(1.5) ==
|
||||
length<metre, min_impl<double>>(1501));
|
||||
static_assert(length<metre, min_impl<int>>(1) + length<kilometre, int>(1) == length<metre, min_impl<int>>(1001));
|
||||
static_assert(length<metre, min_impl<int>>(1) + length<kilometre, double>(1.5) == length<metre, min_impl<double>>(1501));
|
||||
static_assert(length<metre, min_impl<int>>(1) + length<kilometre, double>(1.5) ==
|
||||
length<metre, min_impl<double>>(1501));
|
||||
static_assert(length<metre, min_impl<int>>(1) + length<kilometre, min_impl<int>>(1) == length<metre, int>(1001));
|
||||
static_assert(length<metre, min_impl<int>>(1) + length<kilometre, min_impl<double>>(1.5) == length<metre, double>(1501));
|
||||
static_assert(length<metre, min_impl<int>>(1) + length<kilometre, min_impl<double>>(1.5) ==
|
||||
length<metre, double>(1501));
|
||||
|
||||
static_assert(length<metre, min_impl<int>>(2) - length<metre, min_impl<int>>(1) == length<metre, min_impl<int>>(1));
|
||||
static_assert(length<metre, min_impl<int>>(2) - length<metre, min_impl<double>>(1.5) == length<metre, min_impl<double>>(0.5));
|
||||
static_assert(length<metre, min_impl<int>>(2) - length<metre, min_impl<double>>(1.5) ==
|
||||
length<metre, min_impl<double>>(0.5));
|
||||
static_assert(length<metre, int>(2) - length<metre, min_impl<int>>(1) == length<metre, min_impl<int>>(1));
|
||||
static_assert(length<metre, int>(2) - length<metre, min_impl<double>>(1.5) == length<metre, min_impl<double>>(0.5));
|
||||
static_assert(length<metre, min_impl<int>>(2) - length<metre, int>(1) == length<metre, min_impl<int>>(1));
|
||||
@@ -258,29 +274,40 @@ static_assert(length<metre, min_impl<int>>(2) - length<metre, double>(1.5) == le
|
||||
static_assert(length<metre, min_impl<int>>(2) - length<metre, min_impl<int>>(1) == length<metre, int>(1));
|
||||
static_assert(length<metre, min_impl<int>>(2) - length<metre, min_impl<double>>(1.5) == length<metre, double>(0.5));
|
||||
|
||||
static_assert(length<kilometre, min_impl<int>>(2) - length<metre, min_impl<int>>(1) == length<metre, min_impl<int>>(1999));
|
||||
static_assert(length<kilometre, min_impl<int>>(2) - length<metre, min_impl<double>>(1.5) == length<metre, min_impl<double>>(1998.5));
|
||||
static_assert(length<kilometre, min_impl<int>>(2) - length<metre, min_impl<int>>(1) ==
|
||||
length<metre, min_impl<int>>(1999));
|
||||
static_assert(length<kilometre, min_impl<int>>(2) - length<metre, min_impl<double>>(1.5) ==
|
||||
length<metre, min_impl<double>>(1998.5));
|
||||
static_assert(length<kilometre, int>(2) - length<metre, min_impl<int>>(1) == length<metre, min_impl<int>>(1999));
|
||||
static_assert(length<kilometre, int>(2) - length<metre, min_impl<double>>(1.5) == length<metre, min_impl<double>>(1998.5));
|
||||
static_assert(length<kilometre, int>(2) - length<metre, min_impl<double>>(1.5) ==
|
||||
length<metre, min_impl<double>>(1998.5));
|
||||
static_assert(length<kilometre, min_impl<int>>(2) - length<metre, int>(1) == length<metre, min_impl<int>>(1999));
|
||||
static_assert(length<kilometre, min_impl<int>>(2) - length<metre, double>(1.5) == length<metre, min_impl<double>>(1998.5));
|
||||
static_assert(length<kilometre, min_impl<int>>(2) - length<metre, double>(1.5) ==
|
||||
length<metre, min_impl<double>>(1998.5));
|
||||
static_assert(length<kilometre, min_impl<int>>(2) - length<metre, min_impl<int>>(1) == length<metre, int>(1999));
|
||||
static_assert(length<kilometre, min_impl<int>>(2) - length<metre, min_impl<double>>(1.5) == length<metre, double>(1998.5));
|
||||
static_assert(length<kilometre, min_impl<int>>(2) - length<metre, min_impl<double>>(1.5) ==
|
||||
length<metre, double>(1998.5));
|
||||
|
||||
static_assert(length<metre, min_impl<int>>(2000) - length<kilometre, min_impl<int>>(1) == length<metre, min_impl<int>>(1000));
|
||||
static_assert(length<metre, min_impl<int>>(2000) - length<kilometre, min_impl<double>>(1.5) == length<metre, min_impl<double>>(500));
|
||||
static_assert(length<metre, min_impl<int>>(2000) - length<kilometre, min_impl<int>>(1) ==
|
||||
length<metre, min_impl<int>>(1000));
|
||||
static_assert(length<metre, min_impl<int>>(2000) - length<kilometre, min_impl<double>>(1.5) ==
|
||||
length<metre, min_impl<double>>(500));
|
||||
static_assert(length<metre, int>(2000) - length<kilometre, min_impl<int>>(1) == length<metre, min_impl<int>>(1000));
|
||||
static_assert(length<metre, int>(2000) - length<kilometre, min_impl<double>>(1.5) == length<metre, min_impl<double>>(500));
|
||||
static_assert(length<metre, int>(2000) - length<kilometre, min_impl<double>>(1.5) ==
|
||||
length<metre, min_impl<double>>(500));
|
||||
static_assert(length<metre, min_impl<int>>(2000) - length<kilometre, int>(1) == length<metre, min_impl<int>>(1000));
|
||||
static_assert(length<metre, min_impl<int>>(2000) - length<kilometre, double>(1.5) == length<metre, min_impl<double>>(500));
|
||||
static_assert(length<metre, min_impl<int>>(2000) - length<kilometre, double>(1.5) ==
|
||||
length<metre, min_impl<double>>(500));
|
||||
static_assert(length<metre, min_impl<int>>(2000) - length<kilometre, min_impl<int>>(1) == length<metre, int>(1000));
|
||||
static_assert(length<metre, min_impl<int>>(2000) - length<kilometre, min_impl<double>>(1.5) == length<metre, double>(500));
|
||||
static_assert(length<metre, min_impl<int>>(2000) - length<kilometre, min_impl<double>>(1.5) ==
|
||||
length<metre, double>(500));
|
||||
|
||||
static_assert(length<metre, min_impl<int>>(123) * min_impl<double>(1.5) == length<metre, min_impl<double>>(184.5));
|
||||
static_assert(length<metre, min_impl<int>>(123) * 1.5 == length<metre, min_impl<double>>(184.5));
|
||||
static_assert(length<metre, int>(123) * min_impl<double>(1.5) == length<metre, min_impl<double>>(184.5));
|
||||
|
||||
static_assert(length<metre, min_impl<int>>(123) * quantity{min_impl<double>(1.5)} == length<metre, min_impl<double>>(184.5));
|
||||
static_assert(length<metre, min_impl<int>>(123) * quantity{min_impl<double>(1.5)} ==
|
||||
length<metre, min_impl<double>>(184.5));
|
||||
static_assert(length<metre, min_impl<int>>(123) * quantity{1.5} == length<metre, min_impl<double>>(184.5));
|
||||
static_assert(length<metre, int>(123) * quantity{min_impl<double>(1.5)} == length<metre, min_impl<double>>(184.5));
|
||||
|
||||
@@ -288,7 +315,8 @@ static_assert(min_impl<double>(1.5) * length<metre, min_impl<int>>(123) == lengt
|
||||
static_assert(min_impl<double>(1.5) * length<metre, int>(123) == length<metre, min_impl<double>>(184.5));
|
||||
static_assert(1.5 * length<metre, min_impl<int>>(123) == length<metre, min_impl<double>>(184.5));
|
||||
|
||||
static_assert(quantity{min_impl<double>(1.5)} * length<metre, min_impl<int>>(123) == length<metre, min_impl<double>>(184.5));
|
||||
static_assert(quantity{min_impl<double>(1.5)} * length<metre, min_impl<int>>(123) ==
|
||||
length<metre, min_impl<double>>(184.5));
|
||||
static_assert(quantity{min_impl<double>(1.5)} * length<metre, int>(123) == length<metre, min_impl<double>>(184.5));
|
||||
static_assert(quantity{1.5} * length<metre, min_impl<int>>(123) == length<metre, min_impl<double>>(184.5));
|
||||
|
||||
@@ -296,7 +324,8 @@ static_assert(length<metre, min_impl<int>>(123) / min_impl<double>(2.) == length
|
||||
static_assert(length<metre, min_impl<int>>(123) / 2. == length<metre, min_impl<double>>(61.5));
|
||||
static_assert(length<metre, int>(123) / min_impl<double>(2.) == length<metre, min_impl<double>>(61.5));
|
||||
|
||||
static_assert(length<metre, min_impl<int>>(123) / quantity{min_impl<double>(2.)} == length<metre, min_impl<double>>(61.5));
|
||||
static_assert(length<metre, min_impl<int>>(123) / quantity{min_impl<double>(2.)} ==
|
||||
length<metre, min_impl<double>>(61.5));
|
||||
static_assert(length<metre, min_impl<int>>(123) / quantity{2.} == length<metre, min_impl<double>>(61.5));
|
||||
static_assert(length<metre, int>(123) / quantity{min_impl<double>(2.)} == length<metre, min_impl<double>>(61.5));
|
||||
|
||||
|
||||
@@ -27,7 +27,7 @@
|
||||
#include <units/isq/si/mass.h>
|
||||
#include <units/isq/si/time.h>
|
||||
#include <units/isq/si/voltage.h>
|
||||
#include <units/math.h> // IWYU pragma: keep
|
||||
#include <units/math.h> // IWYU pragma: keep
|
||||
#include <units/unit.h>
|
||||
|
||||
namespace {
|
||||
@@ -37,35 +37,43 @@ using namespace units::isq::si;
|
||||
|
||||
// power spectral density
|
||||
struct sq_volt_per_hertz : unit<sq_volt_per_hertz> {};
|
||||
struct dim_power_spectral_density : derived_dimension<dim_power_spectral_density, sq_volt_per_hertz, units::exponent<dim_voltage, 2>, units::exponent<dim_frequency, -1>> {};
|
||||
struct dim_power_spectral_density :
|
||||
derived_dimension<dim_power_spectral_density, sq_volt_per_hertz, units::exponent<dim_voltage, 2>,
|
||||
units::exponent<dim_frequency, -1>> {};
|
||||
|
||||
template<UnitOf<dim_power_spectral_density> U, Representation Rep = double>
|
||||
using power_spectral_density = quantity<dim_power_spectral_density, U, Rep>;
|
||||
|
||||
// amplitude spectral density
|
||||
struct volt_per_sqrt_hertz : unit<volt_per_sqrt_hertz> {};
|
||||
struct dim_amplitude_spectral_density : derived_dimension<dim_amplitude_spectral_density, volt_per_sqrt_hertz, units::exponent<dim_voltage, 1>, units::exponent<dim_frequency, -1, 2>> {};
|
||||
struct dim_amplitude_spectral_density :
|
||||
derived_dimension<dim_amplitude_spectral_density, volt_per_sqrt_hertz, units::exponent<dim_voltage, 1>,
|
||||
units::exponent<dim_frequency, -1, 2>> {};
|
||||
|
||||
template<UnitOf<dim_amplitude_spectral_density> U, Representation Rep = double>
|
||||
using amplitude_spectral_density = quantity<dim_amplitude_spectral_density, U, Rep>;
|
||||
|
||||
}
|
||||
} // namespace
|
||||
|
||||
namespace {
|
||||
|
||||
static_assert(compare<dimension_sqrt<dim_power_spectral_density>, dim_amplitude_spectral_density>);
|
||||
static_assert(compare<dimension_pow<dim_amplitude_spectral_density, 2>, dim_power_spectral_density>);
|
||||
|
||||
static_assert(compare<decltype(pow<2>(amplitude_spectral_density<volt_per_sqrt_hertz>(4))), decltype(power_spectral_density<sq_volt_per_hertz>(16))>);
|
||||
static_assert(compare<decltype(sqrt(power_spectral_density<sq_volt_per_hertz>(16))), decltype(amplitude_spectral_density<volt_per_sqrt_hertz>(4))>);
|
||||
static_assert(compare<decltype(pow<2>(amplitude_spectral_density<volt_per_sqrt_hertz>(4))),
|
||||
decltype(power_spectral_density<sq_volt_per_hertz>(16))>);
|
||||
static_assert(compare<decltype(sqrt(power_spectral_density<sq_volt_per_hertz>(16))),
|
||||
decltype(amplitude_spectral_density<volt_per_sqrt_hertz>(4))>);
|
||||
|
||||
}
|
||||
} // namespace
|
||||
|
||||
namespace {
|
||||
|
||||
struct kilogram_per_second : unit<kilogram_per_second> {};
|
||||
struct dim_mass_rate : derived_dimension<dim_mass_rate, kilogram_per_second, units::exponent<dim_mass, 1>, units::exponent<dim_time, -1>> {};
|
||||
struct dim_mass_rate :
|
||||
derived_dimension<dim_mass_rate, kilogram_per_second, units::exponent<dim_mass, 1>, units::exponent<dim_time, -1>> {
|
||||
};
|
||||
struct kilogram_per_hour : derived_unit<kilogram_per_hour, dim_mass_rate, kilogram, hour> {};
|
||||
[[maybe_unused]] constexpr auto a = 1_q_kg / 1_q_h;
|
||||
|
||||
}
|
||||
} // namespace
|
||||
@@ -20,9 +20,9 @@
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
// SOFTWARE.
|
||||
|
||||
#include <units/bits/dimension_op.h>
|
||||
#include <units/base_dimension.h>
|
||||
#include <units/bits/dim_unpack.h>
|
||||
#include <units/bits/dimension_op.h>
|
||||
#include <units/derived_dimension.h>
|
||||
#include <units/unit.h>
|
||||
|
||||
@@ -54,18 +54,21 @@ using derived_dim = detail::derived_dimension_base<Es...>;
|
||||
|
||||
static_assert(is_same_v<dim_unpack<>, exponent_list<>>);
|
||||
static_assert(is_same_v<dim_unpack<units::exponent<d0, 1>>, exponent_list<units::exponent<d0, 1>>>);
|
||||
static_assert(is_same_v<dim_unpack<units::exponent<d0, 1>, units::exponent<d1, 2>>, exponent_list<units::exponent<d0, 1>, units::exponent<d1, 2>>>);
|
||||
static_assert(is_same_v<dim_unpack<units::exponent<d0, 1>, units::exponent<d1, 2>>,
|
||||
exponent_list<units::exponent<d0, 1>, units::exponent<d1, 2>>>);
|
||||
using dim1 = derived_dim<units::exponent<d0, 1>>;
|
||||
using dim2 = derived_dim<units::exponent<d0, 1>, units::exponent<d1, 2>>;
|
||||
static_assert(is_same_v<dim_unpack<units::exponent<dim1, 2>, units::exponent<d0, 1>>, exponent_list<units::exponent<d0, 2>, units::exponent<d0, 1>>>);
|
||||
static_assert(is_same_v<dim_unpack<units::exponent<dim1, 2>, units::exponent<d0, 1>>,
|
||||
exponent_list<units::exponent<d0, 2>, units::exponent<d0, 1>>>);
|
||||
static_assert(is_same_v<dim_unpack<units::exponent<dim2, -2>, units::exponent<d0, 1>, units::exponent<d1, 2>>,
|
||||
exponent_list<units::exponent<d0, -2>, units::exponent<d1, -4>, units::exponent<d0, 1>, units::exponent<d1, 2>>>);
|
||||
exponent_list<units::exponent<d0, -2>, units::exponent<d1, -4>, units::exponent<d0, 1>,
|
||||
units::exponent<d1, 2>>>);
|
||||
|
||||
// dim_invert
|
||||
static_assert(is_same_v<dim_invert<derived_dim<units::exponent<d0, -1>>>, d0>);
|
||||
static_assert(is_same_v<dim_invert<derived_dim<units::exponent<d0, -2>>>, unknown_dimension<units::exponent<d0, 2>>>);
|
||||
static_assert(
|
||||
is_same_v<dim_invert<derived_dim<units::exponent<d0, 2>, units::exponent<d1, -1>>>, unknown_dimension<units::exponent<d0, -2>, units::exponent<d1, 1>>>);
|
||||
static_assert(is_same_v<dim_invert<derived_dim<units::exponent<d0, 2>, units::exponent<d1, -1>>>,
|
||||
unknown_dimension<units::exponent<d0, -2>, units::exponent<d1, 1>>>);
|
||||
|
||||
// make_dimension
|
||||
|
||||
@@ -73,46 +76,63 @@ template<typename... Ts>
|
||||
using make_dimension = detail::make_dimension<Ts...>;
|
||||
|
||||
static_assert(is_same_v<make_dimension<units::exponent<d0, 1>>, derived_dim<units::exponent<d0, 1>>>);
|
||||
static_assert(is_same_v<make_dimension<units::exponent<d0, 1>, units::exponent<d1, 1>>, derived_dim<units::exponent<d0, 1>, units::exponent<d1, 1>>>);
|
||||
static_assert(is_same_v<make_dimension<units::exponent<d1, 1>, units::exponent<d0, 1>>, derived_dim<units::exponent<d0, 1>, units::exponent<d1, 1>>>);
|
||||
static_assert(is_same_v<make_dimension<units::exponent<d1, 1>, units::exponent<d1, 1>>, derived_dim<units::exponent<d1, 2>>>);
|
||||
static_assert(is_same_v<make_dimension<units::exponent<d1, 1>, units::exponent<d1, 1, 2>>, derived_dim<units::exponent<d1, 3, 2>>>);
|
||||
static_assert(is_same_v<make_dimension<units::exponent<d1, 1, 2>, units::exponent<d1, 1, 2>>, derived_dim<units::exponent<d1, 1>>>);
|
||||
static_assert(is_same_v<make_dimension<units::exponent<d1, 2>, units::exponent<d1, 1, 2>>, derived_dim<units::exponent<d1, 5, 2>>>);
|
||||
static_assert(is_same_v<make_dimension<units::exponent<d0, 1>, units::exponent<d1, 1>>,
|
||||
derived_dim<units::exponent<d0, 1>, units::exponent<d1, 1>>>);
|
||||
static_assert(is_same_v<make_dimension<units::exponent<d1, 1>, units::exponent<d0, 1>>,
|
||||
derived_dim<units::exponent<d0, 1>, units::exponent<d1, 1>>>);
|
||||
static_assert(
|
||||
is_same_v<make_dimension<units::exponent<d1, 1>, units::exponent<d1, 1>>, derived_dim<units::exponent<d1, 2>>>);
|
||||
static_assert(
|
||||
is_same_v<make_dimension<units::exponent<d1, 1>, units::exponent<d1, 1, 2>>, derived_dim<units::exponent<d1, 3, 2>>>);
|
||||
static_assert(
|
||||
is_same_v<make_dimension<units::exponent<d1, 1, 2>, units::exponent<d1, 1, 2>>, derived_dim<units::exponent<d1, 1>>>);
|
||||
static_assert(
|
||||
is_same_v<make_dimension<units::exponent<d1, 2>, units::exponent<d1, 1, 2>>, derived_dim<units::exponent<d1, 5, 2>>>);
|
||||
|
||||
static_assert(is_same_v<make_dimension<units::exponent<d0, 1>, units::exponent<d1, 1>, units::exponent<d0, 1>, units::exponent<d1, 1>>,
|
||||
derived_dim<units::exponent<d0, 2>, units::exponent<d1, 2>>>);
|
||||
static_assert(is_same_v<make_dimension<units::exponent<d0, -1>, units::exponent<d1, -1>, units::exponent<d0, -1>, units::exponent<d1, -1>>,
|
||||
derived_dim<units::exponent<d0, -2>, units::exponent<d1, -2>>>);
|
||||
static_assert(is_same_v<make_dimension<units::exponent<d0, 1>, units::exponent<d1, 1>, units::exponent<d0, 1>,
|
||||
units::exponent<d1, 1>>,
|
||||
derived_dim<units::exponent<d0, 2>, units::exponent<d1, 2>>>);
|
||||
static_assert(is_same_v<make_dimension<units::exponent<d0, -1>, units::exponent<d1, -1>, units::exponent<d0, -1>,
|
||||
units::exponent<d1, -1>>,
|
||||
derived_dim<units::exponent<d0, -2>, units::exponent<d1, -2>>>);
|
||||
|
||||
static_assert(is_same_v<make_dimension<units::exponent<d0, 1>, units::exponent<d1, 1>, units::exponent<d1, -1>>, derived_dim<units::exponent<d0, 1>>>);
|
||||
static_assert(is_same_v<make_dimension<units::exponent<d0, 1>, units::exponent<d0, -1>, units::exponent<d1, 1>>, derived_dim<units::exponent<d1, 1>>>);
|
||||
static_assert(is_same_v<make_dimension<units::exponent<d0, 1>, units::exponent<d1, 1>, units::exponent<d0, -1>>, derived_dim<units::exponent<d1, 1>>>);
|
||||
static_assert(is_same_v<make_dimension<units::exponent<d0, 1>, units::exponent<d1, 1>, units::exponent<d1, -1>>,
|
||||
derived_dim<units::exponent<d0, 1>>>);
|
||||
static_assert(is_same_v<make_dimension<units::exponent<d0, 1>, units::exponent<d0, -1>, units::exponent<d1, 1>>,
|
||||
derived_dim<units::exponent<d1, 1>>>);
|
||||
static_assert(is_same_v<make_dimension<units::exponent<d0, 1>, units::exponent<d1, 1>, units::exponent<d0, -1>>,
|
||||
derived_dim<units::exponent<d1, 1>>>);
|
||||
|
||||
// dimension_multiply
|
||||
|
||||
static_assert(is_same_v<dimension_multiply<derived_dim<units::exponent<d0, 1>>, derived_dim<units::exponent<d1, 1>>>,
|
||||
unknown_dimension<units::exponent<d0, 1>, units::exponent<d1, 1>>>);
|
||||
static_assert(
|
||||
is_same_v<dimension_multiply<derived_dim<units::exponent<d0, 1>>, d1>, unknown_dimension<units::exponent<d0, 1>, units::exponent<d1, 1>>>);
|
||||
static_assert(
|
||||
is_same_v<dimension_multiply<d0, derived_dim<units::exponent<d1, 1>>>, unknown_dimension<units::exponent<d0, 1>, units::exponent<d1, 1>>>);
|
||||
unknown_dimension<units::exponent<d0, 1>, units::exponent<d1, 1>>>);
|
||||
static_assert(is_same_v<dimension_multiply<derived_dim<units::exponent<d0, 1>>, d1>,
|
||||
unknown_dimension<units::exponent<d0, 1>, units::exponent<d1, 1>>>);
|
||||
static_assert(is_same_v<dimension_multiply<d0, derived_dim<units::exponent<d1, 1>>>,
|
||||
unknown_dimension<units::exponent<d0, 1>, units::exponent<d1, 1>>>);
|
||||
static_assert(is_same_v<dimension_multiply<d0, d1>, unknown_dimension<units::exponent<d0, 1>, units::exponent<d1, 1>>>);
|
||||
static_assert(is_same_v<
|
||||
dimension_multiply<derived_dim<units::exponent<d0, 1>, units::exponent<d1, 1>, units::exponent<d2, 1>>, derived_dim<units::exponent<d3, 1>>>,
|
||||
unknown_dimension<units::exponent<d0, 1>, units::exponent<d1, 1>, units::exponent<d2, 1>, units::exponent<d3, 1>>>);
|
||||
static_assert(is_same_v<
|
||||
dimension_multiply<derived_dim<units::exponent<d0, 1>, units::exponent<d1, 1>, units::exponent<d2, 1>>, derived_dim<units::exponent<d1, 1>>>,
|
||||
unknown_dimension<units::exponent<d0, 1>, units::exponent<d1, 2>, units::exponent<d2, 1>>>);
|
||||
static_assert(is_same_v<
|
||||
dimension_multiply<derived_dim<units::exponent<d0, 1>, units::exponent<d1, 1>, units::exponent<d2, 1>>, derived_dim<units::exponent<d1, -1>>>,
|
||||
unknown_dimension<units::exponent<d0, 1>, units::exponent<d2, 1>>>);
|
||||
static_assert(is_same_v<dimension_multiply<derived_dim<units::exponent<d0, 2>>, derived_dim<units::exponent<d0, -1>>>, d0>);
|
||||
static_assert(
|
||||
is_same_v<
|
||||
dimension_multiply<derived_dim<units::exponent<d0, 1>, units::exponent<d1, 1>, units::exponent<d2, 1>>,
|
||||
derived_dim<units::exponent<d3, 1>>>,
|
||||
unknown_dimension<units::exponent<d0, 1>, units::exponent<d1, 1>, units::exponent<d2, 1>, units::exponent<d3, 1>>>);
|
||||
static_assert(
|
||||
is_same_v<dimension_multiply<derived_dim<units::exponent<d0, 1>, units::exponent<d1, 1>, units::exponent<d2, 1>>,
|
||||
derived_dim<units::exponent<d1, 1>>>,
|
||||
unknown_dimension<units::exponent<d0, 1>, units::exponent<d1, 2>, units::exponent<d2, 1>>>);
|
||||
static_assert(
|
||||
is_same_v<dimension_multiply<derived_dim<units::exponent<d0, 1>, units::exponent<d1, 1>, units::exponent<d2, 1>>,
|
||||
derived_dim<units::exponent<d1, -1>>>,
|
||||
unknown_dimension<units::exponent<d0, 1>, units::exponent<d2, 1>>>);
|
||||
static_assert(
|
||||
is_same_v<dimension_multiply<derived_dim<units::exponent<d0, 2>>, derived_dim<units::exponent<d0, -1>>>, d0>);
|
||||
|
||||
// dimension_divide
|
||||
|
||||
static_assert(is_same_v<dimension_divide<derived_dim<units::exponent<d0, 1>>, derived_dim<units::exponent<d1, 1>>>,
|
||||
unknown_dimension<units::exponent<d0, 1>, units::exponent<d1, -1>>>);
|
||||
static_assert(is_same_v<dimension_divide<derived_dim<units::exponent<d0, 2>>, unknown_dimension<units::exponent<d0, 1>>>, d0>);
|
||||
unknown_dimension<units::exponent<d0, 1>, units::exponent<d1, -1>>>);
|
||||
static_assert(
|
||||
is_same_v<dimension_divide<derived_dim<units::exponent<d0, 2>>, unknown_dimension<units::exponent<d0, 1>>>, d0>);
|
||||
|
||||
} // namespace
|
||||
@@ -58,4 +58,4 @@ static_assert(120 * kB / (2 * min) == 1000 * (B / s));
|
||||
static_assert(12 / (2 * s) == 6 * Bd);
|
||||
static_assert(6000 / (3 * s) == 2 * kBd);
|
||||
|
||||
}
|
||||
} // namespace
|
||||
@@ -21,14 +21,14 @@
|
||||
// SOFTWARE.
|
||||
|
||||
#include "test_tools.h"
|
||||
#include <units/math.h> // IWYU pragma: keep
|
||||
#include <units/isq/si/length.h>
|
||||
#include <units/isq/si/area.h>
|
||||
#include <units/isq/si/volume.h>
|
||||
#include <units/isq/si/time.h>
|
||||
#include <units/isq/si/international/length.h>
|
||||
#include <units/isq/si/international/area.h>
|
||||
#include <units/isq/si/international/length.h>
|
||||
#include <units/isq/si/international/volume.h>
|
||||
#include <units/isq/si/length.h>
|
||||
#include <units/isq/si/time.h>
|
||||
#include <units/isq/si/volume.h>
|
||||
#include <units/math.h> // IWYU pragma: keep
|
||||
|
||||
namespace {
|
||||
|
||||
|
||||
@@ -22,10 +22,10 @@
|
||||
|
||||
#include <units/bits/equivalent.h>
|
||||
#include <units/chrono.h>
|
||||
#include <units/isq/si/cgs/length.h>
|
||||
#include <units/isq/si/length.h>
|
||||
#include <units/kind.h>
|
||||
#include <units/quantity_point.h>
|
||||
#include <units/isq/si/length.h>
|
||||
#include <units/isq/si/cgs/length.h>
|
||||
|
||||
using namespace units;
|
||||
namespace si = isq::si;
|
||||
@@ -54,8 +54,8 @@ static_assert(RebindablePointOriginFor<dynamic_origin<si::dim_length>, si::dim_l
|
||||
static_assert(is_same_v<rebind_point_origin_dimension<dynamic_origin<si::dim_length>, si::dim_length>,
|
||||
dynamic_origin<si::dim_length>>);
|
||||
static_assert(RebindablePointOriginFor<dynamic_origin<si::dim_length>, si::dim_time>);
|
||||
static_assert(is_same_v<rebind_point_origin_dimension<dynamic_origin<si::dim_length>, si::dim_time>,
|
||||
dynamic_origin<si::dim_time>>);
|
||||
static_assert(
|
||||
is_same_v<rebind_point_origin_dimension<dynamic_origin<si::dim_length>, si::dim_time>, dynamic_origin<si::dim_time>>);
|
||||
static_assert(RebindablePointOriginFor<ones_viewpoint1, si::dim_length>);
|
||||
static_assert(is_same_v<rebind_point_origin_dimension<ones_viewpoint1, si::dim_length>, ones_viewpoint1>);
|
||||
static_assert(RebindablePointOriginFor<ones_viewpoint2, si::dim_length>);
|
||||
|
||||
@@ -62,17 +62,25 @@ struct time_kind : kind<time_kind, dim_time> {};
|
||||
|
||||
struct cgs_width_kind : kind<cgs_width_kind, cgs::dim_length> {};
|
||||
|
||||
template <Unit U, Representation Rep = double> using radius = quantity_kind<radius_kind, U, Rep>;
|
||||
template <Unit U, Representation Rep = double> using width = quantity_kind<width_kind, U, Rep>;
|
||||
template <Unit U, Representation Rep = double> using height = quantity_kind<height_kind, U, Rep>;
|
||||
template<Unit U, Representation Rep = double>
|
||||
using radius = quantity_kind<radius_kind, U, Rep>;
|
||||
template<Unit U, Representation Rep = double>
|
||||
using width = quantity_kind<width_kind, U, Rep>;
|
||||
template<Unit U, Representation Rep = double>
|
||||
using height = quantity_kind<height_kind, U, Rep>;
|
||||
|
||||
template <Unit U, Representation Rep = double> using horizontal_area = quantity_kind<horizontal_area_kind, U, Rep>;
|
||||
template <Unit U, Representation Rep = double> using rate_of_climb = quantity_kind<rate_of_climb_kind, U, Rep>;
|
||||
template<Unit U, Representation Rep = double>
|
||||
using horizontal_area = quantity_kind<horizontal_area_kind, U, Rep>;
|
||||
template<Unit U, Representation Rep = double>
|
||||
using rate_of_climb = quantity_kind<rate_of_climb_kind, U, Rep>;
|
||||
|
||||
template <Unit U = one, Representation Rep = double> using apples = quantity_kind<apple, U, Rep>;
|
||||
template <Unit U = one, Representation Rep = double> using oranges = quantity_kind<orange, U, Rep>;
|
||||
template<Unit U = one, Representation Rep = double>
|
||||
using apples = quantity_kind<apple, U, Rep>;
|
||||
template<Unit U = one, Representation Rep = double>
|
||||
using oranges = quantity_kind<orange, U, Rep>;
|
||||
|
||||
template <Unit U, Representation Rep = double> using cgs_width = quantity_kind<cgs_width_kind, U, Rep>;
|
||||
template<Unit U, Representation Rep = double>
|
||||
using cgs_width = quantity_kind<cgs_width_kind, U, Rep>;
|
||||
|
||||
/////////////
|
||||
// concepts
|
||||
@@ -102,14 +110,17 @@ static_assert(sizeof(width<metre, double>) == sizeof(double));
|
||||
static_assert(sizeof(height<metre, short>) == sizeof(short));
|
||||
|
||||
template<typename Width>
|
||||
concept invalid_types = requires {
|
||||
requires !requires { typename quantity_kind<Width, second, int>; }; // unit of a different dimension
|
||||
requires !requires { typename quantity_kind<Width, metre, length<metre>>; }; // quantity used as Rep
|
||||
requires !requires { typename quantity_kind<Width, metre, quantity_point<dynamic_origin<dim_length>, metre>>; }; // quantity point used as Rep
|
||||
requires !requires { typename quantity_kind<Width, metre, width<metre>>; }; // quantity kind used as Rep
|
||||
requires !requires { typename quantity_kind<metre, Width, double>; }; // reordered arguments
|
||||
requires !requires { typename quantity_kind<metre, double, Width>; }; // reordered arguments
|
||||
};
|
||||
concept invalid_types =
|
||||
requires {
|
||||
requires !requires { typename quantity_kind<Width, second, int>; }; // unit of a different dimension
|
||||
requires !requires { typename quantity_kind<Width, metre, length<metre>>; }; // quantity used as Rep
|
||||
requires !requires { // quantity point used as Rep
|
||||
typename quantity_kind<Width, metre, quantity_point<dynamic_origin<dim_length>, metre>>;
|
||||
};
|
||||
requires !requires { typename quantity_kind<Width, metre, width<metre>>; }; // quantity kind used as Rep
|
||||
requires !requires { typename quantity_kind<metre, Width, double>; }; // reordered arguments
|
||||
requires !requires { typename quantity_kind<metre, double, Width>; }; // reordered arguments
|
||||
};
|
||||
static_assert(invalid_types<width_kind>);
|
||||
|
||||
static_assert(std::is_trivially_default_constructible_v<width<metre>>);
|
||||
@@ -199,7 +210,7 @@ static_assert(width<metre>{}.common() == 0 * m);
|
||||
/////////
|
||||
|
||||
static_assert(same(quantity_kind(rate_of_climb<kilometre_per_hour, double>(0.01 * (km / h))),
|
||||
rate_of_climb<kilometre_per_hour, double>(0.01 * (km / h))));
|
||||
rate_of_climb<kilometre_per_hour, double>(0.01 * (km / h))));
|
||||
|
||||
|
||||
////////////////////////////
|
||||
@@ -417,7 +428,8 @@ static_assert((std::uint8_t(255) * m %= quantity(257)) ==
|
||||
(width<metre, std::uint8_t>(255 * m) %= quantity(257)).common());
|
||||
static_assert((std::uint8_t(255) * m %= 257 * m) ==
|
||||
(width<metre, std::uint8_t>(255 * m) %=
|
||||
quantity_kind<downcast_kind<width_kind, dim_one>, one, std::uint8_t>(257)).common());
|
||||
quantity_kind<downcast_kind<width_kind, dim_one>, one, std::uint8_t>(257))
|
||||
.common());
|
||||
static_assert((std::uint8_t(255) * m %= 257 * m) ==
|
||||
(width<metre, std::uint8_t>(255 * m) %= width<metre, std::uint8_t>(257 * m)).common());
|
||||
|
||||
@@ -425,38 +437,39 @@ static_assert(same((-width<metre, short>(short{1} * m)).common(), int{-1} * m));
|
||||
|
||||
template<typename K, typename U, typename Qx>
|
||||
concept invalid_compound_assignments_ = requires(quantity_kind<K, U, int> w, Qx q) {
|
||||
requires !requires { w += q; };
|
||||
requires !requires { w -= q; };
|
||||
requires !requires { w *= q; };
|
||||
requires !requires { w /= q; };
|
||||
requires !requires { w %= q; };
|
||||
};
|
||||
requires !requires { w += q; };
|
||||
requires !requires { w -= q; };
|
||||
requires !requires { w *= q; };
|
||||
requires !requires { w /= q; };
|
||||
requires !requires { w %= q; };
|
||||
};
|
||||
template<typename Width>
|
||||
concept invalid_compound_assignments = requires(quantity_kind<Width, metre, int> w, height<metre, int> h) {
|
||||
requires !requires { w += 1; };
|
||||
requires !requires { w -= 1; };
|
||||
requires !requires { w *= 1 * (km / m); };
|
||||
requires !requires { w /= 1 * (km / m); };
|
||||
requires !requires { w %= 1 * (km / m); };
|
||||
requires !requires { w += m; };
|
||||
requires !requires { w -= m; };
|
||||
requires !requires { w *= m; };
|
||||
requires !requires { w /= m; };
|
||||
requires !requires { w %= m; };
|
||||
requires !requires { w *= quantity_kind<downcast_kind<Width, dim_one>, scaled_unit<ratio{1, 1, 3}, one>, int>{1}; };
|
||||
requires !requires { w /= quantity_kind<downcast_kind<Width, dim_one>, scaled_unit<ratio{1, 1, 3}, one>, int>{1}; };
|
||||
requires !requires { w %= quantity_kind<downcast_kind<Width, dim_one>, scaled_unit<ratio{1, 1, 3}, one>, int>{1}; };
|
||||
requires !requires { w %= 1.0; };
|
||||
requires !requires { w %= quantity(1.0); };
|
||||
requires !requires { w %= 1.0 * (w / w); };
|
||||
requires !requires { w %= 1.0 * w; };
|
||||
requires !requires { w %= h / h; };
|
||||
requires invalid_compound_assignments_<Width, metre, length<metre, int>>;
|
||||
requires invalid_compound_assignments_<Width, metre, height<metre, int>>;
|
||||
requires invalid_compound_assignments_<Width, metre, horizontal_area<square_metre, int>>;
|
||||
requires invalid_compound_assignments_<Width, metre, quantity_point<dynamic_origin<dim_length>, metre, int>>;
|
||||
requires invalid_compound_assignments_<Width, metre, std::chrono::seconds>;
|
||||
};
|
||||
concept invalid_compound_assignments =
|
||||
requires(quantity_kind<Width, metre, int> w, height<metre, int> h) {
|
||||
requires !requires { w += 1; };
|
||||
requires !requires { w -= 1; };
|
||||
requires !requires { w *= 1 * (km / m); };
|
||||
requires !requires { w /= 1 * (km / m); };
|
||||
requires !requires { w %= 1 * (km / m); };
|
||||
requires !requires { w += m; };
|
||||
requires !requires { w -= m; };
|
||||
requires !requires { w *= m; };
|
||||
requires !requires { w /= m; };
|
||||
requires !requires { w %= m; };
|
||||
requires !requires { w *= quantity_kind<downcast_kind<Width, dim_one>, scaled_unit<ratio{1, 1, 3}, one>, int>{1}; };
|
||||
requires !requires { w /= quantity_kind<downcast_kind<Width, dim_one>, scaled_unit<ratio{1, 1, 3}, one>, int>{1}; };
|
||||
requires !requires { w %= quantity_kind<downcast_kind<Width, dim_one>, scaled_unit<ratio{1, 1, 3}, one>, int>{1}; };
|
||||
requires !requires { w %= 1.0; };
|
||||
requires !requires { w %= quantity(1.0); };
|
||||
requires !requires { w %= 1.0 * (w / w); };
|
||||
requires !requires { w %= 1.0 * w; };
|
||||
requires !requires { w %= h / h; };
|
||||
requires invalid_compound_assignments_<Width, metre, length<metre, int>>;
|
||||
requires invalid_compound_assignments_<Width, metre, height<metre, int>>;
|
||||
requires invalid_compound_assignments_<Width, metre, horizontal_area<square_metre, int>>;
|
||||
requires invalid_compound_assignments_<Width, metre, quantity_point<dynamic_origin<dim_length>, metre, int>>;
|
||||
requires invalid_compound_assignments_<Width, metre, std::chrono::seconds>;
|
||||
};
|
||||
static_assert(invalid_compound_assignments<width_kind>);
|
||||
static_assert(invalid_compound_assignments_<time_kind, second, std::chrono::seconds>);
|
||||
|
||||
@@ -474,14 +487,16 @@ static_assert(same(width<metre, int>(2 * m) - width<metre, double>(3. * m), widt
|
||||
static_assert(same(width<metre, double>(2. * m) - width<metre, int>(3 * m), width<metre, double>(-1. * m)));
|
||||
static_assert(same(width<metre, double>(2e3 * m) - width<kilometre, int>(3 * km), width<metre, double>(-1e3 * m)));
|
||||
|
||||
static_assert(is_same_v<
|
||||
decltype((width<metre, std::uint8_t>(0 * m) + width<metre, std::uint8_t>(0 * m)).common().number()), int&&>);
|
||||
static_assert(is_same_v<
|
||||
decltype((width<metre, std::uint8_t>(0 * m) - width<metre, std::uint8_t>(0 * m)).common().number()), int&&>);
|
||||
static_assert(
|
||||
is_same_v<decltype((width<metre, std::uint8_t>(0 * m) + width<metre, std::uint8_t>(0 * m)).common().number()),
|
||||
int&&>);
|
||||
static_assert(
|
||||
is_same_v<decltype((width<metre, std::uint8_t>(0 * m) - width<metre, std::uint8_t>(0 * m)).common().number()),
|
||||
int&&>);
|
||||
static_assert((width<metre, std::uint8_t>(128 * m) + width<metre, std::uint8_t>(128 * m)).common().number() ==
|
||||
std::uint8_t(128) + std::uint8_t(128));
|
||||
std::uint8_t(128) + std::uint8_t(128));
|
||||
static_assert((width<metre, std::uint8_t>(0 * m) - width<metre, std::uint8_t>(1 * m)).common().number() ==
|
||||
std::uint8_t(0) - std::uint8_t(1));
|
||||
std::uint8_t(0) - std::uint8_t(1));
|
||||
|
||||
static_assert(!std::is_invocable_v<std::plus<>, width<metre>, double>);
|
||||
static_assert(!std::is_invocable_v<std::plus<>, width<metre>, length<metre>>);
|
||||
@@ -595,15 +610,15 @@ static_assert(same(quantity(2) / quantity_kind<time_kind, second, double>(3. * s
|
||||
static_assert(same(quantity(2.) / quantity_kind<time_kind, second, int>(3 * s),
|
||||
quantity_kind<downcast_kind<time_kind, dim_frequency>, hertz, double>(2 / 3. / (1 * s))));
|
||||
|
||||
static_assert(
|
||||
same(quantity_kind<downcast_kind<time_kind, dim_one>, one, int>(2) / quantity_kind<time_kind, second, int>(3 * s),
|
||||
quantity_kind<downcast_kind<time_kind, dim_frequency>, hertz, int>(2 / 3 / (1 * s))));
|
||||
static_assert(
|
||||
same(quantity_kind<downcast_kind<time_kind, dim_one>, one, int>(2) / quantity_kind<time_kind, second, double>(3. * s),
|
||||
quantity_kind<downcast_kind<time_kind, dim_frequency>, hertz, double>(2 / 3. / (1 * s))));
|
||||
static_assert(
|
||||
same(quantity_kind<downcast_kind<time_kind, dim_one>, one, double>(2.) / quantity_kind<time_kind, second, int>(3 * s),
|
||||
quantity_kind<downcast_kind<time_kind, dim_frequency>, hertz, double>(2 / 3. / (1 * s))));
|
||||
static_assert(same(quantity_kind<downcast_kind<time_kind, dim_one>, one, int>(2) /
|
||||
quantity_kind<time_kind, second, int>(3 * s),
|
||||
quantity_kind<downcast_kind<time_kind, dim_frequency>, hertz, int>(2 / 3 / (1 * s))));
|
||||
static_assert(same(quantity_kind<downcast_kind<time_kind, dim_one>, one, int>(2) /
|
||||
quantity_kind<time_kind, second, double>(3. * s),
|
||||
quantity_kind<downcast_kind<time_kind, dim_frequency>, hertz, double>(2 / 3. / (1 * s))));
|
||||
static_assert(same(quantity_kind<downcast_kind<time_kind, dim_one>, one, double>(2.) /
|
||||
quantity_kind<time_kind, second, int>(3 * s),
|
||||
quantity_kind<downcast_kind<time_kind, dim_frequency>, hertz, double>(2 / 3. / (1 * s))));
|
||||
|
||||
static_assert(same(height<metre, int>(2 * m) / (3 * s), rate_of_climb<metre_per_second, int>(0 * (m / s))));
|
||||
static_assert(same(height<metre, int>(2 * m) / (3. * s), rate_of_climb<metre_per_second, double>(2 / 3. * (m / s))));
|
||||
@@ -611,7 +626,8 @@ static_assert(same(height<metre, double>(2. * m) / (3 * s), rate_of_climb<metre_
|
||||
|
||||
static_assert(same(width<metre, int>(2 * m) * dimensionless<percent, int>(3), width<centimetre, int>(6 * cm)));
|
||||
static_assert(same(dimensionless<percent, int>(2) * width<metre, int>(3 * m), width<centimetre, int>(6 * cm)));
|
||||
static_assert(same(width<metre, int>(2 * m) / dimensionless<percent, double>(3), width<hectometre, double>(2. / 3 * hm)));
|
||||
static_assert(same(width<metre, int>(2 * m) / dimensionless<percent, double>(3),
|
||||
width<hectometre, double>(2. / 3 * hm)));
|
||||
static_assert(same(width<metre, int>(2 * m) % dimensionless<percent, int>(3), width<metre, int>(2 * m)));
|
||||
|
||||
static_assert(same(height<metre, int>(2 * m) / (3 * m),
|
||||
@@ -644,14 +660,16 @@ static_assert(same(horizontal_area<square_metre>(4 * (m * m)) / (1 * m), width<m
|
||||
static_assert(same(width<metre, int>(2 * m) % 3, width<metre, int>(2 * m)));
|
||||
static_assert(same(width<metre, int>(3 * m) % width<metre, int>(2 * m), width<metre, int>(1 * m)));
|
||||
|
||||
static_assert(is_same_v<
|
||||
decltype((width<metre, std::uint8_t>(0 * m) % width<metre, std::uint8_t>(0 * m)).common().number()),
|
||||
decltype(std::uint8_t(0) % std::uint8_t(0))&&>);
|
||||
static_assert(
|
||||
is_same_v<decltype((width<metre, std::uint8_t>(0 * m) % width<metre, std::uint8_t>(0 * m)).common().number()),
|
||||
decltype(std::uint8_t(0) % std::uint8_t(0))&&>);
|
||||
|
||||
static_assert(!std::is_invocable_v<std::multiplies<>, reference<dim_length, metre>, width<metre>>);
|
||||
static_assert(!std::is_invocable_v<std::multiplies<>, width<metre>, height<metre>>);
|
||||
static_assert(!std::is_invocable_v<std::multiplies<>, height<metre>, quantity_point<dynamic_origin<dim_length>, metre>>);
|
||||
static_assert(!std::is_invocable_v<std::multiplies<>, quantity_point<dynamic_origin<dim_length>, metre>, height<metre>>);
|
||||
static_assert(
|
||||
!std::is_invocable_v<std::multiplies<>, height<metre>, quantity_point<dynamic_origin<dim_length>, metre>>);
|
||||
static_assert(
|
||||
!std::is_invocable_v<std::multiplies<>, quantity_point<dynamic_origin<dim_length>, metre>, height<metre>>);
|
||||
|
||||
static_assert(!std::is_invocable_v<std::divides<>, reference<dim_length, metre>, width<metre>>);
|
||||
static_assert(!std::is_invocable_v<std::divides<>, width<metre>, height<metre>>);
|
||||
@@ -660,7 +678,8 @@ static_assert(!std::is_invocable_v<std::divides<>, quantity_point<dynamic_origin
|
||||
|
||||
static_assert(!std::is_invocable_v<std::modulus<>, width<metre, int>, reference<dim_length, metre>>);
|
||||
static_assert(!std::is_invocable_v<std::modulus<>, width<metre, int>, length<metre, int>>);
|
||||
static_assert(!std::is_invocable_v<std::modulus<>, width<metre, int>, quantity_point<dynamic_origin<dim_length>, metre, int>>);
|
||||
static_assert(
|
||||
!std::is_invocable_v<std::modulus<>, width<metre, int>, quantity_point<dynamic_origin<dim_length>, metre, int>>);
|
||||
static_assert(!std::is_invocable_v<std::modulus<>, width<metre, int>, double>);
|
||||
static_assert(!std::is_invocable_v<std::modulus<>, width<metre, int>, width<metre, double>>);
|
||||
|
||||
@@ -702,24 +721,24 @@ static_assert(std::equality_comparable_with<width<cgs::centimetre, int>, width<m
|
||||
static_assert(std::equality_comparable_with<width<metre>, width<cgs::centimetre>>);
|
||||
template<typename Width>
|
||||
concept invalid_equality = requires(quantity_kind<Width, metre, int> w) {
|
||||
requires !requires { w == 1; };
|
||||
requires !requires { w != 1.0; };
|
||||
requires !requires { w == 1 * m; };
|
||||
requires !requires { w != 1.0 * cgs_cm; };
|
||||
requires !requires { w == 1 * km; };
|
||||
requires !requires { w != m; };
|
||||
requires !requires { w == km; };
|
||||
requires !requires { w != quantity(1); };
|
||||
requires !requires { w == dimensionless<percent>(1.0); };
|
||||
requires !requires { w != height<metre, int>(1 * m); };
|
||||
requires !requires { w == height<kilometre, double>(1.0 * km); };
|
||||
requires !requires { w != horizontal_area<square_metre, int>(1 * (m * m)); };
|
||||
requires !requires { w == rate_of_climb<kilometre_per_hour, double>(1.0 * (km / h)); };
|
||||
requires !requires { w != quantity_point(1 * m); };
|
||||
requires !requires { w == quantity_point(1.0 * mm); };
|
||||
requires !requires { w != quantity_point(quantity(1)); };
|
||||
requires !requires { w == quantity_point(dimensionless<percent>(1.0)); };
|
||||
};
|
||||
requires !requires { w == 1; };
|
||||
requires !requires { w != 1.0; };
|
||||
requires !requires { w == 1 * m; };
|
||||
requires !requires { w != 1.0 * cgs_cm; };
|
||||
requires !requires { w == 1 * km; };
|
||||
requires !requires { w != m; };
|
||||
requires !requires { w == km; };
|
||||
requires !requires { w != quantity(1); };
|
||||
requires !requires { w == dimensionless<percent>(1.0); };
|
||||
requires !requires { w != height<metre, int>(1 * m); };
|
||||
requires !requires { w == height<kilometre, double>(1.0 * km); };
|
||||
requires !requires { w != horizontal_area<square_metre, int>(1 * (m * m)); };
|
||||
requires !requires { w == rate_of_climb<kilometre_per_hour, double>(1.0 * (km / h)); };
|
||||
requires !requires { w != quantity_point(1 * m); };
|
||||
requires !requires { w == quantity_point(1.0 * mm); };
|
||||
requires !requires { w != quantity_point(quantity(1)); };
|
||||
requires !requires { w == quantity_point(dimensionless<percent>(1.0)); };
|
||||
};
|
||||
static_assert(invalid_equality<width_kind>);
|
||||
|
||||
static_assert(width<metre, int>(1 * m) < width<metre, int>(2 * m));
|
||||
@@ -734,22 +753,22 @@ static_assert(std::three_way_comparable_with<width<cgs::centimetre, int>, width<
|
||||
static_assert(std::three_way_comparable_with<width<metre>, width<cgs::centimetre>>);
|
||||
template<typename Width>
|
||||
concept invalid_relational = requires(quantity_kind<Width, metre, int> w) {
|
||||
requires !requires { w < 1; };
|
||||
requires !requires { w <= 1.0; };
|
||||
requires !requires { w >= 1 * m; };
|
||||
requires !requires { w > 1.0 * cgs_cm; };
|
||||
requires !requires { w <=> 1 * km; };
|
||||
requires !requires { w < quantity(1); };
|
||||
requires !requires { w <= dimensionless<percent>(1.0); };
|
||||
requires !requires { w >= height<metre, int>(1 * m); };
|
||||
requires !requires { w > height<kilometre, double>(1.0 * km); };
|
||||
requires !requires { w <=> horizontal_area<square_metre, int>(1 * (m * m)); };
|
||||
requires !requires { w < rate_of_climb<kilometre_per_hour, double>(1.0 * (km / h)); };
|
||||
requires !requires { w <= quantity_point(1 * m); };
|
||||
requires !requires { w >= quantity_point(1.0 * mm); };
|
||||
requires !requires { w > quantity_point(quantity(1)); };
|
||||
requires !requires { w <=> quantity_point(dimensionless<percent>(1.0)); };
|
||||
};
|
||||
requires !requires { w < 1; };
|
||||
requires !requires { w <= 1.0; };
|
||||
requires !requires { w >= 1 * m; };
|
||||
requires !requires { w > 1.0 * cgs_cm; };
|
||||
requires !requires { w <=> 1 * km; };
|
||||
requires !requires { w < quantity(1); };
|
||||
requires !requires { w <= dimensionless<percent>(1.0); };
|
||||
requires !requires { w >= height<metre, int>(1 * m); };
|
||||
requires !requires { w > height<kilometre, double>(1.0 * km); };
|
||||
requires !requires { w <=> horizontal_area<square_metre, int>(1 * (m * m)); };
|
||||
requires !requires { w < rate_of_climb<kilometre_per_hour, double>(1.0 * (km / h)); };
|
||||
requires !requires { w <= quantity_point(1 * m); };
|
||||
requires !requires { w >= quantity_point(1.0 * mm); };
|
||||
requires !requires { w > quantity_point(quantity(1)); };
|
||||
requires !requires { w <=> quantity_point(dimensionless<percent>(1.0)); };
|
||||
};
|
||||
static_assert(invalid_relational<width_kind>);
|
||||
|
||||
|
||||
@@ -788,22 +807,37 @@ static_assert(same(quantity_kind_cast<length<centimetre, int>>(width<metre, doub
|
||||
static_assert(same(quantity_kind_cast<length<centimetre, int>>(width<cgs::centimetre, int>(1 * cgs_cm)), width<cgs::centimetre, int>(1 * cgs_cm)));
|
||||
// clang-format on
|
||||
template<typename Width>
|
||||
concept invalid_cast = requires {
|
||||
requires !requires { quantity_kind_cast<apples<one, int>>(quantity_kind<Width, metre, int>(1 * m)); };
|
||||
requires !requires { quantity_kind_cast<horizontal_area<square_metre, int>>(quantity_kind<Width, metre, int>(1 * m)); };
|
||||
requires !requires { quantity_kind_cast<rate_of_climb<metre_per_second, int>>(quantity_kind<Width, metre, int>(1 * m)); };
|
||||
requires !requires { quantity_kind_cast<apple>(quantity_kind<Width, metre, int>(1 * m)); };
|
||||
requires !requires { quantity_kind_cast<horizontal_area_kind>(quantity_kind<Width, metre, int>(1 * m)); };
|
||||
requires !requires { quantity_kind_cast<rate_of_climb_kind>(quantity_kind<Width, metre, int>(1 * m)); };
|
||||
requires !requires { quantity_kind_cast<apple, one>(quantity_kind<Width, metre, int>(1 * m)); };
|
||||
requires !requires { quantity_kind_cast<horizontal_area_kind, square_metre>(quantity_kind<Width, metre, int>(1 * m)); };
|
||||
requires !requires { quantity_kind_cast<rate_of_climb_kind, metre_per_second>(quantity_kind<Width, metre, int>(1 * m)); };
|
||||
requires !requires { quantity_kind_cast<dimensionless<one>>(quantity_kind<Width, metre, int>(1 * m)); };
|
||||
requires !requires { quantity_kind_cast<square_metre>(quantity_kind<Width, metre, int>(1 * m)); };
|
||||
requires !requires { quantity_kind_cast<second>(quantity_kind<Width, metre, int>(1 * m)); };
|
||||
requires !requires { quantity_kind_cast<quantity_point<dynamic_origin<dim_length>, metre, int>>(quantity_kind<Width, metre, int>(1 * m)); };
|
||||
requires !requires { quantity_kind_cast<quantity_point<dynamic_origin<dim_one>, one, int>>(quantity_kind<Width, metre, int>(1 * m)); };
|
||||
};
|
||||
concept invalid_cast =
|
||||
requires {
|
||||
requires !requires { quantity_kind_cast<apples<one, int>>(quantity_kind<Width, metre, int>(1 * m)); };
|
||||
requires !requires {
|
||||
quantity_kind_cast<horizontal_area<square_metre, int>>(quantity_kind<Width, metre, int>(1 * m));
|
||||
};
|
||||
requires !requires {
|
||||
quantity_kind_cast<rate_of_climb<metre_per_second, int>>(quantity_kind<Width, metre, int>(1 * m));
|
||||
};
|
||||
requires !requires { quantity_kind_cast<apple>(quantity_kind<Width, metre, int>(1 * m)); };
|
||||
requires !requires { quantity_kind_cast<horizontal_area_kind>(quantity_kind<Width, metre, int>(1 * m)); };
|
||||
requires !requires { quantity_kind_cast<rate_of_climb_kind>(quantity_kind<Width, metre, int>(1 * m)); };
|
||||
requires !requires { quantity_kind_cast<apple, one>(quantity_kind<Width, metre, int>(1 * m)); };
|
||||
requires !requires {
|
||||
quantity_kind_cast<horizontal_area_kind, square_metre>(quantity_kind<Width, metre, int>(1 * m));
|
||||
};
|
||||
requires !requires {
|
||||
quantity_kind_cast<rate_of_climb_kind, metre_per_second>(quantity_kind<Width, metre, int>(1 * m));
|
||||
};
|
||||
requires !requires { quantity_kind_cast<dimensionless<one>>(quantity_kind<Width, metre, int>(1 * m)); };
|
||||
requires !requires { quantity_kind_cast<square_metre>(quantity_kind<Width, metre, int>(1 * m)); };
|
||||
requires !requires { quantity_kind_cast<second>(quantity_kind<Width, metre, int>(1 * m)); };
|
||||
requires !requires {
|
||||
quantity_kind_cast<quantity_point<dynamic_origin<dim_length>, metre, int>>(
|
||||
quantity_kind<Width, metre, int>(1 * m));
|
||||
};
|
||||
requires !requires {
|
||||
quantity_kind_cast<quantity_point<dynamic_origin<dim_one>, one, int>>(
|
||||
quantity_kind<Width, metre, int>(1 * m));
|
||||
};
|
||||
};
|
||||
static_assert(invalid_cast<width_kind>);
|
||||
|
||||
|
||||
@@ -817,15 +851,15 @@ struct radius_kind : kind<radius_kind, si::dim_length> {};
|
||||
|
||||
struct cylinder_size {};
|
||||
|
||||
template <units::QuantityKindOf<radius_kind> Radius, units::QuantityKindOf<height_kind> Height>
|
||||
template<units::QuantityKindOf<radius_kind> Radius, units::QuantityKindOf<height_kind> Height>
|
||||
cylinder_size operator+(Radius, Height);
|
||||
|
||||
} // namespace mylib
|
||||
|
||||
namespace yourapp {
|
||||
|
||||
static_assert(is_same_v<mylib::cylinder_size,
|
||||
decltype(quantity_kind<mylib::radius_kind, metre, double>(1. * m) + height<metre, double>(1. * m))>);
|
||||
static_assert(is_same_v<mylib::cylinder_size, decltype(quantity_kind<mylib::radius_kind, metre, double>(1. * m) +
|
||||
height<metre, double>(1. * m))>);
|
||||
|
||||
} // namespace yourapp
|
||||
|
||||
|
||||
@@ -79,16 +79,25 @@ struct time_point_kind : point_kind<time_point_kind, time_kind> {};
|
||||
|
||||
struct sys_time_point_kind : point_kind<time_point_kind, time_kind, clock_origin<std::chrono::system_clock>> {};
|
||||
|
||||
template <Unit U, Representation Rep = double> using width = quantity_kind<width_kind, U, Rep>;
|
||||
template <Unit U, Representation Rep = double> using height = quantity_kind<height_kind, U, Rep>;
|
||||
template <Unit U, Representation Rep = double> using abscissa = quantity_point_kind<abscissa_kind, U, Rep>;
|
||||
template <Unit U, Representation Rep = double> using ordinate = quantity_point_kind<ordinate_kind, U, Rep>;
|
||||
template<Unit U, Representation Rep = double>
|
||||
using width = quantity_kind<width_kind, U, Rep>;
|
||||
template<Unit U, Representation Rep = double>
|
||||
using height = quantity_kind<height_kind, U, Rep>;
|
||||
template<Unit U, Representation Rep = double>
|
||||
using abscissa = quantity_point_kind<abscissa_kind, U, Rep>;
|
||||
template<Unit U, Representation Rep = double>
|
||||
using ordinate = quantity_point_kind<ordinate_kind, U, Rep>;
|
||||
|
||||
template <Unit U, Representation Rep = double> using distance = quantity_kind<distance_kind, U, Rep>;
|
||||
template <Unit U, Representation Rep = double> using cgs_width = quantity_kind<cgs_width_kind, U, Rep>;
|
||||
template <Unit U, Representation Rep = double> using cgs_height = quantity_kind<cgs_height_kind, U, Rep>;
|
||||
template <Unit U, Representation Rep = double> using rate_of_climb = quantity_kind<rate_of_climb_kind, U, Rep>;
|
||||
template <Unit U, Representation Rep = double> using altitude = quantity_point_kind<altitude_kind, U, Rep>;
|
||||
template<Unit U, Representation Rep = double>
|
||||
using distance = quantity_kind<distance_kind, U, Rep>;
|
||||
template<Unit U, Representation Rep = double>
|
||||
using cgs_width = quantity_kind<cgs_width_kind, U, Rep>;
|
||||
template<Unit U, Representation Rep = double>
|
||||
using cgs_height = quantity_kind<cgs_height_kind, U, Rep>;
|
||||
template<Unit U, Representation Rep = double>
|
||||
using rate_of_climb = quantity_kind<rate_of_climb_kind, U, Rep>;
|
||||
template<Unit U, Representation Rep = double>
|
||||
using altitude = quantity_point_kind<altitude_kind, U, Rep>;
|
||||
|
||||
template<Unit U, Representation Rep = double>
|
||||
using sea_level_altitude = quantity_point_kind<sea_level_altitude_kind, U, Rep>;
|
||||
@@ -97,10 +106,14 @@ using screen_si_width = quantity_point_kind<screen_si_width_kind, U, Rep>;
|
||||
template<Unit U, Representation Rep = double>
|
||||
using screen_si_cgs_width = quantity_point_kind<screen_si_cgs_width_kind, U, Rep>;
|
||||
|
||||
template <Unit U = one, Representation Rep = double> using apples = quantity_kind<apple, U, Rep>;
|
||||
template <Unit U = one, Representation Rep = double> using oranges = quantity_kind<orange, U, Rep>;
|
||||
template <Unit U = one, Representation Rep = double> using nth_apple = quantity_point_kind<nth_apple_kind, U, Rep>;
|
||||
template <Unit U = one, Representation Rep = double> using nth_orange = quantity_point_kind<nth_orange_kind, U, Rep>;
|
||||
template<Unit U = one, Representation Rep = double>
|
||||
using apples = quantity_kind<apple, U, Rep>;
|
||||
template<Unit U = one, Representation Rep = double>
|
||||
using oranges = quantity_kind<orange, U, Rep>;
|
||||
template<Unit U = one, Representation Rep = double>
|
||||
using nth_apple = quantity_point_kind<nth_apple_kind, U, Rep>;
|
||||
template<Unit U = one, Representation Rep = double>
|
||||
using nth_orange = quantity_point_kind<nth_orange_kind, U, Rep>;
|
||||
|
||||
/////////////
|
||||
// concepts
|
||||
@@ -137,16 +150,21 @@ static_assert(sizeof(abscissa<metre, double>) == sizeof(double));
|
||||
static_assert(sizeof(ordinate<metre, short>) == sizeof(short));
|
||||
|
||||
template<typename Width, typename Abscissa>
|
||||
concept invalid_types = requires {
|
||||
requires !requires { typename quantity_point_kind<Width, metre, int>; }; // width_kind is not a point kind
|
||||
requires !requires { typename quantity_point_kind<Abscissa, second, int>; }; // unit of a different dimension
|
||||
requires !requires { typename quantity_point_kind<Abscissa, metre, length<metre>>; }; // quantity used as Rep
|
||||
requires !requires { typename quantity_point_kind<Abscissa, metre, quantity_point<dynamic_origin<dim_length>, metre>>; }; // quantity point used as Rep
|
||||
requires !requires { typename quantity_point_kind<Abscissa, metre, width<metre>>; }; // quantity kind used as Rep
|
||||
requires !requires { typename quantity_point_kind<Abscissa, metre, abscissa<metre>>; }; // quantity point kind used as Rep
|
||||
requires !requires { typename quantity_point_kind<metre, Abscissa, double>; }; // reordered arguments
|
||||
requires !requires { typename quantity_point_kind<metre, double, Abscissa>; }; // reordered arguments
|
||||
};
|
||||
concept invalid_types =
|
||||
requires {
|
||||
requires !requires { typename quantity_point_kind<Width, metre, int>; }; // width_kind is not a point kind
|
||||
requires !requires { typename quantity_point_kind<Abscissa, second, int>; }; // unit of a different dimension
|
||||
requires !requires { typename quantity_point_kind<Abscissa, metre, length<metre>>; }; // quantity used as Rep
|
||||
requires !requires {
|
||||
typename quantity_point_kind<Abscissa, metre, quantity_point<dynamic_origin<dim_length>, metre>>;
|
||||
}; // quantity point used as Rep
|
||||
requires !requires { typename quantity_point_kind<Abscissa, metre, width<metre>>; }; // quantity kind used as Rep
|
||||
requires !requires {
|
||||
typename quantity_point_kind<Abscissa, metre, abscissa<metre>>;
|
||||
}; // quantity point kind used as Rep
|
||||
requires !requires { typename quantity_point_kind<metre, Abscissa, double>; }; // reordered arguments
|
||||
requires !requires { typename quantity_point_kind<metre, double, Abscissa>; }; // reordered arguments
|
||||
};
|
||||
static_assert(invalid_types<width_kind, abscissa_kind>);
|
||||
|
||||
static_assert(std::is_trivially_default_constructible_v<abscissa<metre>>);
|
||||
@@ -456,22 +474,23 @@ static_assert([]() {
|
||||
|
||||
template<typename PK, typename U, typename Qx>
|
||||
concept invalid_compound_assignments_ = requires(quantity_point_kind<PK, U, int> x, Qx q) {
|
||||
requires !requires { x += q; };
|
||||
requires !requires { x -= q; };
|
||||
};
|
||||
requires !requires { x += q; };
|
||||
requires !requires { x -= q; };
|
||||
};
|
||||
template<typename Abscissa>
|
||||
concept invalid_compound_assignments = requires(quantity_point_kind<Abscissa, metre, int> x) {
|
||||
requires !requires { x += 1; };
|
||||
requires !requires { x -= 1; };
|
||||
requires invalid_compound_assignments_<Abscissa, metre, length<metre, int>>;
|
||||
requires invalid_compound_assignments_<Abscissa, metre, height<metre, int>>;
|
||||
requires invalid_compound_assignments_<Abscissa, metre, rate_of_climb<metre_per_second, int>>;
|
||||
requires invalid_compound_assignments_<Abscissa, metre, quantity_point<dynamic_origin<dim_length>, metre, int>>;
|
||||
requires invalid_compound_assignments_<Abscissa, metre, std::chrono::seconds>;
|
||||
};
|
||||
concept invalid_compound_assignments =
|
||||
requires(quantity_point_kind<Abscissa, metre, int> x) {
|
||||
requires !requires { x += 1; };
|
||||
requires !requires { x -= 1; };
|
||||
requires invalid_compound_assignments_<Abscissa, metre, length<metre, int>>;
|
||||
requires invalid_compound_assignments_<Abscissa, metre, height<metre, int>>;
|
||||
requires invalid_compound_assignments_<Abscissa, metre, rate_of_climb<metre_per_second, int>>;
|
||||
requires invalid_compound_assignments_<Abscissa, metre, quantity_point<dynamic_origin<dim_length>, metre, int>>;
|
||||
requires invalid_compound_assignments_<Abscissa, metre, std::chrono::seconds>;
|
||||
};
|
||||
static_assert(invalid_compound_assignments<abscissa_kind>);
|
||||
static_assert(invalid_compound_assignments_<time_point_kind, second, std::chrono::seconds>);
|
||||
#if __cpp_lib_chrono >= 201907L
|
||||
#if __cpp_lib_chrono >= 201907L
|
||||
static_assert(invalid_compound_assignments_<time_point_kind, second, std::chrono::sys_seconds>);
|
||||
#endif
|
||||
|
||||
@@ -545,26 +564,26 @@ static_assert(std::equality_comparable_with<abscissa<metre>, abscissa<cgs::centi
|
||||
// clang-format on
|
||||
template<typename Int>
|
||||
concept invalid_equality = requires(quantity_point_kind<abscissa_kind, metre, Int> x, Int i) {
|
||||
requires !requires { x == 1; };
|
||||
requires !requires { x != 1.0; };
|
||||
requires !requires { x == 1 * m; };
|
||||
requires !requires { x != 1.0 * cgs_cm; };
|
||||
requires !requires { x == 1 * km; };
|
||||
requires !requires { x != quantity(1); };
|
||||
requires !requires { x == dimensionless<percent>(1.0); };
|
||||
requires !requires { x != width<metre, int>(1 * m); };
|
||||
requires !requires { x == width<kilometre, double>(1.0 * km); };
|
||||
requires !requires { x != height<metre, int>(1 * m); };
|
||||
requires !requires { x == height<kilometre, double>(1.0 * km); };
|
||||
requires !requires { x == rate_of_climb<kilometre_per_hour, double>(1.0 * (km / h)); };
|
||||
requires !requires { x != quantity_point(1 * m); };
|
||||
requires !requires { x == quantity_point(1.0 * mm); };
|
||||
requires !requires { x != quantity_point(quantity(1)); };
|
||||
requires !requires { x == quantity_point(dimensionless<percent>(1.0)); };
|
||||
requires !requires { x != quantity_point_kind(cgs_width<metre, int>(1 * m)); };
|
||||
requires !requires { x == ordinate<metre, int>(1 * m); };
|
||||
requires !requires { screen_si_width<metre, Int>{} != screen_si_cgs_width<metre, Int>{}; };
|
||||
};
|
||||
requires !requires { x == 1; };
|
||||
requires !requires { x != 1.0; };
|
||||
requires !requires { x == 1 * m; };
|
||||
requires !requires { x != 1.0 * cgs_cm; };
|
||||
requires !requires { x == 1 * km; };
|
||||
requires !requires { x != quantity(1); };
|
||||
requires !requires { x == dimensionless<percent>(1.0); };
|
||||
requires !requires { x != width<metre, int>(1 * m); };
|
||||
requires !requires { x == width<kilometre, double>(1.0 * km); };
|
||||
requires !requires { x != height<metre, int>(1 * m); };
|
||||
requires !requires { x == height<kilometre, double>(1.0 * km); };
|
||||
requires !requires { x == rate_of_climb<kilometre_per_hour, double>(1.0 * (km / h)); };
|
||||
requires !requires { x != quantity_point(1 * m); };
|
||||
requires !requires { x == quantity_point(1.0 * mm); };
|
||||
requires !requires { x != quantity_point(quantity(1)); };
|
||||
requires !requires { x == quantity_point(dimensionless<percent>(1.0)); };
|
||||
requires !requires { x != quantity_point_kind(cgs_width<metre, int>(1 * m)); };
|
||||
requires !requires { x == ordinate<metre, int>(1 * m); };
|
||||
requires !requires { screen_si_width<metre, Int>{} != screen_si_cgs_width<metre, Int>{}; };
|
||||
};
|
||||
static_assert(invalid_equality<int>);
|
||||
|
||||
// clang-format off
|
||||
@@ -580,27 +599,28 @@ static_assert(std::three_way_comparable_with<abscissa<cgs::centimetre, int>, abs
|
||||
static_assert(std::three_way_comparable_with<abscissa<metre>, abscissa<cgs::centimetre>>);
|
||||
// clang-format on
|
||||
template<typename Int>
|
||||
concept invalid_relational = requires(quantity_point_kind<abscissa_kind, metre, Int> x, Int i) {
|
||||
requires !requires { x < 1; };
|
||||
requires !requires { x <= 1.0; };
|
||||
requires !requires { x >= 1 * m; };
|
||||
requires !requires { x > 1.0 * cgs_cm; };
|
||||
requires !requires { x <=> 1 * km; };
|
||||
requires !requires { x < quantity(1); };
|
||||
requires !requires { x <= dimensionless<percent>(1.0); };
|
||||
requires !requires { x >= width<metre, int>(1 * m); };
|
||||
requires !requires { x > width<kilometre, double>(1.0 * km); };
|
||||
requires !requires { x <=> height<metre, int>(1 * m); };
|
||||
requires !requires { x < height<kilometre, double>(1.0 * km); };
|
||||
requires !requires { x <= rate_of_climb<kilometre_per_hour, double>(1.0 * (km / h)); };
|
||||
requires !requires { x >= quantity_point(1 * m); };
|
||||
requires !requires { x > quantity_point(1.0 * mm); };
|
||||
requires !requires { x <=> quantity_point(quantity(1)); };
|
||||
requires !requires { x < quantity_point(dimensionless<percent>(1.0)); };
|
||||
requires !requires { x <= quantity_point_kind(cgs_width<metre, int>(1 * m)); };
|
||||
requires !requires { x >= ordinate<metre, int>(1 * m); };
|
||||
requires !requires { screen_si_width<metre, Int>{} > screen_si_cgs_width<metre, Int>{}; };
|
||||
};
|
||||
concept invalid_relational =
|
||||
requires(quantity_point_kind<abscissa_kind, metre, Int> x, Int i) {
|
||||
requires !requires { x < 1; };
|
||||
requires !requires { x <= 1.0; };
|
||||
requires !requires { x >= 1 * m; };
|
||||
requires !requires { x > 1.0 * cgs_cm; };
|
||||
requires !requires { x <=> 1 * km; };
|
||||
requires !requires { x < quantity(1); };
|
||||
requires !requires { x <= dimensionless<percent>(1.0); };
|
||||
requires !requires { x >= width<metre, int>(1 * m); };
|
||||
requires !requires { x > width<kilometre, double>(1.0 * km); };
|
||||
requires !requires { x <=> height<metre, int>(1 * m); };
|
||||
requires !requires { x < height<kilometre, double>(1.0 * km); };
|
||||
requires !requires { x <= rate_of_climb<kilometre_per_hour, double>(1.0 * (km / h)); };
|
||||
requires !requires { x >= quantity_point(1 * m); };
|
||||
requires !requires { x > quantity_point(1.0 * mm); };
|
||||
requires !requires { x <=> quantity_point(quantity(1)); };
|
||||
requires !requires { x < quantity_point(dimensionless<percent>(1.0)); };
|
||||
requires !requires { x <= quantity_point_kind(cgs_width<metre, int>(1 * m)); };
|
||||
requires !requires { x >= ordinate<metre, int>(1 * m); };
|
||||
requires !requires { screen_si_width<metre, Int>{} > screen_si_cgs_width<metre, Int>{}; };
|
||||
};
|
||||
static_assert(invalid_relational<int>);
|
||||
|
||||
|
||||
@@ -652,25 +672,35 @@ static_assert(same(quantity_point_kind_cast<length<centimetre, int>>(abscissa<cg
|
||||
static_assert(same(quantity_point_kind_cast<screen_si_cgs_width<metre, int>>(screen_si_width<metre, int>(1 * m)), screen_si_cgs_width<metre, int>(1 * m)));
|
||||
// clang-format on
|
||||
template<typename Int>
|
||||
concept invalid_cast = requires(Int i) {
|
||||
requires !requires { quantity_point_kind_cast<apples<one, Int>>(abscissa<metre, Int>(i * m)); };
|
||||
requires !requires { quantity_point_kind_cast<rate_of_climb<metre_per_second, Int>>(abscissa<metre, Int>(i * m)); };
|
||||
requires !requires { quantity_point_kind_cast<apple>(abscissa<metre, Int>(i * m)); };
|
||||
requires !requires { quantity_point_kind_cast<rate_of_climb_kind>(abscissa<metre, Int>(i * m)); };
|
||||
requires !requires { quantity_point_kind_cast<apple, one>(abscissa<metre, Int>(i * m)); };
|
||||
requires !requires { quantity_point_kind_cast<width_kind, metre>(abscissa<metre, Int>(i * m)); };
|
||||
requires !requires { quantity_point_kind_cast<width_kind, kilometre>(abscissa<metre, Int>(i * m)); };
|
||||
requires !requires { quantity_point_kind_cast<height_kind, metre>(abscissa<metre, Int>(i * m)); };
|
||||
requires !requires { quantity_point_kind_cast<height_kind, kilometre>(abscissa<metre, Int>(i * m)); };
|
||||
requires !requires { quantity_point_kind_cast<cgs_width_kind, cgs::centimetre>(abscissa<metre, Int>(i * m)); };
|
||||
requires !requires { quantity_point_kind_cast<rate_of_climb_kind, metre_per_second>(abscissa<metre, Int>(i * m)); };
|
||||
requires !requires { quantity_point_kind_cast<dimensionless<one>>(abscissa<metre, Int>(i * m)); };
|
||||
requires !requires { quantity_point_kind_cast<square_metre>(abscissa<metre, Int>(i * m)); };
|
||||
requires !requires { quantity_point_kind_cast<second>(abscissa<metre, Int>(i * m)); };
|
||||
requires !requires { quantity_point_kind_cast<quantity_point<dynamic_origin<dim_length>, metre, Int>>(abscissa<metre, Int>(i * m)); };
|
||||
requires !requires { quantity_point_kind_cast<quantity_point<dynamic_origin<dim_one>, one, Int>>(abscissa<metre, Int>(i * m)); };
|
||||
requires !requires { quantity_point_kind_cast<quantity_point<dynamic_origin<dim_length>, metre, Int>>(screen_si_width<metre, Int>(i * m)); };
|
||||
};
|
||||
concept invalid_cast =
|
||||
requires(Int i) {
|
||||
requires !requires { quantity_point_kind_cast<apples<one, Int>>(abscissa<metre, Int>(i * m)); };
|
||||
requires !requires { quantity_point_kind_cast<rate_of_climb<metre_per_second, Int>>(abscissa<metre, Int>(i * m)); };
|
||||
requires !requires { quantity_point_kind_cast<apple>(abscissa<metre, Int>(i * m)); };
|
||||
requires !requires { quantity_point_kind_cast<rate_of_climb_kind>(abscissa<metre, Int>(i * m)); };
|
||||
requires !requires { quantity_point_kind_cast<apple, one>(abscissa<metre, Int>(i * m)); };
|
||||
requires !requires { quantity_point_kind_cast<width_kind, metre>(abscissa<metre, Int>(i * m)); };
|
||||
requires !requires { quantity_point_kind_cast<width_kind, kilometre>(abscissa<metre, Int>(i * m)); };
|
||||
requires !requires { quantity_point_kind_cast<height_kind, metre>(abscissa<metre, Int>(i * m)); };
|
||||
requires !requires { quantity_point_kind_cast<height_kind, kilometre>(abscissa<metre, Int>(i * m)); };
|
||||
requires !requires { quantity_point_kind_cast<cgs_width_kind, cgs::centimetre>(abscissa<metre, Int>(i * m)); };
|
||||
requires !requires { quantity_point_kind_cast<rate_of_climb_kind, metre_per_second>(abscissa<metre, Int>(i * m)); };
|
||||
requires !requires { quantity_point_kind_cast<dimensionless<one>>(abscissa<metre, Int>(i * m)); };
|
||||
requires !requires { quantity_point_kind_cast<square_metre>(abscissa<metre, Int>(i * m)); };
|
||||
requires !requires { quantity_point_kind_cast<second>(abscissa<metre, Int>(i * m)); };
|
||||
requires !requires {
|
||||
quantity_point_kind_cast<quantity_point<dynamic_origin<dim_length>, metre, Int>>(
|
||||
abscissa<metre, Int>(i * m));
|
||||
};
|
||||
requires !requires {
|
||||
quantity_point_kind_cast<quantity_point<dynamic_origin<dim_one>, one, Int>>(
|
||||
abscissa<metre, Int>(i * m));
|
||||
};
|
||||
requires !requires {
|
||||
quantity_point_kind_cast<quantity_point<dynamic_origin<dim_length>, metre, Int>>(
|
||||
screen_si_width<metre, Int>(i * m));
|
||||
};
|
||||
};
|
||||
static_assert(invalid_cast<int>);
|
||||
|
||||
|
||||
@@ -687,16 +717,16 @@ struct ordinate_kind : point_kind<ordinate_kind, height_kind> {};
|
||||
|
||||
struct point {};
|
||||
|
||||
template <units::QuantityPointKindOf<abscissa_kind> Abscissa, units::QuantityPointKindOf<ordinate_kind> Ordinate>
|
||||
template<units::QuantityPointKindOf<abscissa_kind> Abscissa, units::QuantityPointKindOf<ordinate_kind> Ordinate>
|
||||
point operator+(Abscissa, Ordinate);
|
||||
|
||||
} // namespace mylib
|
||||
|
||||
namespace yourapp {
|
||||
|
||||
static_assert(is_same_v<mylib::point,
|
||||
decltype(quantity_point_kind(quantity_kind<mylib::width_kind, metre, int>(1 * m)) +
|
||||
quantity_point_kind(quantity_kind<mylib::height_kind, metre, int>(1 * m)))>);
|
||||
static_assert(
|
||||
is_same_v<mylib::point, decltype(quantity_point_kind(quantity_kind<mylib::width_kind, metre, int>(1 * m)) +
|
||||
quantity_point_kind(quantity_kind<mylib::height_kind, metre, int>(1 * m)))>);
|
||||
|
||||
} // namespace yourapp
|
||||
|
||||
|
||||
@@ -34,24 +34,27 @@ template<typename T>
|
||||
inline constexpr bool compare_impl<T, T> = true;
|
||||
|
||||
template<typename T, typename U>
|
||||
requires (UNITS_DOWNCAST_MODE == 0)
|
||||
requires(UNITS_DOWNCAST_MODE == 0)
|
||||
inline constexpr bool compare_impl<T, U> = units::equivalent<T, U>;
|
||||
|
||||
template<typename T, typename U>
|
||||
inline constexpr bool compare = compare_impl<std::remove_cvref_t<T>, std::remove_cvref_t<U>>;
|
||||
|
||||
template<typename T, typename... Us, typename... Vs>
|
||||
constexpr bool constructible_from(Vs...) {
|
||||
constexpr bool constructible_from(Vs...)
|
||||
{
|
||||
return std::constructible_from<T, Us..., Vs...>;
|
||||
}
|
||||
|
||||
template<class T> void convertible_from__(T);
|
||||
template<class T>
|
||||
void convertible_from__(T);
|
||||
|
||||
template<typename T, typename... Us>
|
||||
concept convertible_from_ = requires(Us... us) { convertible_from__<T>({us...}); };
|
||||
|
||||
template<typename T, typename... Us, typename... Vs>
|
||||
constexpr bool convertible_from(Vs...) {
|
||||
constexpr bool convertible_from(Vs...)
|
||||
{
|
||||
if constexpr (sizeof...(Us) + sizeof...(Vs) == 1)
|
||||
return std::is_convertible_v<Us..., Vs..., T>;
|
||||
else
|
||||
@@ -59,24 +62,28 @@ constexpr bool convertible_from(Vs...) {
|
||||
}
|
||||
|
||||
template<typename T, typename... Us, typename... Vs>
|
||||
constexpr bool constructible_or_convertible_from(Vs...) {
|
||||
constexpr bool constructible_or_convertible_from(Vs...)
|
||||
{
|
||||
return constructible_from<T, Us..., Vs...>() || convertible_from<T, Us..., Vs...>();
|
||||
}
|
||||
|
||||
template<typename T, typename... Us, typename... Vs>
|
||||
constexpr bool constructible_and_convertible_from(Vs...) {
|
||||
constexpr bool constructible_and_convertible_from(Vs...)
|
||||
{
|
||||
return constructible_from<T, Us..., Vs...>() && convertible_from<T, Us..., Vs...>();
|
||||
}
|
||||
|
||||
template<typename T, typename... Us>
|
||||
requires (constructible_from<T, Us...>())
|
||||
constexpr T construct_from(Us... us) {
|
||||
requires(constructible_from<T, Us...>())
|
||||
constexpr T construct_from(Us... us)
|
||||
{
|
||||
return T(us...);
|
||||
}
|
||||
|
||||
template<typename T, typename... Us>
|
||||
requires (convertible_from<T, Us...>())
|
||||
constexpr T convert_from(Us... us) {
|
||||
requires(convertible_from<T, Us...>())
|
||||
constexpr T convert_from(Us... us)
|
||||
{
|
||||
if constexpr (sizeof...(Us) == 1)
|
||||
return [](T t) { return t; }(us...);
|
||||
else
|
||||
@@ -84,16 +91,18 @@ constexpr T convert_from(Us... us) {
|
||||
}
|
||||
|
||||
template<std::equality_comparable T, typename... Us>
|
||||
requires (constructible_from<T, Us...>() && convertible_from<T, Us...>())
|
||||
constexpr T construct_and_convert_from(Us... us) {
|
||||
requires(constructible_from<T, Us...>() && convertible_from<T, Us...>())
|
||||
constexpr T construct_and_convert_from(Us... us)
|
||||
{
|
||||
T t{construct_from<T>(us...)};
|
||||
assert(t == convert_from<T>(us...));
|
||||
return t;
|
||||
}
|
||||
|
||||
template<typename T, typename... Us>
|
||||
requires (constructible_from<T, Us...>() && !convertible_from<T, Us...>())
|
||||
constexpr T construct_from_only(Us... us) {
|
||||
requires(constructible_from<T, Us...>() && !convertible_from<T, Us...>())
|
||||
constexpr T construct_from_only(Us... us)
|
||||
{
|
||||
return construct_from<T>(us...);
|
||||
}
|
||||
|
||||
@@ -109,7 +118,8 @@ inline constexpr bool ctad_constructible_from_<T, std::void_t<decltype(T(Us{}...
|
||||
#endif
|
||||
|
||||
template<template<typename...> typename T, typename... Us, typename... Vs>
|
||||
constexpr bool ctad_constructible_from(Vs...) {
|
||||
constexpr bool ctad_constructible_from(Vs...)
|
||||
{
|
||||
return ctad_constructible_from_<T, void, Us..., Vs...>;
|
||||
}
|
||||
|
||||
@@ -118,8 +128,10 @@ constexpr auto same = []<std::equality_comparable T>(T l, T r) { return l == r;
|
||||
#else
|
||||
constexpr auto same = []<typename T, typename U>(T l, U r)
|
||||
requires requires { l == r; }
|
||||
// requires std::equality_comparable_with<T, U> // TODO: Fix #205
|
||||
{ return l == r; };
|
||||
// requires std::equality_comparable_with<T, U> // TODO: Fix #205
|
||||
{
|
||||
return l == r;
|
||||
};
|
||||
#endif
|
||||
|
||||
template<auto F>
|
||||
|
||||
Reference in new issue
Block a user