feat: quantity_kind and quantity_point_kind

This commit is contained in:
Johel Ernesto Guerrero Peña authored and Mateusz Pusz committed 2021-02-15 19:31:08 +01:00
1 parent 384f4b2624
commit 6bf09aa646
32 files changed
+2757 -202

No files matched your search

+25 -1
View File
@@ -4,7 +4,7 @@ Basic Concepts
==============
The most important concepts in the library are `Unit`, `Dimension`,
`Quantity`, and `QuantityPoint`:
`Quantity`, `QuantityPoint`, `QuantityKind`, and `QuantityPointKind`:
.. image:: /_static/img/concepts.png
:align: center
@@ -18,15 +18,35 @@ The most important concepts in the library are `Unit`, `Dimension`,
[exponent<Dimension, Num, Den>]<-[derived_dimension<Child, Unit, Exponent...>]
]
[<abstract>Quantity|
[quantity<Dimension, Unit, Rep>]
]
[<abstract>QuantityPoint|
[quantity_point<Dimension, Unit, Rep>]
]
[<abstract>QuantityKind|
[quantity_kind<Kind, Unit, Rep>]
]
[<abstract>QuantityPointKind|
[quantity_point_kind<PointKind, Unit, Rep>]
]
[<abstract>Unit]<-[Dimension]
[Dimension]<-[Quantity]
[Unit]<-[Quantity]
[Quantity]<-[QuantityPoint]
[<abstract>Kind]<-[QuantityKind]
[Dimension]<-[Kind]
[Quantity]<-[QuantityKind]
[<abstract>PointKind]<-[QuantityPointKind]
[Kind]<-[PointKind]
[QuantityKind]-<[QuantityPointKind]
`Unit` is a basic building block of the library. Every dimension works with
a concrete hierarchy of units. Such hierarchy defines a reference unit and
often a few scaled versions of it.
@@ -40,3 +60,7 @@ derived dimensions.
specific representation.
`QuantityPoint` is an absolute `Quantity` with respect to some origin.
`QuantityKind` is a `Quantity` with more specific usage.
`QuantityPointKind` is an absolute `QuantityKind` with respect to some origin.
+12 -4
View File
@@ -56,7 +56,8 @@ Explicit
--------
Explicit conversions are available with
the `quantity_cast` and `quantity_point_cast` function templates.
the `quantity_cast`, `quantity_point_cast`,
`quantity_kind_cast`, and `quantity_point_kind_cast` function templates.
They are especially useful to force a truncating conversion across quantities of the same
dimension for integral representation types and ratios that may cause precision loss::
@@ -99,6 +100,13 @@ or a specific target `quantity_point`::
std::cout << "Point: " << quantity_point_cast<decltype(quantity_point{0_q_m})>(d) << '\n';
For a single explicit template argument,
`quantity_point_kind_cast` is a superset of `quantity_kind_cast`,
which is also a superset of `quantity_cast`.
For the (dimension, unit) pair of explicit arguments case of `quantity_cast`,
`quantity_point_kind_cast` and `quantity_kind_cast`
accept a `PointKind` and `Kind` instead of a `Dimension`, respectively.
.. seealso::
For more information on conversion and casting and on how to extend the above "integral"
@@ -115,14 +123,14 @@ represent numbers it would be highly uncomfortable to every time type::
const auto d1 = 10_q_km;
const auto d2 = 3_q_km;
if(d1 / d2 > dimensionless<one, 2>) {
if(d1 / d2 > dimensionless<one>(2)) {
// ...
}
or::
const auto fill_time_left = (box.height / box.fill_level(measured_mass) -
dimensionless<one, 1>) * fill_time;
dimensionless<one>(1)) * fill_time;
This is why it was decided to allow the ``dimensionless<one>`` quantity of any
representation type to be implicitly constructible from this representation type.
@@ -147,7 +155,7 @@ could be ambiguous. For example::
return d1 / d2 + 1;
}
As long as we can reason about what such code means for ``foo(10_q_km, 2_q_km)`` it is not that obvious
As long as we can reason about what such code means for ``foo(10_q_km, 2_q_km)`` it is not that obvious
at all in the case of ``foo(10_q_cm, 2_q_ft)``. To make such code to compile for every case we have to
either change the type of the resulting unit to the one having ``ratio(1)`` (:term:`coherent derived unit`)::
+22 -4
View File
@@ -50,7 +50,7 @@ probably will always end up in a quantity of a yet another dimension:
However, please note that there is an exception from the above rule.
In case we divide the same dimensions, or multiply by the inverted
dimension, than we will end up with just a scalable number type:
dimension, than we will end up with just a dimensionless quantity:
.. code-block::
:emphasize-lines: 4-5
@@ -58,8 +58,23 @@ dimension, than we will end up with just a scalable number type:
Time auto dur1 = 10_q_s;
Time auto dur2 = 2_q_s;
Frequency auto fr1 = 5_q_Hz;
QuantityValue auto v1 = dur1 / dur2; // 5
QuantityValue auto v2 = dur1 * fr1; // 50
Dimensionless auto v1 = dur1 / dur2; // quantity(5)
Dimensionless auto v2 = dur1 * fr1; // quantity(50)
Quantity kinds behave the same as quantities for addition, substraction, and
multiplication with, and division by a :term:`scalable number`.
Multiplication and divison with a quantity
(but not a quantity kind) is allowed.
The result is a quantity kind with the appropiate dimension
and related to the original quantity kind.
struct height : kind<height, dim_length> {};
struct rate_of_climb : derived_kind<rate_of_climb, height, 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)`
Quantity points have a more restricted set of operations.
Quantity points can't be added together,
@@ -81,7 +96,7 @@ The result will always be a quantity point of the same dimension:
.. code-block::
:emphasize-lines: 3
Length auto dist1 = 2_q_m;
Length auto dist2 = 1_q_m;
auto res1 = dist1 - quantity_point{dist2}; // ERROR
@@ -98,6 +113,9 @@ The result is a relative quantity of the same dimension:
That's it! You can't multiply nor divide quantity points with anything else.
The same restrictions of a quantity point with respect to its quantity
apply to a quantity point kind with respect to its quantity kind.
Base Dimensions
---------------
+72
View File
@@ -0,0 +1,72 @@
.. namespace:: units
Quantity Kinds
==============
A quantity kind is a quantity of more specific usage.
It is represented in the library with a `quantity_kind` class template.
.. _quantity-point-construction:
Kind creation
-------------
We need a `kind` to represent the more specific usage of a quantity.
struct radius : kind<radius, si::dim_length> {};
Quantities of kind `radius` represent a radius.
They are clearly distinct from more generic usages of length quantities.
Construction
------------
To create the quantity kind object from a `quantity` we just have to pass
the value to the `quantity_kind` class template constructor::
quantity_kind<radius, si::kilometre, double> d(123 * km);
.. note::
As the constructor without the kind argument is explicit,
the quantity object can be created from a quantity 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_kind<radius, si::kilometre, double> d = 123 * km; // ERROR
Differences to quantity
-----------------------
Unlike `quantity`, the library provides:
- no kinds, such as ``radius`` or ``width``, therefore
* no UDLs or unit constants,
* 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
(see the :ref:`Dimensions` chapter)
Quantity point kind
-------------------
A quantity point kind is the analogous of a quantity point for quantity kinds.
(see the :ref:`Quantity Points` chapter).
They are represented in the library with a `quantity_point_kind` class template.
First, we need a `point_kind` for a `kind`.
struct width : kind<width, si::dim_length> {};
struct x_coordinate : point_kind<x_coordinate, width> {};
Now x coordinates can be constructed:
quantity_point_kind<x_coordinate, si::metre, int> auto x_pos(123 * m);
// `QuantityPointKindOf<x_coordinate>` with `x_pos.relative()`
// equal to `quantity_kind<width, si::metre, int>(123 * m)`
+1 -1
View File
@@ -40,4 +40,4 @@ Unlike `quantity`, the library provides:
- no dimension-specific concepts, such as ``LengthPoint``
(there's the dimension-agnostic `QuantityPoint`),
- a more limited set of operations on quantity points
(see the :ref:`Conversions and Casting` chapter)
(see the :ref:`Dimensions` chapter)
+3 -2
View File
@@ -8,13 +8,14 @@ also tries really hard to print any quantity in the most user friendly way.
.. note::
The library provides no text output for quantity points.
The library provides no text output for
quantity points or quantity (point) kinds.
Output Streams
--------------
.. tip::
The streaming support is provided via the ``<units/quantity_io.h>`` header
file.