feat!: 💥 dimensionless quantities refactored
Dimensionless quantities are now represented by quantity types rather than by plain representation types. Only dimensionless quantities with `unitless` unit are implicitly convertible from representation types. `units::exp()` now is a function doing std::exp() on a representation type (previous `units::exp` class template was renamed to `units::exponent`). BREAKING_CHANGE: gcc-9.3 support removed BREAKING_CHANGE: `exp` and `Exp` renamed to `exponent` and `Exponent` Resolves #27 Resolves #42
This commit is contained in:
1 parent
c8b60b80c1
commit
563b358d5e
47 files changed
+599
-422
No files matched your search
@@ -8,7 +8,7 @@ struct test<%= k %> {
|
||||
|
||||
#if defined(METABENCH)
|
||||
using dim = units::make_dimension_t<<%=
|
||||
xs = ((1)..(n)).map { |j| "units::exp<dim#{j}, 1>" }
|
||||
xs = ((1)..(n)).map { |j| "units::exponent<dim#{j}, 1>" }
|
||||
rng = Random.new(k)
|
||||
xs.shuffle(random: rng).join(', ')
|
||||
%>>;
|
||||
|
||||
@@ -8,7 +8,7 @@ struct test<%= k %> {
|
||||
|
||||
#if defined(METABENCH)
|
||||
using dim = units::make_dimension_t<<%=
|
||||
xs = ((1)..(n)).map { |j| "units::exp<dim#{j}, 1>" }
|
||||
xs = ((1)..(n)).map { |j| "units::exponent<dim#{j}, 1>" }
|
||||
rng = Random.new(k)
|
||||
xs.shuffle(random: rng).join(', ')
|
||||
%>>;
|
||||
|
||||
@@ -60,26 +60,26 @@ namespace units {
|
||||
struct base_dimension_less : std::bool_constant<D1 < D2> {
|
||||
};
|
||||
|
||||
// exp
|
||||
// exponent
|
||||
|
||||
template<const base_dimension& BaseDimension, std::intmax_t Num, std::intmax_t Den = 1>
|
||||
struct exp {
|
||||
struct exponent {
|
||||
static constexpr const base_dimension& dimension = BaseDimension;
|
||||
static constexpr std::intmax_t num = Num;
|
||||
static constexpr std::intmax_t den = Den;
|
||||
};
|
||||
|
||||
// is_exp
|
||||
// is_exponent
|
||||
namespace detail {
|
||||
template<typename T>
|
||||
inline constexpr bool is_exp = false;
|
||||
inline constexpr bool is_exponent = false;
|
||||
|
||||
template<const base_dimension& BaseDimension, std::intmax_t Num, std::intmax_t Den>
|
||||
inline constexpr bool is_exp<exp<BaseDimension, Num, Den>> = true;
|
||||
inline constexpr bool is_exponent<exponent<BaseDimension, Num, Den>> = true;
|
||||
} // namespace detail
|
||||
|
||||
template<typename T>
|
||||
concept Exponent = detail::is_exp<T>;
|
||||
concept Exponent = detail::is_exponent<T>;
|
||||
|
||||
// exp_dim_id_less
|
||||
|
||||
@@ -93,8 +93,8 @@ namespace units {
|
||||
struct exp_invert;
|
||||
|
||||
template<const base_dimension& BaseDimension, std::intmax_t Num, std::intmax_t Den>
|
||||
struct exp_invert<exp<BaseDimension, Num, Den>> {
|
||||
using type = exp<BaseDimension, -Num, Den>;
|
||||
struct exp_invert<exponent<BaseDimension, Num, Den>> {
|
||||
using type = exponent<BaseDimension, -Num, Den>;
|
||||
};
|
||||
|
||||
template<Exponent E>
|
||||
@@ -161,12 +161,12 @@ namespace units {
|
||||
};
|
||||
|
||||
template<const base_dimension& D, std::intmax_t Num1, std::intmax_t Den1, std::intmax_t Num2, std::intmax_t Den2, Exponent... ERest>
|
||||
struct dim_consolidate<dimension<exp<D, Num1, Den1>, exp<D, Num2, Den2>, ERest...>> {
|
||||
struct dim_consolidate<dimension<exponent<D, Num1, Den1>, exponent<D, Num2, Den2>, ERest...>> {
|
||||
using r1 = std::ratio<Num1, Den1>;
|
||||
using r2 = std::ratio<Num2, Den2>;
|
||||
using r = std::ratio_add<r1, r2>;
|
||||
using type = conditional<r::num == 0, dim_consolidate_t<dimension<ERest...>>,
|
||||
dim_consolidate_t<dimension<exp<D, r::num, r::den>, ERest...>>>;
|
||||
dim_consolidate_t<dimension<exponent<D, r::num, r::den>, ERest...>>>;
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
|
||||
@@ -60,26 +60,26 @@ namespace units {
|
||||
struct base_dimension_less : std::bool_constant<D1 < D2> {
|
||||
};
|
||||
|
||||
// exp
|
||||
// exponent
|
||||
|
||||
template<const base_dimension& BaseDimension, std::intmax_t Num, std::intmax_t Den = 1>
|
||||
struct exp {
|
||||
struct exponent {
|
||||
static constexpr const base_dimension& dimension = BaseDimension;
|
||||
static constexpr int num = Num;
|
||||
static constexpr int den = Den;
|
||||
};
|
||||
|
||||
// is_exp
|
||||
// is_exponent
|
||||
namespace detail {
|
||||
template<typename T>
|
||||
inline constexpr bool is_exp = false;
|
||||
inline constexpr bool is_exponent = false;
|
||||
|
||||
template<const base_dimension& BaseDimension, std::intmax_t Num, std::intmax_t Den>
|
||||
inline constexpr bool is_exp<exp<BaseDimension, Num, Den>> = true;
|
||||
inline constexpr bool is_exponent<exponent<BaseDimension, Num, Den>> = true;
|
||||
} // namespace detail
|
||||
|
||||
template<typename T>
|
||||
concept Exponent = detail::is_exp<T>;
|
||||
concept Exponent = detail::is_exponent<T>;
|
||||
|
||||
// exp_dim_id_less
|
||||
|
||||
@@ -93,8 +93,8 @@ namespace units {
|
||||
struct exp_invert;
|
||||
|
||||
template<const base_dimension& BaseDimension, std::intmax_t Num, std::intmax_t Den>
|
||||
struct exp_invert<exp<BaseDimension, Num, Den>> {
|
||||
using type = exp<BaseDimension, -Num, Den>;
|
||||
struct exp_invert<exponent<BaseDimension, Num, Den>> {
|
||||
using type = exponent<BaseDimension, -Num, Den>;
|
||||
};
|
||||
|
||||
template<Exponent E>
|
||||
@@ -161,12 +161,12 @@ namespace units {
|
||||
};
|
||||
|
||||
template<const base_dimension& D, std::intmax_t Num1, std::intmax_t Den1, std::intmax_t Num2, std::intmax_t Den2, typename... ERest>
|
||||
struct dim_consolidate<dimension<exp<D, Num1, Den1>, exp<D, Num2, Den2>, ERest...>> {
|
||||
struct dim_consolidate<dimension<exponent<D, Num1, Den1>, exponent<D, Num2, Den2>, ERest...>> {
|
||||
using r1 = std::ratio<Num1, Den1>;
|
||||
using r2 = std::ratio<Num2, Den2>;
|
||||
using r = std::ratio_add<r1, r2>;
|
||||
using type = conditional<r::num == 0, dim_consolidate_t<dimension<ERest...>>,
|
||||
dim_consolidate_t<dimension<exp<D, r::num, r::den>, ERest...>>>;
|
||||
dim_consolidate_t<dimension<exponent<D, r::num, r::den>, ERest...>>>;
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
|
||||
@@ -60,10 +60,10 @@ namespace units {
|
||||
struct base_dimension_less : std::bool_constant<D1 < D2> {
|
||||
};
|
||||
|
||||
// exp
|
||||
// exponent
|
||||
|
||||
template<const base_dimension& BaseDimension, std::intmax_t Num, std::intmax_t Den = 1>
|
||||
struct exp {
|
||||
struct exponent {
|
||||
static constexpr const base_dimension& dimension = BaseDimension;
|
||||
static constexpr std::intmax_t num = Num;
|
||||
static constexpr std::intmax_t den = Den;
|
||||
@@ -81,8 +81,8 @@ namespace units {
|
||||
struct exp_invert;
|
||||
|
||||
template<const base_dimension& BaseDimension, std::intmax_t Num, std::intmax_t Den>
|
||||
struct exp_invert<exp<BaseDimension, Num, Den>> {
|
||||
using type = exp<BaseDimension, -Num, Den>;
|
||||
struct exp_invert<exponent<BaseDimension, Num, Den>> {
|
||||
using type = exponent<BaseDimension, -Num, Den>;
|
||||
};
|
||||
|
||||
template<typename E>
|
||||
@@ -132,12 +132,12 @@ namespace units {
|
||||
};
|
||||
|
||||
template<const base_dimension& D, std::intmax_t Num1, std::intmax_t Den1, std::intmax_t Num2, std::intmax_t Den2, typename... ERest>
|
||||
struct dim_consolidate<dimension<exp<D, Num1, Den1>, exp<D, Num2, Den2>, ERest...>> {
|
||||
struct dim_consolidate<dimension<exponent<D, Num1, Den1>, exponent<D, Num2, Den2>, ERest...>> {
|
||||
using r1 = std::ratio<Num1, Den1>;
|
||||
using r2 = std::ratio<Num2, Den2>;
|
||||
using r = std::ratio_add<r1, r2>;
|
||||
using type = conditional<r::num == 0, dim_consolidate_t<dimension<ERest...>>,
|
||||
dim_consolidate_t<dimension<exp<D, r::num, r::den>, ERest...>>>;
|
||||
dim_consolidate_t<dimension<exponent<D, r::num, r::den>, ERest...>>>;
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
|
||||
@@ -8,7 +8,7 @@ struct test<%= k %> {
|
||||
|
||||
#if defined(METABENCH)
|
||||
using dim = units::make_dimension_t<<%=
|
||||
xs = ((1)..(n)).map { |j| "units::exp<dim#{j}, 1>" }
|
||||
xs = ((1)..(n)).map { |j| "units::exponent<dim#{j}, 1>" }
|
||||
rng = Random.new(k)
|
||||
xs.shuffle(random: rng).join(', ')
|
||||
%>>;
|
||||
|
||||
@@ -421,6 +421,72 @@ TEST_CASE("operator<< on a quantity", "[text][ostream][fmt]")
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("dimensionless quantity")
|
||||
{
|
||||
SECTION("unitless with ratio == 1")
|
||||
{
|
||||
const auto q = 4q_m / 2q_m;
|
||||
os << q;
|
||||
|
||||
SECTION("iostream")
|
||||
{
|
||||
CHECK(os.str() == "2");
|
||||
}
|
||||
|
||||
SECTION("fmt with default format {} on a quantity")
|
||||
{
|
||||
CHECK(fmt::format("{}", q) == os.str());
|
||||
}
|
||||
|
||||
SECTION("fmt with format {:%Q %q} on a quantity")
|
||||
{
|
||||
CHECK(fmt::format("{:%Q %q}", q) == "2 ");
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("unitless with ratio.exp != 0")
|
||||
{
|
||||
const auto q = 4q_km / 2q_m;
|
||||
os << q;
|
||||
|
||||
SECTION("iostream")
|
||||
{
|
||||
CHECK(os.str() == "2 × 10³");
|
||||
}
|
||||
|
||||
SECTION("fmt with default format {} on a quantity")
|
||||
{
|
||||
CHECK(fmt::format("{}", q) == os.str());
|
||||
}
|
||||
|
||||
SECTION("fmt with format {:%Q %q} on a quantity")
|
||||
{
|
||||
CHECK(fmt::format("{:%Q %q}", q) == "2 × 10³");
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("percents")
|
||||
{
|
||||
const auto q = quantity_cast<percent>(15.q_m / 100.q_m);
|
||||
os << q;
|
||||
|
||||
SECTION("iostream")
|
||||
{
|
||||
CHECK(os.str() == "15 %");
|
||||
}
|
||||
|
||||
SECTION("fmt with default format {} on a quantity")
|
||||
{
|
||||
CHECK(fmt::format("{}", q) == os.str());
|
||||
}
|
||||
|
||||
SECTION("fmt with format {:%Q %q} on a quantity")
|
||||
{
|
||||
CHECK(fmt::format("{:%Q %q}", q) == os.str());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("quantity with an unkown dimension")
|
||||
{
|
||||
SECTION("unit::ratio::num == 1 && unit::ratio::den == 1")
|
||||
@@ -573,7 +639,7 @@ TEST_CASE("operator<< on a quantity", "[text][ostream][fmt]")
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("exp::num == 1 && exp::den == 1")
|
||||
SECTION("exponent::num == 1 && exponent::den == 1")
|
||||
{
|
||||
const auto q = 4q_m * 2q_s;
|
||||
os << q;
|
||||
@@ -594,7 +660,7 @@ TEST_CASE("operator<< on a quantity", "[text][ostream][fmt]")
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("exp::num == 2 && exp::den == 1 for positive exponent")
|
||||
SECTION("exponent::num == 2 && exponent::den == 1 for positive exponent")
|
||||
{
|
||||
const auto q = 4q_m * 2q_s * 2q_s;
|
||||
os << q;
|
||||
@@ -615,7 +681,7 @@ TEST_CASE("operator<< on a quantity", "[text][ostream][fmt]")
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("exp::num == 2 && exp::den == 1 for negative exponent (first dimension)")
|
||||
SECTION("exponent::num == 2 && exponent::den == 1 for negative exponent (first dimension)")
|
||||
{
|
||||
const auto q = 8q_s / 2q_m / 2q_m;
|
||||
os << q;
|
||||
@@ -636,7 +702,7 @@ TEST_CASE("operator<< on a quantity", "[text][ostream][fmt]")
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("exp::num == 2 && exp::den == 1 for negative exponent (not first dimension)")
|
||||
SECTION("exponent::num == 2 && exponent::den == 1 for negative exponent (not first dimension)")
|
||||
{
|
||||
const auto q = 8q_m / 2q_kg / 2q_kg;
|
||||
os << q;
|
||||
|
||||
@@ -63,10 +63,12 @@ TEST_CASE("absolute functions on quantity returns the absolute value", "[math][a
|
||||
REQUIRE(abs(-1q_m) == 1q_m);
|
||||
}
|
||||
|
||||
#ifndef COMP_MSVC
|
||||
SECTION ("floating-point representation")
|
||||
{
|
||||
REQUIRE(abs(-1.q_m) == 1q_m);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
SECTION ("'abs()' on a positive quantity returns the abs")
|
||||
@@ -76,10 +78,12 @@ TEST_CASE("absolute functions on quantity returns the absolute value", "[math][a
|
||||
REQUIRE(abs(1q_m) == 1q_m);
|
||||
}
|
||||
|
||||
#ifndef COMP_MSVC
|
||||
SECTION ("floating-point representation")
|
||||
{
|
||||
REQUIRE(abs(1.q_m) == 1q_m);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -33,14 +33,14 @@ using namespace units::physical::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::exp<dim_voltage, 2>, units::exp<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<Unit U, Scalar 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::exp<dim_voltage, 1>, units::exp<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<Unit U, Scalar Rep = double>
|
||||
using amplitude_spectral_density = quantity<dim_amplitude_spectral_density, U, Rep>;
|
||||
@@ -60,7 +60,7 @@ static_assert(is_same_v<decltype(sqrt(power_spectral_density<sq_volt_per_hertz>(
|
||||
namespace {
|
||||
|
||||
struct kilogram_per_second : unit<kilogram_per_second> {};
|
||||
struct dim_mass_rate : derived_dimension<dim_mass_rate, kilogram_per_second, units::exp<dim_mass, 1>, units::exp<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 : deduced_unit<kilogram_per_hour, dim_mass_rate, kilogram, hour> {};
|
||||
constexpr auto a = 1q_kg / 1q_h;
|
||||
static_assert(is_same_v<decltype(a)::unit, kilogram_per_hour>);
|
||||
|
||||
@@ -39,8 +39,8 @@ struct d3 : base_dimension<"d3", u3> {};
|
||||
|
||||
// exp_invert
|
||||
|
||||
static_assert(is_same_v<exp_invert<units::exp<d0, 2>>, units::exp<d0, -2>>);
|
||||
static_assert(is_same_v<exp_invert<units::exp<d1, -2>>, units::exp<d1, 2>>);
|
||||
static_assert(is_same_v<exp_invert<units::exponent<d0, 2>>, units::exponent<d0, -2>>);
|
||||
static_assert(is_same_v<exp_invert<units::exponent<d1, -2>>, units::exponent<d1, 2>>);
|
||||
|
||||
// dim_unpack
|
||||
|
||||
@@ -54,66 +54,66 @@ template<Exponent... Es>
|
||||
using derived_dim = detail::derived_dimension_base<Es...>;
|
||||
|
||||
static_assert(is_same_v<dim_unpack<>, exp_list<>>);
|
||||
static_assert(is_same_v<dim_unpack<units::exp<d0, 1>>, exp_list<units::exp<d0, 1>>>);
|
||||
static_assert(is_same_v<dim_unpack<units::exp<d0, 1>, units::exp<d1, 2>>, exp_list<units::exp<d0, 1>, units::exp<d1, 2>>>);
|
||||
using dim1 = derived_dim<units::exp<d0, 1>>;
|
||||
using dim2 = derived_dim<units::exp<d0, 1>, units::exp<d1, 2>>;
|
||||
static_assert(is_same_v<dim_unpack<units::exp<dim1, 2>, units::exp<d0, 1>>, exp_list<units::exp<d0, 2>, units::exp<d0, 1>>>);
|
||||
static_assert(is_same_v<dim_unpack<units::exp<dim2, -2>, units::exp<d0, 1>, units::exp<d1, 2>>,
|
||||
exp_list<units::exp<d0, -2>, units::exp<d1, -4>, units::exp<d0, 1>, units::exp<d1, 2>>>);
|
||||
static_assert(is_same_v<dim_unpack<units::exponent<d0, 1>>, exp_list<units::exponent<d0, 1>>>);
|
||||
static_assert(is_same_v<dim_unpack<units::exponent<d0, 1>, units::exponent<d1, 2>>, exp_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>>, exp_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>>,
|
||||
exp_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::exp<d0, -1>>>, d0>);
|
||||
static_assert(is_same_v<dim_invert<derived_dim<units::exp<d0, -2>>>, unknown_dimension<units::exp<d0, 2>>>);
|
||||
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::exp<d0, 2>, units::exp<d1, -1>>>, unknown_dimension<units::exp<d0, -2>, units::exp<d1, 1>>>);
|
||||
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
|
||||
|
||||
template<typename... Ts>
|
||||
using make_dimension = detail::make_dimension<Ts...>;
|
||||
|
||||
static_assert(is_same_v<make_dimension<units::exp<d0, 1>>, derived_dim<units::exp<d0, 1>>>);
|
||||
static_assert(is_same_v<make_dimension<units::exp<d0, 1>, units::exp<d1, 1>>, derived_dim<units::exp<d0, 1>, units::exp<d1, 1>>>);
|
||||
static_assert(is_same_v<make_dimension<units::exp<d1, 1>, units::exp<d0, 1>>, derived_dim<units::exp<d0, 1>, units::exp<d1, 1>>>);
|
||||
static_assert(is_same_v<make_dimension<units::exp<d1, 1>, units::exp<d1, 1>>, derived_dim<units::exp<d1, 2>>>);
|
||||
static_assert(is_same_v<make_dimension<units::exp<d1, 1>, units::exp<d1, 1, 2>>, derived_dim<units::exp<d1, 3, 2>>>);
|
||||
static_assert(is_same_v<make_dimension<units::exp<d1, 1, 2>, units::exp<d1, 1, 2>>, derived_dim<units::exp<d1, 1>>>);
|
||||
static_assert(is_same_v<make_dimension<units::exp<d1, 2>, units::exp<d1, 1, 2>>, derived_dim<units::exp<d1, 5, 2>>>);
|
||||
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::exp<d0, 1>, units::exp<d1, 1>, units::exp<d0, 1>, units::exp<d1, 1>>,
|
||||
derived_dim<units::exp<d0, 2>, units::exp<d1, 2>>>);
|
||||
static_assert(is_same_v<make_dimension<units::exp<d0, -1>, units::exp<d1, -1>, units::exp<d0, -1>, units::exp<d1, -1>>,
|
||||
derived_dim<units::exp<d0, -2>, units::exp<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::exp<d0, 1>, units::exp<d1, 1>, units::exp<d1, -1>>, derived_dim<units::exp<d0, 1>>>);
|
||||
static_assert(is_same_v<make_dimension<units::exp<d0, 1>, units::exp<d0, -1>, units::exp<d1, 1>>, derived_dim<units::exp<d1, 1>>>);
|
||||
static_assert(is_same_v<make_dimension<units::exp<d0, 1>, units::exp<d1, 1>, units::exp<d0, -1>>, derived_dim<units::exp<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::exp<d0, 1>>, derived_dim<units::exp<d1, 1>>>,
|
||||
unknown_dimension<units::exp<d0, 1>, units::exp<d1, 1>>>);
|
||||
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::exp<d0, 1>>, d1>, unknown_dimension<units::exp<d0, 1>, units::exp<d1, 1>>>);
|
||||
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::exp<d1, 1>>>, unknown_dimension<units::exp<d0, 1>, units::exp<d1, 1>>>);
|
||||
static_assert(is_same_v<dimension_multiply<d0, d1>, unknown_dimension<units::exp<d0, 1>, units::exp<d1, 1>>>);
|
||||
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::exp<d0, 1>, units::exp<d1, 1>, units::exp<d2, 1>>, derived_dim<units::exp<d3, 1>>>,
|
||||
unknown_dimension<units::exp<d0, 1>, units::exp<d1, 1>, units::exp<d2, 1>, units::exp<d3, 1>>>);
|
||||
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::exp<d0, 1>, units::exp<d1, 1>, units::exp<d2, 1>>, derived_dim<units::exp<d1, 1>>>,
|
||||
unknown_dimension<units::exp<d0, 1>, units::exp<d1, 2>, units::exp<d2, 1>>>);
|
||||
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::exp<d0, 1>, units::exp<d1, 1>, units::exp<d2, 1>>, derived_dim<units::exp<d1, -1>>>,
|
||||
unknown_dimension<units::exp<d0, 1>, units::exp<d2, 1>>>);
|
||||
static_assert(is_same_v<dimension_multiply<derived_dim<units::exp<d0, 2>>, derived_dim<units::exp<d0, -1>>>, d0>);
|
||||
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::exp<d0, 1>>, derived_dim<units::exp<d1, 1>>>,
|
||||
unknown_dimension<units::exp<d0, 1>, units::exp<d1, -1>>>);
|
||||
static_assert(is_same_v<dimension_divide<derived_dim<units::exp<d0, 2>>, unknown_dimension<units::exp<d0, 1>>>, d0>);
|
||||
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>);
|
||||
|
||||
} // namespace
|
||||
@@ -161,21 +161,21 @@ static_assert(
|
||||
static_assert(
|
||||
is_same_v<decltype(speed<metre_per_second, int>() * physical::si::time<hour, int>()), length<scaled_unit<ratio(36, 1, 2), metre>, int>>);
|
||||
static_assert(is_same_v<decltype(length<metre>() * physical::si::time<minute>()),
|
||||
quantity<unknown_dimension<units::exp<dim_length, 1>, units::exp<dim_time, 1>>, scaled_unit<ratio(6, 1, 1), unknown_coherent_unit>>>);
|
||||
quantity<unknown_dimension<units::exponent<dim_length, 1>, units::exponent<dim_time, 1>>, scaled_unit<ratio(6, 1, 1), unknown_coherent_unit>>>);
|
||||
static_assert(is_same_v<decltype(1 / physical::si::time<second, int>()), frequency<hertz, int>>);
|
||||
static_assert(is_same_v<decltype(1 / physical::si::time<minute, int>()), frequency<scaled_unit<ratio(1, 6, -1), hertz>, int>>);
|
||||
static_assert(is_same_v<decltype(1 / frequency<hertz, int>()), physical::si::time<second, int>>);
|
||||
static_assert(is_same_v<decltype(1 / length<kilometre>()),
|
||||
quantity<unknown_dimension<units::exp<dim_length, -1>>, scaled_unit<ratio(1, 1, -3), unknown_coherent_unit>>>);
|
||||
quantity<unknown_dimension<units::exponent<dim_length, -1>>, scaled_unit<ratio(1, 1, -3), unknown_coherent_unit>>>);
|
||||
static_assert(is_same_v<decltype(length<metre, int>() / 1.0), length<metre, double>>);
|
||||
static_assert(is_same_v<decltype(length<metre, int>() / length<metre, double>()), double>);
|
||||
static_assert(is_same_v<decltype(length<kilometre, int>() / length<metre, double>()), double>);
|
||||
static_assert(is_same_v<decltype(length<metre, int>() / length<metre, double>()), dimensionless<unitless, double>>);
|
||||
static_assert(is_same_v<decltype(length<kilometre, int>() / length<metre, double>()), dimensionless<scaled_unit<ratio(1, 1, 3), unitless>, double>>);
|
||||
static_assert(
|
||||
is_same_v<decltype(length<metre, int>() / physical::si::time<second, int>()), speed<metre_per_second, int>>);
|
||||
static_assert(
|
||||
is_same_v<decltype(length<metre>() / physical::si::time<minute>()), speed<scaled_unit<ratio(1, 6, -1), metre_per_second>>>);
|
||||
static_assert(is_same_v<decltype(physical::si::time<minute>() / length<metre>()),
|
||||
quantity<unknown_dimension<units::exp<dim_length, -1>, units::exp<dim_time, 1>>, scaled_unit<ratio(6 ,1 , 1), unknown_coherent_unit>>>);
|
||||
quantity<unknown_dimension<units::exponent<dim_length, -1>, units::exponent<dim_time, 1>>, scaled_unit<ratio(6 ,1 , 1), unknown_coherent_unit>>>);
|
||||
static_assert(is_same_v<decltype(length<metre, int>() % short(1)), length<metre, int>>);
|
||||
static_assert(is_same_v<decltype(length<metre, int>() % length<metre, short>(1)), length<metre, int>>);
|
||||
|
||||
@@ -186,14 +186,27 @@ static_assert((1q_km - 1q_m).count() == 999);
|
||||
static_assert((2q_m * 2).count() == 4);
|
||||
static_assert((3 * 3q_m).count() == 9);
|
||||
static_assert((4q_m / 2).count() == 2);
|
||||
static_assert(4q_m / 2q_m == 2);
|
||||
static_assert(4q_km / 2000q_m == 2);
|
||||
static_assert((4q_km / 2q_m).count() == 2);
|
||||
static_assert((4000q_m / 2q_m).count() == 2000);
|
||||
static_assert((7q_m % 2).count() == 1);
|
||||
static_assert((7q_m % 2q_m).count() == 1);
|
||||
static_assert((7q_km % 2000q_m).count() == 1000);
|
||||
|
||||
static_assert((10q_km2 * 10q_km2) / 50q_km2 == 2q_km2);
|
||||
|
||||
constexpr auto q1 = 10q_km / 5q_m;
|
||||
static_assert(std::is_same_v<decltype(q1), const dimensionless<scaled_unit<ratio(1, 1, 3), unitless>, std::int64_t>>);
|
||||
static_assert(q1.count() == 2);
|
||||
|
||||
constexpr dimensionless<unitless> q2 = q1;
|
||||
static_assert(q2.count() == 2000);
|
||||
|
||||
static_assert(quantity_cast<unitless>(q1).count() == 2000);
|
||||
|
||||
constexpr auto q3 = 10q_s * 2q_kHz;
|
||||
static_assert(std::is_same_v<decltype(q3), const dimensionless<scaled_unit<ratio(1, 1, 3), unitless>, std::int64_t>>);
|
||||
static_assert(q3.count() == 20);
|
||||
|
||||
// comparators
|
||||
|
||||
static_assert(2q_m + 1q_m == 3q_m);
|
||||
@@ -264,6 +277,37 @@ static_assert(quantity_cast<metre>(2q_km).count() == 2000);
|
||||
static_assert(quantity_cast<kilometre>(2000q_m).count() == 2);
|
||||
static_assert(quantity_cast<int>(1.23q_m).count() == 1);
|
||||
|
||||
// dimensionless
|
||||
|
||||
static_assert(std::is_convertible_v<double, dimensionless<unitless>>);
|
||||
static_assert(std::is_convertible_v<float, dimensionless<unitless>>);
|
||||
static_assert(!std::is_convertible_v<double, dimensionless<unitless, int>>);
|
||||
static_assert(std::is_convertible_v<int, dimensionless<unitless>>);
|
||||
|
||||
static_assert(!std::is_convertible_v<double, dimensionless<scaled_unit<ratio(1, 1, 1), unitless>>>);
|
||||
static_assert(std::is_constructible_v<dimensionless<scaled_unit<ratio(1, 1, 1), unitless>>, double>);
|
||||
|
||||
static_assert(dimensionless<unitless>(1.23) + dimensionless<unitless>(1.23) == dimensionless<unitless>(2.46));
|
||||
static_assert(dimensionless<unitless>(1.23) + dimensionless<unitless>(1.23) == 2.46);
|
||||
static_assert(dimensionless<unitless>(1.23) + 1.23 == 2.46);
|
||||
static_assert(1.23 + dimensionless<unitless>(1.23) == 2.46);
|
||||
static_assert(dimensionless<unitless>(1) + 1 == 2);
|
||||
static_assert(dimensionless<unitless, int>(1) + 1 == 2);
|
||||
|
||||
template<typename Rep>
|
||||
concept invalid_dimensionless_operation = requires()
|
||||
{
|
||||
!requires(dimensionless<unitless, Rep> d) { d + 1.23; };
|
||||
!requires(dimensionless<unitless, Rep> d) { 1.23 + d; };
|
||||
!requires(dimensionless<scaled_unit<ratio(1, 1, 1), unitless>, Rep> d) { 1 + d; };
|
||||
!requires(dimensionless<scaled_unit<ratio(1, 1, 1), unitless>, Rep> d) { d + 1; };
|
||||
};
|
||||
static_assert(invalid_dimensionless_operation<int>);
|
||||
|
||||
static_assert(quantity_cast<percent>(50.q_m / 100.q_m).count() == 50);
|
||||
static_assert(50.q_m / 100.q_m == dimensionless<percent>(50));
|
||||
|
||||
|
||||
// time
|
||||
|
||||
static_assert(1q_h == 3600q_s);
|
||||
|
||||
@@ -40,7 +40,9 @@ static_assert(1q_hm == 100q_m);
|
||||
static_assert(1q_au == 149'597'870'700q_m);
|
||||
static_assert(1q_km + 1q_m == 1001q_m);
|
||||
static_assert(10q_km / 5q_km == 2);
|
||||
static_assert(100q_mm / 5q_cm == 2);
|
||||
static_assert(10q_km / 5q_km < 3);
|
||||
static_assert(100q_mm / 5q_cm == dimensionless<scaled_unit<ratio(1, 1, -1), unitless>>(20));
|
||||
static_assert(100q_mm / 5q_cm == dimensionless<unitless>(2));
|
||||
static_assert(10q_km / 2 == 5q_km);
|
||||
|
||||
static_assert(millimetre::symbol == "mm");
|
||||
@@ -102,7 +104,8 @@ static_assert(120 / 1q_min == 2q_Hz);
|
||||
static_assert(1000 / 1q_s == 1q_kHz);
|
||||
static_assert(1 / 1q_ms == 1q_kHz);
|
||||
static_assert(3.2q_GHz == 3'200'000'000q_Hz);
|
||||
static_assert(10q_Hz * 1q_min == 600);
|
||||
static_assert(10q_Hz * 1q_min == dimensionless<scaled_unit<ratio(60), unitless>>(10));
|
||||
static_assert(10q_Hz * 1q_min == dimensionless<unitless>(600));
|
||||
static_assert(2 / 1q_Hz == 2q_s);
|
||||
|
||||
// force
|
||||
|
||||
@@ -98,20 +98,20 @@ struct d0 : base_dimension<"d0", u0> {};
|
||||
struct u1 : named_unit<u1, "u1", no_prefix> {};
|
||||
struct d1 : base_dimension<"d1", u1> {};
|
||||
|
||||
static_assert(is_same_v<type_list_merge_sorted<type_list<units::exp<d0, 1>>, type_list<units::exp<d1, 1>>, exp_less>,
|
||||
type_list<units::exp<d0, 1>, units::exp<d1, 1>>>);
|
||||
static_assert(is_same_v<type_list_merge_sorted<type_list<units::exp<d1, 1>>, type_list<units::exp<d0, 1>>, exp_less>,
|
||||
type_list<units::exp<d0, 1>, units::exp<d1, 1>>>);
|
||||
static_assert(is_same_v<type_list_merge_sorted<type_list<units::exponent<d0, 1>>, type_list<units::exponent<d1, 1>>, exp_less>,
|
||||
type_list<units::exponent<d0, 1>, units::exponent<d1, 1>>>);
|
||||
static_assert(is_same_v<type_list_merge_sorted<type_list<units::exponent<d1, 1>>, type_list<units::exponent<d0, 1>>, exp_less>,
|
||||
type_list<units::exponent<d0, 1>, units::exponent<d1, 1>>>);
|
||||
|
||||
// type_list_sort
|
||||
|
||||
template<TypeList List>
|
||||
using exp_sort = type_list_sort<List, exp_less>;
|
||||
|
||||
static_assert(is_same_v<exp_sort<exp_list<units::exp<d0, 1>>>, exp_list<units::exp<d0, 1>>>);
|
||||
static_assert(is_same_v<exp_sort<exp_list<units::exponent<d0, 1>>>, exp_list<units::exponent<d0, 1>>>);
|
||||
static_assert(
|
||||
is_same_v<exp_sort<exp_list<units::exp<d0, 1>, units::exp<d1, -1>>>, exp_list<units::exp<d0, 1>, units::exp<d1, -1>>>);
|
||||
is_same_v<exp_sort<exp_list<units::exponent<d0, 1>, units::exponent<d1, -1>>>, exp_list<units::exponent<d0, 1>, units::exponent<d1, -1>>>);
|
||||
static_assert(
|
||||
is_same_v<exp_sort<exp_list<units::exp<d1, 1>, units::exp<d0, -1>>>, exp_list<units::exp<d0, -1>, units::exp<d1, 1>>>);
|
||||
is_same_v<exp_sort<exp_list<units::exponent<d1, 1>, units::exponent<d0, -1>>>, exp_list<units::exponent<d0, -1>, units::exponent<d1, 1>>>);
|
||||
|
||||
} // namespace
|
||||
@@ -46,7 +46,7 @@ static_assert([]<Prefix P>(P) { return !requires { typename prefixed_unit<struct
|
||||
#endif
|
||||
|
||||
struct metre_per_second : unit<metre_per_second> {};
|
||||
struct dim_speed : derived_dimension<dim_speed, metre_per_second, units::exp<dim_length, 1>, units::exp<dim_time, -1>> {};
|
||||
struct dim_speed : derived_dimension<dim_speed, metre_per_second, units::exponent<dim_length, 1>, units::exponent<dim_time, -1>> {};
|
||||
struct kilometre_per_hour : deduced_unit<kilometre_per_hour, dim_speed, kilometre, hour> {};
|
||||
|
||||
static_assert(is_same_v<downcast<scaled_unit<ratio(1), metre>>, metre>);
|
||||
|
||||
Reference in new issue
Block a user