forked from mpusz/mp-units
feat: full-on dimensional analysis between related quantity kinds
This commit is contained in:
committed by
Mateusz Pusz
parent
dad9b4f166
commit
017183653d
@@ -49,6 +49,7 @@ set(unitsSphinxDocs
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/design/directories.rst"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/design/downcasting.rst"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/design/quantity.rst"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/design/quantity_kind.rst"
|
||||
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/examples.rst"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/examples/avg_speed.rst"
|
||||
|
||||
@@ -0,0 +1,52 @@
|
||||
.. namespace:: units
|
||||
|
||||
quantity_kind
|
||||
=============
|
||||
|
||||
The ``quantity_kind`` class template provides a similar interface to ``quantity``.
|
||||
|
||||
Kinds
|
||||
-----
|
||||
|
||||
The first template parameter of ``quantity_kind`` is a ``Kind``.
|
||||
|
||||
``Kind``s, by themselves:
|
||||
|
||||
* Wrap a ``Dimension``, and
|
||||
* opt into the downcasting facility.
|
||||
|
||||
If a dimensional analysis operator on a quantity of kind *A*
|
||||
can result on a quantity of kind *B*,
|
||||
*A* and *B* are *related*.
|
||||
|
||||
The library provides two ``Kind`` bases, ``kind`` and ``derived_kind``.
|
||||
|
||||
``kind`` is an entry point, and there's only one per set of related kinds.
|
||||
|
||||
``derived_kind`` is used to explicitly name other related kinds.
|
||||
Unnamed, they look like ``detail::_kind_base<the-entry-kind, some_dimension>``.
|
||||
|
||||
Unnamed kinds, like unnamed units and dimensions,
|
||||
allows (intermediate) results in formulas without having to name them.
|
||||
|
||||
Quantity kinds
|
||||
--------------
|
||||
|
||||
``quantity_kind`` wraps a ``quantity`` and layers over its dimensional analysis.
|
||||
While all properties of the ``quantity`` apply transparently,
|
||||
results are always ``quantity_kind``s related to the kind(s) of the argument(s).
|
||||
|
||||
One of the arguments to the dimensional analysis operators can also be ``Quantity``.
|
||||
|
||||
The way back to ``quantity`` is through the ``.common()`` observer.
|
||||
|
||||
Intra-kind operations
|
||||
---------------------
|
||||
|
||||
``quantity_kind`` takes care of operators between related quantity kinds.
|
||||
Intra-kind operations can be opted into as follows::
|
||||
|
||||
struct width : kind<width, dim_length> {};
|
||||
struct height : kind<height, dim_length> {};
|
||||
|
||||
size2d operator+(QuantityKindOf<width> auto, QuantityKindOf<height> auto);
|
||||
@@ -67,23 +67,40 @@ dimension, than we will end up with just a dimensionless quantity:
|
||||
Quantity Kinds
|
||||
++++++++++++++
|
||||
|
||||
Quantity kinds behave the same as quantities for addition and subtraction.
|
||||
The same behavior is also provided for multiplication with, and division by
|
||||
a :term:`scalable number`.
|
||||
|
||||
Multiplication and division with a quantity (but not a quantity kind) is allowed.
|
||||
The result is a quantity kind with the appropriate dimension
|
||||
and related to the original quantity kind:
|
||||
Quantity kinds behave the same as quantities for all operations,
|
||||
except that the quantity types in the operators' declarations
|
||||
are quantity kind types instead.
|
||||
Additionally, for the dimensional analysis operators,
|
||||
you can use a quantity argument instead of a quantity kind.
|
||||
|
||||
.. code-block::
|
||||
:emphasize-lines: 5-6
|
||||
:emphasize-lines: 8-9
|
||||
|
||||
struct height : kind<height, dim_length> {};
|
||||
struct rate_of_climb : derived_kind<rate_of_climb, height, dim_speed> {};
|
||||
struct height_kind : kind<height_kind, dim_length> {};
|
||||
struct rate_of_climb_kind : derived_kind<rate_of_climb_kind, height_kind, dim_speed> {};
|
||||
|
||||
quantity_kind h(height{}, 100 * m);
|
||||
quantity_point_kind rate = h / (25 * s);
|
||||
// quantity_point_kind<rate_of_climb, si::metre_per_second, int>(4 * m / s)
|
||||
template <Unit U, QuantityValue Rep = double> using height = quantity_kind<height_kind, U, Rep>;
|
||||
template <Unit U, QuantityValue Rep = double> using rate_of_climb = quantity_kind<rate_of_climb_kind, U, Rep>;
|
||||
|
||||
height h{100 * m};
|
||||
rate_of_climb rate = h / (25 * s);
|
||||
// quantity_kind<rate_of_climb_kind, si::metre_per_second, int>(4 * m / s)
|
||||
|
||||
.. code-block::
|
||||
:emphasize-lines: 8-12
|
||||
|
||||
struct width_kind : kind<width_kind, dim_length> {};
|
||||
struct horizontal_area_kind : derived_kind<horizontal_area_kind, width_kind, dim_area> {};
|
||||
|
||||
template <Unit U, QuantityValue Rep = double> using width = quantity_kind<width_kind, U, Rep>;
|
||||
template <Unit U, QuantityValue Rep = double> using horizontal_area = quantity_kind<horizontal_area_kind, U, Rep>;
|
||||
|
||||
width w{5 * m};
|
||||
horizontal_area area1 = w * w;
|
||||
// quantity_kind<horizontal_area_kind, si::metre_per_second, int>(25 * m * m)
|
||||
width w2 = area1 / w; // quantity_kind<width_kind, si::metre, int>(5 * m)
|
||||
auto q1 = w / w; // Dimensionless quantity kinds related to width
|
||||
auto q2 = w / (5 * m); // with .common() equal to quantity{1}
|
||||
|
||||
Quantity Points
|
||||
+++++++++++++++
|
||||
|
||||
@@ -41,7 +41,7 @@ the value to the `quantity_kind` class template constructor::
|
||||
Differences To Quantity
|
||||
-----------------------
|
||||
|
||||
Unlike `quantity`, the library provides:
|
||||
The library provides:
|
||||
|
||||
- no kinds, such as ``radius`` or ``width``, therefore
|
||||
|
||||
@@ -49,7 +49,7 @@ Unlike `quantity`, the library provides:
|
||||
* no kind-specific concepts, such as ``Radius``,
|
||||
(there's the generic `QuantityKind` and kind-specifiable `QuantityKindOf`),
|
||||
|
||||
- a slightly different set of operations on quantity kinds
|
||||
- a slightly larger set of operations on quantity kinds
|
||||
(see the :ref:`framework/dimensions:Quantity Kinds` chapter).
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user