mirror of
https://github.com/mpusz/mp-units.git
synced 2025-08-03 20:34:26 +02:00
@@ -28,6 +28,6 @@ The same constant defined for natural units may be provided as::
|
||||
namespace natural {
|
||||
|
||||
template<ScalableNumber Rep = double>
|
||||
inline constexpr auto speed_of_light = speed<unitless, Rep>(1);
|
||||
inline constexpr auto speed_of_light = speed<one, Rep>(1);
|
||||
|
||||
}
|
||||
|
@@ -110,16 +110,16 @@ represent numbers it would be highly uncomfortable to every time type::
|
||||
|
||||
const auto d1 = 10q_km;
|
||||
const auto d2 = 3q_km;
|
||||
if(d1 / d2 > dimensionless<unitless, 2>) {
|
||||
if(d1 / d2 > dimensionless<one, 2>) {
|
||||
// ...
|
||||
}
|
||||
|
||||
or::
|
||||
|
||||
const auto fill_time_left = (box.height / box.fill_level(measured_mass) -
|
||||
dimensionless<unitless, 1>) * fill_time;
|
||||
dimensionless<one, 1>) * fill_time;
|
||||
|
||||
This is why it was decided to allow the ``dimensionless<unitless>`` quantity of any
|
||||
This is why it was decided to allow the ``dimensionless<one>`` quantity of any
|
||||
representation type to be implicitly constructible from this representation type.
|
||||
With that the above examples can be rewritten as follows::
|
||||
|
||||
@@ -133,7 +133,7 @@ and::
|
||||
|
||||
const auto fill_time_left = (box.height / box.fill_level(measured_mass) - 1) * fill_time;
|
||||
|
||||
The above is true only for dimensionless quantities of `unitless` unit. If our quantity have a unit with
|
||||
The above is true only for dimensionless quantities of `one` unit. If our quantity have a unit with
|
||||
ratio different than ``1`` the implicit conversion will not happen. This is to prevent cases were the code
|
||||
could be ambiguous. For example::
|
||||
|
||||
@@ -148,14 +148,14 @@ either change the type of the resulting unit to the one having ``ratio(1)`` (:te
|
||||
|
||||
Dimensionless auto foo(Length auto d1, Length auto d2)
|
||||
{
|
||||
return quantity_cast<unitless>(d1 / d2) + 1;
|
||||
return quantity_cast<one>(d1 / d2) + 1;
|
||||
}
|
||||
|
||||
or to explicitly state what is the unit of our dimensionless value, e.g. `unitless`, `percent`, etc::
|
||||
or to explicitly state what is the unit of our dimensionless value, e.g. `one`, `percent`, etc::
|
||||
|
||||
Dimensionless auto foo(Length auto d1, Length auto d2)
|
||||
{
|
||||
return d1 / d2 + dimensionless<unitless>(1);
|
||||
return d1 / d2 + dimensionless<one>(1);
|
||||
}
|
||||
|
||||
There is one more important point to note here. As the the dimensionless quantity is more than just
|
||||
@@ -166,7 +166,7 @@ code will not compile::
|
||||
|
||||
To make it compile fine we have to either explicitly get the value stored in the quantity::
|
||||
|
||||
auto v = std::exp(quantity_cast<unitless>(10q_m / 5q_m).count());
|
||||
auto v = std::exp(quantity_cast<one>(10q_m / 5q_m).count());
|
||||
|
||||
or use a mathematical wrapper function from `units` namespace::
|
||||
|
||||
|
@@ -167,7 +167,7 @@ Whenever we divide two quantities of the same dimension we end up with a
|
||||
:term:`dimensionless quantity` otherwise known as :term:`quantity of dimension one`::
|
||||
|
||||
static_assert(10q_km / 5q_km == 2);
|
||||
static_assert(std::is_same_v<decltype(10q_km / 5q_km), quantity<dim_one, unitless, std::int64_t>>);
|
||||
static_assert(std::is_same_v<decltype(10q_km / 5q_km), quantity<dim_one, one, std::int64_t>>);
|
||||
|
||||
According to the official ISO definition `dim_one` is a dimension "for which all the
|
||||
exponents of the factors corresponding to the base quantities in its quantity dimension
|
||||
@@ -189,10 +189,10 @@ are provided::
|
||||
|
||||
There are two special units provided for usage with such a quantity:
|
||||
|
||||
- `unitless` which is the :ref:`coherent unit` of dimensionless quantity and does not
|
||||
- `one` which is the :ref:`coherent unit` of dimensionless quantity and does not
|
||||
provide any textual symbol (according to the ISO definition "the measurement units and
|
||||
values of quantities of dimension one are numbers"),
|
||||
- `percent` which has the symbol ``%`` and ``ratio(1, 100)`` of the `unitless` unit.
|
||||
- `percent` which has the symbol ``%`` and ``ratio(1, 100)`` of the `one` unit.
|
||||
|
||||
For example the following code::
|
||||
|
||||
|
@@ -26,8 +26,8 @@
|
||||
|
||||
namespace units {
|
||||
|
||||
struct unitless : named_unit<unitless, "", no_prefix> {};
|
||||
struct percent : named_scaled_unit<percent, "%", no_prefix, ratio(1, 100), unitless> {};
|
||||
struct one : named_unit<one, "", no_prefix> {};
|
||||
struct percent : named_scaled_unit<percent, "%", no_prefix, ratio(1, 100), one> {};
|
||||
|
||||
/**
|
||||
* @brief Dimension one
|
||||
@@ -35,7 +35,7 @@ struct percent : named_scaled_unit<percent, "%", no_prefix, ratio(1, 100), unitl
|
||||
* Dimension for which all the exponents of the factors corresponding to the base
|
||||
* dimensions are zero. Also commonly named as "dimensionless".
|
||||
*/
|
||||
struct dim_one : derived_dimension<dim_one, unitless> {};
|
||||
struct dim_one : derived_dimension<dim_one, one> {};
|
||||
|
||||
template<typename T>
|
||||
concept Dimensionless = QuantityOf<T, dim_one>;
|
||||
|
@@ -27,6 +27,6 @@
|
||||
namespace units::physical::natural {
|
||||
|
||||
template<ScalableNumber Rep = double>
|
||||
inline constexpr auto speed_of_light = speed<unitless, Rep>(1);
|
||||
inline constexpr auto speed_of_light = speed<one, Rep>(1);
|
||||
|
||||
} // namespace units::physical::natural
|
||||
|
@@ -40,7 +40,7 @@ struct dim_mass : physical::dim_mass<gigaelectronvolt> {};
|
||||
template<Unit U, ScalableNumber Rep = double>
|
||||
using mass = quantity<dim_mass, U, Rep>;
|
||||
|
||||
struct dim_speed : physical::dim_speed<dim_speed, unitless, dim_length, dim_time> {};
|
||||
struct dim_speed : physical::dim_speed<dim_speed, one, dim_length, dim_time> {};
|
||||
template<Unit U, ScalableNumber Rep = double>
|
||||
using speed = quantity<dim_speed, U, Rep>;
|
||||
|
||||
|
@@ -27,7 +27,6 @@
|
||||
|
||||
namespace units::physical::natural {
|
||||
|
||||
struct unitless : named_unit<unitless, "", no_prefix> {};
|
||||
struct electronvolt : named_unit<electronvolt, "eV", si::prefix> {};
|
||||
struct gigaelectronvolt : prefixed_unit<gigaelectronvolt, si::giga, electronvolt> {};
|
||||
struct inverted_gigaelectronvolt : named_unit<inverted_gigaelectronvolt, basic_symbol_text{"GeV⁻¹", "GeV^-1"}, no_prefix> {};
|
||||
|
@@ -73,7 +73,7 @@ public:
|
||||
|
||||
template<ScalableNumber Value>
|
||||
requires detail::safe_convertible<Value, rep>
|
||||
constexpr explicit(!(std::is_same_v<dimension, dim_one> && std::is_same_v<unit, unitless>)) quantity(const Value& v) : value_{static_cast<rep>(v)} {}
|
||||
constexpr explicit(!(std::is_same_v<dimension, dim_one> && std::is_same_v<unit, one>)) quantity(const Value& v) : value_{static_cast<rep>(v)} {}
|
||||
|
||||
template<Quantity Q2>
|
||||
requires equivalent_dim<D, typename Q2::dimension> &&
|
||||
|
@@ -423,7 +423,7 @@ TEST_CASE("operator<< on a quantity", "[text][ostream][fmt]")
|
||||
|
||||
SECTION("dimensionless quantity")
|
||||
{
|
||||
SECTION("unitless with ratio == 1")
|
||||
SECTION("one with ratio == 1")
|
||||
{
|
||||
const auto q = 4q_m / 2q_m;
|
||||
os << q;
|
||||
@@ -444,7 +444,7 @@ TEST_CASE("operator<< on a quantity", "[text][ostream][fmt]")
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("unitless with ratio.exp != 0")
|
||||
SECTION("one with ratio.exp != 0")
|
||||
{
|
||||
const auto q = 4q_km / 2q_m;
|
||||
os << q;
|
||||
|
@@ -168,8 +168,8 @@ static_assert(is_same_v<decltype(1 / frequency<hertz, int>()), physical::si::tim
|
||||
static_assert(is_same_v<decltype(1 / length<kilometre>()),
|
||||
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>()), 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>() / length<metre, double>()), dimensionless<one, double>>);
|
||||
static_assert(is_same_v<decltype(length<kilometre, int>() / length<metre, double>()), dimensionless<scaled_unit<ratio(1, 1, 3), one>, double>>);
|
||||
static_assert(
|
||||
is_same_v<decltype(length<metre, int>() / physical::si::time<second, int>()), speed<metre_per_second, int>>);
|
||||
static_assert(
|
||||
@@ -195,16 +195,16 @@ 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(std::is_same_v<decltype(q1), const dimensionless<scaled_unit<ratio(1, 1, 3), one>, std::int64_t>>);
|
||||
static_assert(q1.count() == 2);
|
||||
|
||||
constexpr dimensionless<unitless> q2 = q1;
|
||||
constexpr dimensionless<one> q2 = q1;
|
||||
static_assert(q2.count() == 2000);
|
||||
|
||||
static_assert(quantity_cast<unitless>(q1).count() == 2000);
|
||||
static_assert(quantity_cast<one>(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(std::is_same_v<decltype(q3), const dimensionless<scaled_unit<ratio(1, 1, 3), one>, std::int64_t>>);
|
||||
static_assert(q3.count() == 20);
|
||||
|
||||
// comparators
|
||||
@@ -279,32 +279,32 @@ 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<one>>);
|
||||
static_assert(std::is_convertible_v<float, dimensionless<one>>);
|
||||
static_assert(!std::is_convertible_v<double, dimensionless<one, int>>);
|
||||
static_assert(std::is_convertible_v<int, dimensionless<one>>);
|
||||
|
||||
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(!std::is_convertible_v<double, dimensionless<scaled_unit<ratio(1, 1, 1), one>>>);
|
||||
static_assert(std::is_constructible_v<dimensionless<scaled_unit<ratio(1, 1, 1), one>>, 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);
|
||||
static_assert(dimensionless<one>(1.23) + dimensionless<one>(1.23) == dimensionless<one>(2.46));
|
||||
static_assert(dimensionless<one>(1.23) + dimensionless<one>(1.23) == 2.46);
|
||||
static_assert(dimensionless<one>(1.23) + 1.23 == 2.46);
|
||||
static_assert(1.23 + dimensionless<one>(1.23) == 2.46);
|
||||
static_assert(dimensionless<one>(1) + 1 == 2);
|
||||
static_assert(dimensionless<one, 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; };
|
||||
!requires(dimensionless<one, Rep> d) { d + 1.23; };
|
||||
!requires(dimensionless<one, Rep> d) { 1.23 + d; };
|
||||
!requires(dimensionless<scaled_unit<ratio(1, 1, 1), one>, Rep> d) { 1 + d; };
|
||||
!requires(dimensionless<scaled_unit<ratio(1, 1, 1), one>, Rep> d) { d + 1; };
|
||||
};
|
||||
static_assert(invalid_dimensionless_operation<int>);
|
||||
|
||||
static_assert(std::is_same_v<decltype(10q_km / 5q_km), quantity<dim_one, unitless, std::int64_t>>);
|
||||
static_assert(std::is_same_v<decltype(10q_km / 5q_km), quantity<dim_one, one, std::int64_t>>);
|
||||
|
||||
static_assert(quantity_cast<percent>(50.q_m / 100.q_m).count() == 50);
|
||||
static_assert(50.q_m / 100.q_m == dimensionless<percent>(50));
|
||||
|
@@ -41,8 +41,8 @@ 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(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(100q_mm / 5q_cm == dimensionless<scaled_unit<ratio(1, 1, -1), one>>(20));
|
||||
static_assert(100q_mm / 5q_cm == dimensionless<one>(2));
|
||||
static_assert(10q_km / 2 == 5q_km);
|
||||
|
||||
static_assert(millimetre::symbol == "mm");
|
||||
@@ -105,8 +105,8 @@ 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).count() == 10);
|
||||
static_assert(10q_Hz * 1q_min == dimensionless<scaled_unit<ratio(60), unitless>>(10));
|
||||
static_assert(10q_Hz * 1q_min == dimensionless<unitless>(600));
|
||||
static_assert(10q_Hz * 1q_min == dimensionless<scaled_unit<ratio(60), one>>(10));
|
||||
static_assert(10q_Hz * 1q_min == dimensionless<one>(600));
|
||||
static_assert(2 / 1q_Hz == 2q_s);
|
||||
|
||||
// force
|
||||
|
Reference in New Issue
Block a user