2020-03-09 18:55:41 +01:00
|
|
|
.. namespace:: units
|
|
|
|
|
|
|
|
|
|
Quantities
|
|
|
|
|
==========
|
|
|
|
|
|
|
|
|
|
A :term:`quantity` is a concrete amount of a unit for a specified dimension
|
|
|
|
|
with a specific representation and is represented in the library with a
|
|
|
|
|
`quantity` class template.
|
|
|
|
|
|
|
|
|
|
|
2020-09-14 08:45:36 +02:00
|
|
|
Construction
|
|
|
|
|
------------
|
2020-03-09 18:55:41 +01:00
|
|
|
|
2020-09-08 21:17:09 +02:00
|
|
|
To create the quantity object from a :term:`scalable number` we just have to pass
|
2020-03-09 18:55:41 +01:00
|
|
|
the value to the `quantity` class template explicit constructor::
|
|
|
|
|
|
|
|
|
|
quantity<si::dim_length, si::kilometre, double> d(123);
|
2020-12-29 16:33:52 +01:00
|
|
|
quantity<si::dim_speed, si::kilometre_per_hour, int> v(70);
|
2020-03-09 18:55:41 +01:00
|
|
|
|
|
|
|
|
.. note::
|
|
|
|
|
|
|
|
|
|
As the constructor is explicit, the quantity object can be created from
|
|
|
|
|
an "unsafe" fundamental type only via
|
|
|
|
|
`direct initialization <https://en.cppreference.com/w/cpp/language/direct_initialization>`_.
|
|
|
|
|
This is why the code below using
|
|
|
|
|
`copy initialization <https://en.cppreference.com/w/cpp/language/copy_initialization>`_
|
|
|
|
|
**does not compile**::
|
|
|
|
|
|
|
|
|
|
quantity<si::dim_length, si::kilometre, double> d = 123; // ERROR
|
|
|
|
|
|
2020-12-29 16:33:52 +01:00
|
|
|
Dimension-Specific Aliases
|
|
|
|
|
++++++++++++++++++++++++++
|
|
|
|
|
|
2020-03-09 18:55:41 +01:00
|
|
|
To simplify `quantity` objects creation the library provides helper aliases for
|
|
|
|
|
quantities of each :term:`dimension` which additionally set the representation
|
|
|
|
|
type to ``double`` by default::
|
|
|
|
|
|
|
|
|
|
namespace si {
|
|
|
|
|
|
2020-10-06 18:17:52 +02:00
|
|
|
template<Unit U, QuantityValue Rep = double>
|
2020-03-09 18:55:41 +01:00
|
|
|
using length = quantity<dim_length, U, Rep>;
|
|
|
|
|
|
2020-12-29 16:33:52 +01:00
|
|
|
template<Unit U, QuantityValue Rep = double>
|
|
|
|
|
using speed = quantity<dim_speed, U, Rep>;
|
|
|
|
|
|
2020-03-09 18:55:41 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Thanks to that, the above example can be rewritten as follows::
|
|
|
|
|
|
|
|
|
|
si::length<si::kilometre> d(123);
|
2020-12-29 16:33:52 +01:00
|
|
|
si::speed<si::kilometre_per_hour, int> v(70);
|
|
|
|
|
|
|
|
|
|
User Defined Literals
|
|
|
|
|
+++++++++++++++++++++
|
2020-03-09 18:55:41 +01:00
|
|
|
|
|
|
|
|
To further simplify construction of quantities with compile-time known
|
|
|
|
|
values the library provides :abbr:`UDL (User Defined Literal)` s for each
|
2020-12-29 16:33:52 +01:00
|
|
|
:term:`unit` of every :term:`dimension`::
|
|
|
|
|
|
|
|
|
|
inline namespace literals {
|
|
|
|
|
|
2021-02-18 19:54:40 +01:00
|
|
|
constexpr auto operator"" _q_km(unsigned long long l) { return length<kilometre, std::int64_t>(l); }
|
|
|
|
|
constexpr auto operator"" _q_km(long double l) { return length<kilometre, long double>(l); }
|
2020-12-29 16:33:52 +01:00
|
|
|
|
2021-02-18 19:54:40 +01:00
|
|
|
constexpr auto operator"" _q_km_per_h(unsigned long long l) { return speed<kilometre_per_hour, std::int64_t>(l); }
|
|
|
|
|
constexpr auto operator"" _q_km_per_h(long double l) { return speed<kilometre_per_hour, long double>(l); }
|
2020-12-29 16:33:52 +01:00
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Thanks to them the same code can be as simple as::
|
2020-03-09 18:55:41 +01:00
|
|
|
|
2021-03-16 12:03:25 +01:00
|
|
|
using namespace units::isq::si::literals;
|
2020-12-29 16:33:52 +01:00
|
|
|
auto d = 123._q_km; // si::length<si::kilometre, long double>
|
|
|
|
|
auto v = 70_q_km_per_h; // si::speed<si::kilometre_per_hour, std::int64_t>
|
|
|
|
|
|
|
|
|
|
.. note::
|
|
|
|
|
|
|
|
|
|
``123._q_km`` should be read as a quantity of length in kilometers. Initially the
|
|
|
|
|
library did not use the ``_q_`` prefix for UDLs but it turned out that there are
|
|
|
|
|
a few unit symbols that collide with literals already existing in C and C++
|
|
|
|
|
language (i.e. ``F`` (farad), ``J`` (joule), ``W`` (watt), ``K`` (kelvin),
|
|
|
|
|
``d`` (day), ``l`` or ``L`` (litre), ``erg``, ``ergps``). This is why the
|
|
|
|
|
``_q_`` prefix was consistently applied to all the UDLs.
|
|
|
|
|
|
|
|
|
|
|
2021-03-18 18:36:44 -04:00
|
|
|
Quantity References
|
|
|
|
|
+++++++++++++++++++
|
2020-12-29 16:33:52 +01:00
|
|
|
|
2021-03-18 18:36:44 -04:00
|
|
|
Quantity References provide an alternative way to simplify quantities creation.
|
|
|
|
|
They are defined using the `reference` class template::
|
2020-12-29 16:33:52 +01:00
|
|
|
|
2021-03-18 18:36:44 -04:00
|
|
|
namespace references {
|
2020-12-29 16:33:52 +01:00
|
|
|
|
2021-03-18 18:36:44 -04:00
|
|
|
inline constexpr auto km = reference<dim_length, kilometre>{};
|
|
|
|
|
inline constexpr auto h = reference<dim_time, hour>{};
|
2020-12-29 16:33:52 +01:00
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
With the above our code can look as follows::
|
|
|
|
|
|
2021-03-18 18:36:44 -04:00
|
|
|
using namespace units::isq::si::references;
|
2020-12-29 16:33:52 +01:00
|
|
|
auto d = 123. * km; // si::length<si::kilometre, double>
|
2021-03-18 18:36:44 -04:00
|
|
|
auto v = 70 * (km / h); // si::speed<si::kilometre_per_hour, int>
|
2020-12-29 16:33:52 +01:00
|
|
|
|
|
|
|
|
.. important::
|
|
|
|
|
|
2021-03-18 18:56:31 -04:00
|
|
|
The following syntaxes are not allowed:
|
|
|
|
|
``2 / s``, ``km * 3``, ``s / 4``, ``70 * km / h``.
|
2020-12-29 16:33:52 +01:00
|
|
|
|
2021-03-18 18:36:44 -04:00
|
|
|
It is also allowed to easily define custom quantity references from existing ones::
|
2020-12-29 16:33:52 +01:00
|
|
|
|
|
|
|
|
inline constexpr auto Nm = N * m;
|
|
|
|
|
inline constexpr auto km_per_h = km / h;
|
|
|
|
|
inline constexpr auto mph = mi / h;
|
|
|
|
|
|
2021-03-18 18:36:44 -04:00
|
|
|
UDLs vs Quantity References
|
|
|
|
|
+++++++++++++++++++++++++++
|
2020-12-29 16:33:52 +01:00
|
|
|
|
2021-03-18 18:36:44 -04:00
|
|
|
UDLs are helpful but they also have some disadvantages compared to Quantity References:
|
2020-12-29 16:33:52 +01:00
|
|
|
|
|
|
|
|
1. UDLs are only for compile-time known values and do not work for runtime variables
|
|
|
|
|
|
2021-02-17 17:54:12 +01:00
|
|
|
- UDLs::
|
2020-12-29 16:33:52 +01:00
|
|
|
|
2021-03-16 12:03:25 +01:00
|
|
|
using namespace units::isq::si::literals;
|
2021-02-17 17:54:12 +01:00
|
|
|
auto v1 = 120_q_km / 2_q_h;
|
|
|
|
|
auto v2 = length<kilometre>(distance) / time<hour>(duration);
|
2020-12-29 16:33:52 +01:00
|
|
|
|
2021-03-18 18:36:44 -04:00
|
|
|
- Quantity References::
|
2020-12-29 16:33:52 +01:00
|
|
|
|
2021-03-18 18:36:44 -04:00
|
|
|
using namespace units::isq::si::references;
|
2021-02-17 17:54:12 +01:00
|
|
|
auto v1 = 120 * km / (2 * h);
|
2021-03-18 18:36:44 -04:00
|
|
|
auto v2 = distance * (1 * km) / (duration * (1 * h));
|
2021-02-17 17:54:12 +01:00
|
|
|
|
2021-03-18 18:36:44 -04:00
|
|
|
References treat both cases in a unified way. It is also worth to notice that we work
|
2021-02-17 17:54:12 +01:00
|
|
|
mostly with runtime variables and compile-time known values mostly appear only in physical
|
|
|
|
|
constants and unit tests.
|
2020-12-29 16:33:52 +01:00
|
|
|
|
|
|
|
|
2. UDLs cannot be disambiguated with a namespace name
|
|
|
|
|
|
2021-02-17 17:54:12 +01:00
|
|
|
- UDLs::
|
|
|
|
|
|
2021-03-16 12:03:25 +01:00
|
|
|
using namespace units::isq::si::literals;
|
|
|
|
|
using namespace units::isq::si::cgs::literals;
|
2021-02-17 17:54:12 +01:00
|
|
|
auto d = 1_q_cm; // FAILS TO COMPILE
|
2020-12-29 16:33:52 +01:00
|
|
|
|
2021-03-18 18:36:44 -04:00
|
|
|
- Quantity References::
|
2020-12-29 16:33:52 +01:00
|
|
|
|
2021-03-18 18:36:44 -04:00
|
|
|
inline constexpr auto si_cm = units::isq::si::references::cm;
|
|
|
|
|
inline constexpr auto cgs_cm = units::isq::si::cgs::references::cm;
|
2020-12-29 16:33:52 +01:00
|
|
|
|
2021-02-17 17:54:12 +01:00
|
|
|
auto d1 = 1. * si_cm; // si::length<si::centimetre>
|
|
|
|
|
auto d2 = 1. * cgs_cm; // si::cgs::length<si::centimetre>
|
2020-12-29 16:33:52 +01:00
|
|
|
|
2021-02-17 17:54:12 +01:00
|
|
|
3. Poor control over the representation types as UDLs return only ``std::int64_t`` or
|
|
|
|
|
``long double``
|
2020-12-29 16:33:52 +01:00
|
|
|
|
2021-02-17 17:54:12 +01:00
|
|
|
- UDLs::
|
2020-12-29 16:33:52 +01:00
|
|
|
|
2021-03-16 12:03:25 +01:00
|
|
|
using namespace units::isq::si::literals;
|
2021-02-17 17:54:12 +01:00
|
|
|
auto d1 = 123._q_km; // si::length<si::kilometre, long double>
|
|
|
|
|
auto d2 = 123_q_km; // si::length<si::kilometre, std::int64_t>
|
2020-12-29 16:33:52 +01:00
|
|
|
|
2021-02-17 17:54:12 +01:00
|
|
|
No possibility to obtain any other representation type.
|
2020-12-29 16:33:52 +01:00
|
|
|
|
2021-03-18 18:36:44 -04:00
|
|
|
- Quantity References::
|
2021-02-17 17:54:12 +01:00
|
|
|
|
2021-03-18 18:36:44 -04:00
|
|
|
using namespace units::isq::si::references;
|
2021-02-17 17:54:12 +01:00
|
|
|
auto d1 = 123. * km; // si::length<si::kilometre, double>
|
|
|
|
|
auto d2 = 123 * km; // si::length<si::kilometre, int>
|
|
|
|
|
auto d3 = 123.f * km; // si::length<si::kilometre, float>
|
|
|
|
|
auto d4 = 123.L * km; // si::length<si::kilometre, long double>
|
|
|
|
|
auto d5 = 123ul * km; // si::length<si::kilometre, unsigned long>
|
|
|
|
|
auto d6 = 123ll * km; // si::length<si::kilometre, long long>
|
2020-12-29 16:33:52 +01:00
|
|
|
|
|
|
|
|
4. UDLs are verbose to define and standardize
|
2021-02-17 17:54:12 +01:00
|
|
|
|
|
|
|
|
- UDLs:
|
|
|
|
|
|
|
|
|
|
- for each unit an integral and a floating-point UDL have to be defined
|
|
|
|
|
- have to be provided for unnamed derived units (i.e. ``_q_km_per_h``)
|
2020-12-29 16:33:52 +01:00
|
|
|
|
2021-03-18 18:36:44 -04:00
|
|
|
- Quantity References:
|
2021-02-17 17:54:12 +01:00
|
|
|
|
2021-03-18 18:36:44 -04:00
|
|
|
- one reference per unit
|
|
|
|
|
- unnamed derived units constructed from base references (i.e. ``km / h``)
|
2021-02-17 17:54:12 +01:00
|
|
|
|
|
|
|
|
5. Typical UDL definition for quantities when compiled with a ``-Wsign-conversion``
|
|
|
|
|
flag results in a compilation warning. This warning could be silenced with a
|
|
|
|
|
``static_cast<std::int64_t>(value)`` in every UDL, but in a such case other safety
|
|
|
|
|
and security issues could be silently introduced.
|
2021-03-18 18:36:44 -04:00
|
|
|
Quantity References, on the opposite, always use the exact representation type provided
|
2021-02-17 17:54:12 +01:00
|
|
|
by the user so there is no chance for a truncating conversion on a quantity construction.
|
2020-12-29 16:33:52 +01:00
|
|
|
|
2021-02-16 16:19:57 +01:00
|
|
|
|
2020-03-26 17:09:26 +01:00
|
|
|
Dimension-specific Concepts
|
2020-03-09 18:55:41 +01:00
|
|
|
---------------------------
|
|
|
|
|
|
|
|
|
|
In case the user does not care about the specific unit and representation but
|
|
|
|
|
requires quantity of a concrete dimension than dimension-specific concepts can
|
|
|
|
|
be used::
|
|
|
|
|
|
2021-03-16 12:03:25 +01:00
|
|
|
using namespace units::isq::si::literals;
|
2020-09-09 19:20:35 +02:00
|
|
|
constexpr Length auto d = 123_q_km; // si::length<si::kilometre, std::int64_t>
|
2020-03-09 18:55:41 +01:00
|
|
|
|
|
|
|
|
.. note::
|
|
|
|
|
|
|
|
|
|
All instances of `quantity` class always match the `Quantity` concept.
|
|
|
|
|
All other regular types that are not quantities are called
|
2020-09-08 21:17:09 +02:00
|
|
|
:term:`scalable numbers <scalable number>` by the library and match the
|
2020-10-06 18:17:52 +02:00
|
|
|
`QuantityValue` concept.
|
2020-03-09 18:55:41 +01:00
|
|
|
|
|
|
|
|
However, the above is not the most important usage of those concepts. Let's
|
|
|
|
|
assume that the user wants to implement an ``avg_speed`` function that will
|
|
|
|
|
be calculating the average speed based on provided distance and duration
|
|
|
|
|
quantities. The usage of such a function can look as follows::
|
|
|
|
|
|
2021-03-16 12:03:25 +01:00
|
|
|
using namespace units::isq::si::literals;
|
|
|
|
|
using namespace units::isq::si::international::literals;
|
2020-09-09 19:20:35 +02:00
|
|
|
constexpr Speed auto v1 = avg_speed(220_q_km, 2_q_h);
|
|
|
|
|
constexpr Speed auto v2 = avg_speed(140_q_mi, 2_q_h);
|
2020-03-09 18:55:41 +01:00
|
|
|
|
|
|
|
|
In this and all other physical units libraries such a function can be
|
|
|
|
|
implemented as::
|
|
|
|
|
|
2020-05-10 17:31:47 +02:00
|
|
|
constexpr si::speed<si::metre_per_second> avg_speed(si::length<si::metre> d,
|
|
|
|
|
si::time<si::second> t)
|
2020-03-09 18:55:41 +01:00
|
|
|
{
|
|
|
|
|
return d / t;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
While being correct, this function performs unnecessary intermediate
|
|
|
|
|
conversions (from kilometers to meters, from hours to seconds,
|
|
|
|
|
and from meters per second to kilometers per hour) which can affect
|
|
|
|
|
runtime performance and the precision of the final result. To eliminate
|
|
|
|
|
all that overhead we have to write a template function::
|
|
|
|
|
|
|
|
|
|
template<typename U1, typename R1, typename U2, typename R2>
|
|
|
|
|
constexpr auto avg_speed(si::length<U1, R1> d, si::time<U2, R2> t)
|
|
|
|
|
{
|
|
|
|
|
return d / t;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
This function will work for every SI unit and representation without any
|
|
|
|
|
unnecessary overhead. It is also simple enough to prove its implementation
|
|
|
|
|
being correct just by a simple inspection. However, it might not always be
|
|
|
|
|
the case. For more complicated calculations we would like to ensure that we
|
|
|
|
|
are returning a physical quantity of a correct dimension. For this
|
|
|
|
|
dimension-specific concepts come handy again and with usage of C++20 generic
|
|
|
|
|
functions our function can look as simple as::
|
|
|
|
|
|
2020-05-10 17:31:47 +02:00
|
|
|
constexpr Speed auto avg_speed(Length auto d, Time auto t)
|
2020-03-09 18:55:41 +01:00
|
|
|
{
|
|
|
|
|
return d / t;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Now we are sure that the dimension of returned quantity is correct. Also
|
|
|
|
|
please note that with the above code we implemented a truly generic function
|
|
|
|
|
that works efficiently not only with SI units but also with other systems of
|
|
|
|
|
units like CGS.
|
|
|
|
|
|
|
|
|
|
.. seealso::
|
|
|
|
|
|
2021-02-16 16:19:57 +01:00
|
|
|
Please refer to :ref:`examples/avg_speed:avg_speed` example for more
|
|
|
|
|
information on different kinds of interfaces supported by the library.
|
2020-03-09 18:55:41 +01:00
|
|
|
|
|
|
|
|
|
2020-03-26 17:09:26 +01:00
|
|
|
Working With Constrained Deduced Quantity Types
|
2020-03-09 18:55:41 +01:00
|
|
|
-----------------------------------------------
|
|
|
|
|
|
|
|
|
|
It is important to note that when we assign a result from the function to an
|
|
|
|
|
automatically deduced type, even if it is constrained by a dimension-specific
|
|
|
|
|
concept, we still do not know what is the exact unit and representation type
|
|
|
|
|
of such a quantity. In many cases it might be exactly what we want to get,
|
|
|
|
|
but often we would like to know a specific type too. We have two options here:
|
|
|
|
|
|
|
|
|
|
- query the actual dimension, unit, and representation types::
|
|
|
|
|
|
2020-09-09 19:20:35 +02:00
|
|
|
constexpr Speed auto v = avg_speed(220_q_km, 2_q_h);
|
2020-03-09 18:55:41 +01:00
|
|
|
using quantity_type = decltype(v);
|
|
|
|
|
using dimension_type = quantity_type::dimension;
|
|
|
|
|
using unit_type = quantity_type::unit;
|
|
|
|
|
using rep_type = quantity_type::rep;
|
|
|
|
|
|
|
|
|
|
- convert or cast to a desired quantity type::
|
|
|
|
|
|
2020-09-09 19:20:35 +02:00
|
|
|
constexpr Speed auto v1 = avg_speed(220._q_km, 2_q_h);
|
2020-05-10 17:31:47 +02:00
|
|
|
constexpr si::speed<si::metre_per_second> v2 = v1;
|
|
|
|
|
constexpr Speed auto v3 = quantity_cast<si::speed<si::metre_per_second>(v1);
|
2020-03-09 18:55:41 +01:00
|
|
|
|
|
|
|
|
.. seealso::
|
|
|
|
|
|
2021-02-16 16:19:57 +01:00
|
|
|
More information on this subject can be found in the
|
|
|
|
|
:ref:`framework/conversions_and_casting:Conversions and Casting` chapter.
|
2020-09-08 17:13:38 +02:00
|
|
|
|
|
|
|
|
|
|
|
|
|
Dimensionless Quantities
|
|
|
|
|
------------------------
|
|
|
|
|
|
|
|
|
|
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`::
|
|
|
|
|
|
2020-09-09 19:20:35 +02:00
|
|
|
static_assert(10_q_km / 5_q_km == 2);
|
|
|
|
|
static_assert(std::is_same_v<decltype(10_q_km / 5_q_km), quantity<dim_one, one, std::int64_t>>);
|
2020-09-08 17:13:38 +02:00
|
|
|
|
|
|
|
|
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
|
|
|
|
|
are zero".
|
|
|
|
|
|
|
|
|
|
.. seealso::
|
|
|
|
|
|
|
|
|
|
Reasoning for the above design is provided in
|
2021-02-16 16:19:57 +01:00
|
|
|
:ref:`faq:Why a dimensionless quantity is not just an fundamental arithmetic type?`
|
2020-09-08 17:13:38 +02:00
|
|
|
|
|
|
|
|
To simplify the usage of the dimensionless quantity a following concept and alias template
|
|
|
|
|
are provided::
|
|
|
|
|
|
|
|
|
|
template<typename T>
|
|
|
|
|
concept Dimensionless = QuantityOf<T, dim_one>;
|
|
|
|
|
|
2020-10-06 18:17:52 +02:00
|
|
|
template<Unit U, QuantityValue Rep = double>
|
2020-09-08 17:13:38 +02:00
|
|
|
using dimensionless = quantity<dim_one, U, Rep>;
|
|
|
|
|
|
|
|
|
|
There are two special units provided for usage with such a quantity:
|
|
|
|
|
|
2020-09-14 08:45:36 +02:00
|
|
|
- `one` which is the :term:`coherent derived unit` of dimensionless quantity and does not
|
2020-09-08 17:13:38 +02:00
|
|
|
provide any textual symbol (according to the ISO definition "the measurement units and
|
|
|
|
|
values of quantities of dimension one are numbers"),
|
2020-09-09 11:20:55 +02:00
|
|
|
- `percent` which has the symbol ``%`` and ``ratio(1, 100)`` of the `one` unit.
|
2020-09-08 17:13:38 +02:00
|
|
|
|
|
|
|
|
For example the following code::
|
|
|
|
|
|
2020-09-09 19:20:35 +02:00
|
|
|
std::cout << quantity_cast<percent>(50._q_m / 100._q_m) << '\n';
|
2020-09-08 17:13:38 +02:00
|
|
|
|
|
|
|
|
will print ``50 %`` to the console output.
|
|
|
|
|
|
|
|
|
|
Again, according to the ISO definition "such quantities convey more information than a
|
|
|
|
|
number". This is exactly what we observe in the above example. The value stored inside
|
2021-03-19 06:47:37 +01:00
|
|
|
the quantity, the text output, and the value returned by the `quantity::number()` member
|
2020-09-08 17:13:38 +02:00
|
|
|
function is ``50`` rather than ``0.5``. It means that dimensionless quantities behave
|
|
|
|
|
like all other quantities and store the value in terms of a ratio of a coherent unit.
|
|
|
|
|
This allows us to not loose precision when we divide quantities of the same dimensions
|
|
|
|
|
but with units having vastly different ratios, e.g.
|
|
|
|
|
`Dimensionless Hubble parameter <https://en.wikipedia.org/wiki/Hubble%27s_law#Dimensionless_Hubble_parameter>`_
|
|
|
|
|
is expressed as a ratio of kilometers and megaparsecs.
|
|
|
|
|
|
|
|
|
|
.. seealso::
|
|
|
|
|
|
2021-02-16 16:19:57 +01:00
|
|
|
More information on dimensionless quantities can be found in the
|
|
|
|
|
:ref:`framework/conversions_and_casting:Implicit conversions of dimensionless quantities`
|
|
|
|
|
chapter.
|