mirror of
https://github.com/mpusz/mp-units.git
synced 2025-07-29 18:07:16 +02:00
docs: "Design Overview" chapter added and "Concepts" chapter reworked
This commit is contained in:
@ -98,7 +98,7 @@ to form a quantity.
|
||||
|
||||
The same applies to the `quantity_point` construction. To prevent similar issues during
|
||||
construction, it always needs to get both a `quantity` and
|
||||
a [`PointOrigin`](../users_guide/framework_basics/basic_concepts.md#PointOrigin) that we use
|
||||
a [`PointOrigin`](../users_guide/framework_basics/concepts.md#PointOrigin) that we use
|
||||
as a reference point.
|
||||
|
||||
|
||||
@ -156,7 +156,7 @@ code.
|
||||
!!! note
|
||||
|
||||
In case you have a good idea of how to rename
|
||||
[existing concepts](../users_guide/framework_basics/basic_concepts.md) to the `standard_case`,
|
||||
[existing concepts](../users_guide/framework_basics/concepts.md) to the `standard_case`,
|
||||
please let us know in the associated [GitHub Issue](https://github.com/mpusz/mp-units/issues/93).
|
||||
|
||||
|
||||
|
@ -31,7 +31,7 @@ errors and debugging as easy and user-friendly as possible.
|
||||
|
||||
To achieve this goal, several techniques are applied:
|
||||
|
||||
- [usage of C++20 concepts](../users_guide/framework_basics/basic_concepts.md) that improve
|
||||
- [usage of C++20 concepts](../users_guide/framework_basics/concepts.md) that improve
|
||||
compile-times and the readability of error messages when compared to the traditional template
|
||||
metaprogramming with [SFINAE](https://en.cppreference.com/w/cpp/language/sfinae),
|
||||
- [usage of strong types for framework entities](../users_guide/framework_basics/interface_introduction.md#strong-types-instead-of-aliases) (instead of type aliases),
|
||||
|
@ -152,7 +152,7 @@ template<Reference auto R,
|
||||
class quantity;
|
||||
```
|
||||
|
||||
The second template parameter is constrained with a [`RepresentationOf`](basic_concepts.md#RepresentationOf)
|
||||
The second template parameter is constrained with a [`RepresentationOf`](concepts.md#RepresentationOf)
|
||||
concept that checks if the provided representation type satisfies the requirements for the character
|
||||
associated with this quantity type.
|
||||
|
||||
|
@ -1,30 +1,6 @@
|
||||
# Basic Concepts
|
||||
# Concepts
|
||||
|
||||
The most important concepts in the **mp-units** library are [`Dimension`](#Dimension),
|
||||
[`QuantitySpec`](#QuantitySpec), [`Unit`](#Unit), [`Reference`](#Reference),
|
||||
[`Representation`](#Representation), [`Quantity`](#Quantity), and [`QuantityPoint`](#QuantityPoint).
|
||||
|
||||
The tree provided below presents how those and a few other concepts depend on each other:
|
||||
|
||||
```mermaid
|
||||
flowchart TD
|
||||
Dimension --- QuantitySpec
|
||||
QuantitySpec --- Reference
|
||||
Unit --- Reference
|
||||
Reference --- Quantity
|
||||
Representation --- Quantity
|
||||
Quantity --- QuantityPoint
|
||||
PointOrigin --- QuantityPoint
|
||||
|
||||
click Dimension "#Dimension"
|
||||
click QuantitySpec "#QuantitySpec"
|
||||
click Unit "#Unit"
|
||||
click Reference "#Reference"
|
||||
click Representation "#Representation"
|
||||
click Quantity "#Quantity"
|
||||
click PointOrigin "#PointOrigin"
|
||||
click QuantityPoint "#QuantityPoint"
|
||||
```
|
||||
This chapter enumerates all the user-facing concepts in the **mp-units** library.
|
||||
|
||||
|
||||
## `Dimension<T>` { #Dimension }
|
||||
@ -40,31 +16,6 @@ or derived [quantity](../../appendix/glossary.md#quantity):
|
||||
by the library's framework based on the [quantity equation](../../appendix/glossary.md#quantity-equation)
|
||||
provided in the [quantity specification](../../appendix/glossary.md#quantity_spec).
|
||||
|
||||
??? abstract "Examples"
|
||||
|
||||
`isq::dim_length`, `isq::dim_mass`, `isq::dim_time`, `isq::dim_electric_current`,
|
||||
`isq::dim_thermodynamic_temperature`, `isq::dim_amount_of_substance`, and
|
||||
`isq::dim_luminous_intensity` are the dimensions of base quantities in the
|
||||
[ISQ](../../appendix/glossary.md#isq).
|
||||
|
||||
The implementation of IEC 80000 in this library provides `iec80000::dim_traffic_intensity`
|
||||
base dimension to extend ISQ with information technology quantities.
|
||||
|
||||
A `Dimension` can be defined by the user in the following way:
|
||||
|
||||
```cpp
|
||||
inline constexpr struct dim_length : base_dimension<"L"> {} dim_length;
|
||||
```
|
||||
|
||||
The division on quantity specifications also divides their dimensions:
|
||||
|
||||
```cpp
|
||||
static_assert((isq::length / isq::time).dimension == isq::dim_length / isq::dim_time);
|
||||
```
|
||||
|
||||
The [dimension equation](../../appendix/glossary.md#dimension-equation) of `isq::dim_length / isq::dim_time`
|
||||
results in the `derived_dimension<isq::dim_length, per<isq::dim_time>>` type.
|
||||
|
||||
|
||||
### `DimensionOf<T, V>` { #DimensionOf }
|
||||
|
||||
@ -91,49 +42,6 @@ including:
|
||||
- Intermediate [derived quantity](../../appendix/glossary.md#derived-quantity) specifications being
|
||||
a result of a [quantity equations](../../appendix/glossary.md#quantity-equation) on other specifications.
|
||||
|
||||
??? abstract "Examples"
|
||||
|
||||
`isq::length`, `isq::mass`, `isq::time`, `isq::electric_current`, `isq::thermodynamic_temperature`,
|
||||
`isq::amount_of_substance`, and `isq::luminous_intensity` are the specifications of base quantities
|
||||
in the [ISQ](../../appendix/glossary.md#isq).
|
||||
|
||||
`isq::width`, `isq::height`, `isq::radius`, and `isq::position_vector` are only a few of many
|
||||
quantities of a kind length specified in the [ISQ](../../appendix/glossary.md#isq).
|
||||
|
||||
`kind_of<isq::length>` behaves as any of the quantities of a kind length.
|
||||
|
||||
`isq::area`, `isq::speed`, `isq::moment_of_force` are only a few of many derived quantities provided
|
||||
in the [ISQ](../../appendix/glossary.md#isq).
|
||||
|
||||
`QuantitySpec` can be defined by the user in one of the following ways:
|
||||
|
||||
=== "C++23"
|
||||
|
||||
```cpp
|
||||
inline constexpr struct length : quantity_spec<dim_length> {} length;
|
||||
inline constexpr struct height : quantity_spec<length> {} height;
|
||||
inline constexpr struct speed : quantity_spec<length / time> {} speed;
|
||||
```
|
||||
|
||||
=== "C++20"
|
||||
|
||||
```cpp
|
||||
inline constexpr struct length : quantity_spec<length, dim_length> {} length;
|
||||
inline constexpr struct height : quantity_spec<height, length> {} height;
|
||||
inline constexpr struct speed : quantity_spec<speed, length / time> {} speed;
|
||||
```
|
||||
|
||||
=== "Portable"
|
||||
|
||||
```cpp
|
||||
QUANTITY_SPEC(length, dim_length);
|
||||
QUANTITY_SPEC(height, length);
|
||||
QUANTITY_SPEC(speed, length / time);
|
||||
```
|
||||
|
||||
The [quantity equation](../../appendix/glossary.md#quantity-equation) of `isq::length / isq::time` results
|
||||
in the `derived_quantity_spec<isq::length, per<isq::time>>` type.
|
||||
|
||||
|
||||
### `QuantitySpecOf<T, V>` { #QuantitySpecOf }
|
||||
|
||||
@ -159,7 +67,7 @@ and when `T` is implicitly convertible to `V`.
|
||||
```
|
||||
|
||||
|
||||
## `Unit<T> ` { #Unit }
|
||||
## `Unit<T>` { #Unit }
|
||||
|
||||
`Unit` concept matches all the [units](../../appendix/glossary.md#unit) in the library including:
|
||||
|
||||
@ -180,38 +88,6 @@ and when `T` is implicitly convertible to `V`.
|
||||
|
||||
In the **mp-units** library, [physical constants are also implemented as units](faster_than_lightspeed_constants.md).
|
||||
|
||||
??? abstract "Examples"
|
||||
|
||||
`si::second`, `si::metre`, `si::kilogram`, `si::ampere`, `si::kelvin`, `si::mole`, and `si::candela`
|
||||
are the base units of [SI](../../appendix/glossary.md#si).
|
||||
|
||||
`si::kilo<si::metre>` is a prefixed unit of length.
|
||||
|
||||
`si::radian`, `si::newton`, and `si::watt` are examples of named derived units within
|
||||
[SI](../../appendix/glossary.md#si).
|
||||
|
||||
`non_si::minute` is an example of a scaled unit of time.
|
||||
|
||||
`si::si2019::speed_of_light_in_vacuum` is a physical constant standardized by the SI in 2019.
|
||||
|
||||
`Unit` can be defined by the user in one of the following ways:
|
||||
|
||||
```cpp
|
||||
template<PrefixableUnit auto U> struct kilo_ : prefixed_unit<"k", mag_power<10, 3>, U> {};
|
||||
template<PrefixableUnit auto U> inline constexpr kilo_<U> kilo;
|
||||
|
||||
inline constexpr struct second : named_unit<"s", kind_of<isq::time>> {} second;
|
||||
inline constexpr struct gram : named_unit<"g", kind_of<isq::mass>> {} gram;
|
||||
inline constexpr struct minute : named_unit<"min", mag<60> * second> {} minute;
|
||||
inline constexpr struct kilogram : decltype(kilo<gram>) {} kilogram;
|
||||
inline constexpr struct newton : named_unit<"N", kilogram * metre / square(second)> {} newton;
|
||||
|
||||
inline constexpr struct speed_of_light_in_vacuum : named_unit<"c", mag<299'792'458> * metre / second> {} speed_of_light_in_vacuum;
|
||||
```
|
||||
|
||||
The [unit equation](../../appendix/glossary.md#unit-equation) of `si::metre / si::second` results
|
||||
in the `derived_unit<si::metre, per<si::second>>` type.
|
||||
|
||||
|
||||
### `AssociatedUnit<T>` { #AssociatedUnit }
|
||||
|
||||
@ -219,8 +95,8 @@ and when `T` is implicitly convertible to `V`.
|
||||
and is satisfied by:
|
||||
|
||||
- All units derived from a `named_unit` class template instantiated with a unique symbol identifier
|
||||
and a [`QuantitySpec`](#quantityspec).
|
||||
- All units being a result of a [unit equations](../../appendix/glossary.md#unit-equation) on other
|
||||
and a [`QuantitySpec`](#quantityspec) of a [quantity kind](../../appendix/glossary.md#kind).
|
||||
- All units being a result of [unit equations](../../appendix/glossary.md#unit-equation) on other
|
||||
associated units.
|
||||
|
||||
??? abstract "Examples"
|
||||
@ -230,7 +106,7 @@ and is satisfied by:
|
||||
|
||||
Natural units typically do not have an associated quantity. For example, if we assume `c = 1`,
|
||||
a `natural::second` unit can be used to measure both `time` and `length`. In such case, `speed`
|
||||
would be a [dimensionless quantity](../../appendix/glossary.md#dimensionless-quantity).
|
||||
would have a unit of `one`.
|
||||
|
||||
|
||||
### `PrefixableUnit<T>` { #PrefixableUnit }
|
||||
@ -286,14 +162,6 @@ A `Reference` can either be:
|
||||
- The instantiation of a `reference` class template with a [`QuantitySpec`](#QuantitySpec) passed as
|
||||
the first template argument and a [`Unit`](#Unit) passed as the second one.
|
||||
|
||||
??? abstract "Examples"
|
||||
|
||||
`si::metre` is defined in the [SI](../../appendix/glossary.md#si) as a unit of `isq::length`
|
||||
and thus can be used as a reference to instantiate a quantity of length.
|
||||
|
||||
The expression `isq::height[m]` results with `reference<isq::height, si::metre>` which can be used to
|
||||
instantiate a quantity of `isq::height` with a unit of `si::metre`.
|
||||
|
||||
|
||||
### `ReferenceOf<T, V>` { #ReferenceOf }
|
||||
|
||||
@ -324,7 +192,7 @@ with `true` for one or more of the following variable templates:
|
||||
- `is_tensor<T>`
|
||||
|
||||
|
||||
??? abstract "Examples"
|
||||
??? tip
|
||||
|
||||
If we want to use scalar types to also express [vector quantities](character_of_a_quantity.md#defining-vector-and-tensor-quantities)
|
||||
(e.g., ignoring the "direction" of the vector) the following definition can be provided to enable such a behavior:
|
||||
@ -341,13 +209,6 @@ with `true` for one or more of the following variable templates:
|
||||
`Quantity` concept matches every [quantity](../../appendix/glossary.md#quantity) in the library and is
|
||||
satisfied by all types being or deriving from an instantiation of a `quantity` class template.
|
||||
|
||||
??? abstract "Examples"
|
||||
|
||||
All of `42 * m`, `42 * si::metre`, `42 * isq::height[m]`, and `isq::height(42 * m)` create a quantity
|
||||
and thus satisfy a `Quantity` concept.
|
||||
|
||||
A quantity type can also be specified explicitly (e.g., `quantity<si::metre, int>`,
|
||||
`quantity<isq::height[m]>`).
|
||||
|
||||
### `QuantityOf<T, V>` { #QuantityOf }
|
||||
|
||||
@ -363,14 +224,6 @@ the library. It is satisfied by either:
|
||||
- All types derived from an `absolute_point_origin` class template.
|
||||
- All types derived from a `relative_point_origin` class template.
|
||||
|
||||
??? abstract "Examples"
|
||||
|
||||
The types of both definitions below satisfy a `PointOrigin` concept:
|
||||
|
||||
```cpp
|
||||
inline constexpr struct absolute_zero : absolute_point_origin<isq::thermodynamic_temperature> {} absolute_zero;
|
||||
inline constexpr struct ice_point : relative_point_origin<absolute_zero + 273.15 * kelvin> {} ice_point;
|
||||
```
|
||||
|
||||
### `PointOriginFor<T, V>` { #PointOriginFor }
|
||||
|
||||
@ -380,8 +233,8 @@ implicitly convertible from quantity specification `V`, which means that `V` mus
|
||||
|
||||
??? abstract "Examples"
|
||||
|
||||
`ice_point` can serve as a point origin for _points_ of `isq::Celsius_temperature` because this quantity
|
||||
type implicitly converts to `isq::thermodynamic_temperature`.
|
||||
`si::ice_point` can serve as a point origin for _points_ of `isq::Celsius_temperature` because this
|
||||
quantity type implicitly converts to `isq::thermodynamic_temperature`.
|
||||
|
||||
However, if we define `mean_sea_level` in the following way:
|
||||
|
||||
@ -401,15 +254,6 @@ implicitly convertible from quantity specification `V`, which means that `V` mus
|
||||
`QuantityPoint` concept is satisfied by all types being either a specialization or derived from `quantity_point`
|
||||
class template.
|
||||
|
||||
??? abstract "Examples"
|
||||
|
||||
The following specifies a quantity point defined in terms of an `ice_point` quantity point origin
|
||||
provided in the previous example:
|
||||
|
||||
```cpp
|
||||
constexpr auto room_reference_temperature = ice_point + isq::Celsius_temperature(21 * deg_C);
|
||||
```
|
||||
|
||||
|
||||
### `QuantityPointOf<T, V>` { #QuantityPointOf }
|
||||
|
||||
@ -428,10 +272,10 @@ for which an instantiation of `quantity_like_traits` type trait yields a valid t
|
||||
|
||||
- Static data member `reference` that matches the [`Reference`](#Reference) concept,
|
||||
- `rep` type that matches [`RepresentationOf`](#RepresentationOf) concept with the character provided
|
||||
in `reference`,
|
||||
in `reference`.
|
||||
- `to_numerical_value(T)` static member function returning a raw value of the quantity packed in
|
||||
either `convert_explicitly` or `convert_implicitly` wrapper that enables implicit conversion in
|
||||
the latter case,
|
||||
the latter case.
|
||||
- `from_numerical_value(rep)` static member function returning `T` packed in either `convert_explicitly`
|
||||
or `convert_implicitly` wrapper that enables implicit conversion in the latter case.
|
||||
|
||||
@ -467,13 +311,13 @@ for which an instantiation of `quantity_like_traits` type trait yields a valid t
|
||||
`QuantityPointLike` concept provides interoperability with other libraries and is satisfied by a type `T`
|
||||
for which an instantiation of `quantity_point_like_traits` type trait yields a valid type that provides:
|
||||
|
||||
- Static data member `reference` that matches the [`Reference`](#Reference) concept
|
||||
- Static data member `point_origin` that matches the [`PointOrigin`](#PointOrigin) concept
|
||||
- Static data member `reference` that matches the [`Reference`](#Reference) concept.
|
||||
- Static data member `point_origin` that matches the [`PointOrigin`](#PointOrigin) concept.
|
||||
- `rep` type that matches [`RepresentationOf`](#RepresentationOf) concept with the character provided
|
||||
in `reference`
|
||||
in `reference`.
|
||||
- `to_quantity(T)` static member function returning the `quantity` being the offset of the point
|
||||
from the origin packed in either `convert_explicitly` or `convert_implicitly` wrapper that enables
|
||||
implicit conversion in the latter case,
|
||||
implicit conversion in the latter case.
|
||||
- `from_quantity(quantity<reference, rep>)` static member function returning `T` packed in either
|
||||
`convert_explicitly` or `convert_implicitly` wrapper that enables implicit conversion in the latter
|
||||
case.
|
382
docs/users_guide/framework_basics/design_overview.md
Normal file
382
docs/users_guide/framework_basics/design_overview.md
Normal file
@ -0,0 +1,382 @@
|
||||
# Design Overview
|
||||
|
||||
The most important entities in the **mp-units** library are:
|
||||
|
||||
- [quantity](#quantity),
|
||||
- [quantity point](#quantity-point),
|
||||
- [unit](#unit),
|
||||
- [dimension](#dimension),
|
||||
- [quantity specification](#quantity-specification)
|
||||
- [quantity reference](#quantity-reference),
|
||||
- [quantity representation](#quantity-representation).
|
||||
|
||||
The graph provided below presents how those and a few other entities depend on each other:
|
||||
|
||||
```mermaid
|
||||
flowchart TD
|
||||
Unit --- Reference
|
||||
Dimension --- QuantitySpec["Quantity specification"]
|
||||
quantity_character["Quantity character"] --- QuantitySpec
|
||||
QuantitySpec --- Reference["Quantity reference"]
|
||||
Reference --- Quantity
|
||||
quantity_character --- Representation
|
||||
Representation --- Quantity
|
||||
Quantity --- QuantityPoint["Quantity point"]
|
||||
PointOrigin["Point origin"] --- QuantityPoint
|
||||
|
||||
click Dimension "#dimension"
|
||||
click quantity_character "#quantity-character"
|
||||
click QuantitySpec "#quantity-specification"
|
||||
click Unit "#unit"
|
||||
click Reference "#quantity-reference"
|
||||
click Representation "#quantity-representation"
|
||||
click Quantity "#quantity"
|
||||
click PointOrigin "#point-origin"
|
||||
click QuantityPoint "#quantity-point"
|
||||
```
|
||||
|
||||
## Dimension
|
||||
|
||||
[Dimension](../../appendix/glossary.md#dimension) specifies the dependence of a quantity on the base
|
||||
quantities of a particular system of quantities. It is represented as a product of powers of factors
|
||||
corresponding to the base quantities, omitting any numerical factor.
|
||||
|
||||
In the **mp-units** library, we use the terms:
|
||||
|
||||
- **base dimension** to refer to the dimension of a [base quantity](../../appendix/glossary.md#base-quantity),
|
||||
- **derived dimension** to refer to the dimension of a [derived quantity](../../appendix/glossary.md#derived-quantity).
|
||||
|
||||
For example:
|
||||
|
||||
- _length_ ($\mathsf{L}$), _mass_ ($\mathsf{M}$), _time_ ($\mathsf{T}$), _electric current_ ($\mathsf{I}$),
|
||||
_thermodynamic temperature_ ($\mathsf{Θ}$), _amount of substance_ ($\mathsf{N}$), and
|
||||
_luminous intensity_ ($\mathsf{J}$) are the base dimensions of the [ISQ](../../appendix/glossary.md#isq).
|
||||
- A derived dimension of _force_ in the [ISQ](../../appendix/glossary.md#isq) is denoted by
|
||||
$\textsf{dim }F = \mathsf{LMT}^{–2}$.
|
||||
- The implementation of IEC 80000 in this library provides `iec80000::dim_traffic_intensity`
|
||||
base dimension to extend ISQ with strong information technology quantities.
|
||||
|
||||
[Base dimensions](../../appendix/glossary.md#base-dimension) can be defined by the user in
|
||||
the following way:
|
||||
|
||||
```cpp
|
||||
inline constexpr struct dim_length : base_dimension<"L"> {} dim_length;
|
||||
inline constexpr struct dim_time : base_dimension<"T"> {} dim_time;
|
||||
```
|
||||
|
||||
[Derived dimensions](../../appendix/glossary.md#derived-dimension) are implicitly created
|
||||
by the library's framework based on the [quantity equation](../../appendix/glossary.md#quantity-equation)
|
||||
provided in the [quantity specification](../../appendix/glossary.md#quantity_spec):
|
||||
|
||||
=== "C++23"
|
||||
|
||||
```cpp
|
||||
inline constexpr struct length : quantity_spec<dim_length> {} length;
|
||||
inline constexpr struct time : quantity_spec<dim_time> {} time;
|
||||
inline constexpr struct speed : quantity_spec<length / time> {} speed;
|
||||
|
||||
static_assert(speed.dimension == dim_length / dim_time);
|
||||
```
|
||||
|
||||
=== "C++20"
|
||||
|
||||
```cpp
|
||||
inline constexpr struct length : quantity_spec<length, dim_length> {} length;
|
||||
inline constexpr struct time : quantity_spec<time, dim_time> {} time;
|
||||
inline constexpr struct speed : quantity_spec<speed, length / time> {} speed;
|
||||
|
||||
static_assert(speed.dimension == dim_length / dim_time);
|
||||
```
|
||||
|
||||
=== "Portable"
|
||||
|
||||
```cpp
|
||||
QUANTITY_SPEC(length, dim_length);
|
||||
QUANTITY_SPEC(time, dim_time);
|
||||
QUANTITY_SPEC(speed, length / time);
|
||||
|
||||
static_assert(speed.dimension == dim_length / dim_time);
|
||||
```
|
||||
|
||||
|
||||
!!! important
|
||||
|
||||
Users should not explicitly define any derived dimensions. Those should always be implicitly
|
||||
created by the framework.
|
||||
|
||||
The multiplication/division on quantity specifications also multiplies/divides their dimensions:
|
||||
|
||||
```cpp
|
||||
static_assert((length / time).dimension == dim_length / dim_time);
|
||||
```
|
||||
|
||||
The [dimension equation](../../appendix/glossary.md#dimension-equation) of `isq::dim_length / isq::dim_time`
|
||||
results in the `derived_dimension<isq::dim_length, per<isq::dim_time>>` type.
|
||||
|
||||
|
||||
## Quantity character
|
||||
|
||||
[ISO 80000](../appendix/references.md#ISO80000) explicitly states that quantities (even of the same kind) may have
|
||||
different [characters](../../appendix/glossary.md#character):
|
||||
|
||||
- scalar,
|
||||
- vector,
|
||||
- tensor.
|
||||
|
||||
The quantity character in the **mp-units** library is implemented with the `quantity_character` enumeration:
|
||||
|
||||
```cpp
|
||||
enum class quantity_character { scalar, vector, tensor };
|
||||
```
|
||||
|
||||
!!! info
|
||||
|
||||
You can read more on quantity characters in the ["Character of a Quantity"](character_of_a_quantity.md)
|
||||
chapter.
|
||||
|
||||
|
||||
## Quantity specification
|
||||
|
||||
[Dimension is not enough to describe a quantity](systems_of_quantities.md#dimension-is-not-enough-to-describe-a-quantity).
|
||||
This is why the [ISO 80000](../appendix/references.md#ISO80000) provides hundreds of named quantity
|
||||
types. It turns out that there are many more quantity types in the [ISQ](../../appendix/glossary.md#isq)
|
||||
than the named units in the [SI](../../appendix/glossary.md#si).
|
||||
|
||||
This is why the **mp-units** library introduces a quantity specification entity that stores:
|
||||
|
||||
- [dimension](../../appendix/glossary.md#dimension),
|
||||
- quantity type/name,
|
||||
- [quantity character](../../appendix/glossary.md#character),
|
||||
- the [quantity equation](../../appendix/glossary.md#quantity-equation) being the recipe to create this quantity
|
||||
(only for derived quantities that specify such a recipe).
|
||||
|
||||
!!! note
|
||||
|
||||
We know that it might be sometimes confusing to talk about quantities, quantity types/names, and quantity
|
||||
specifications. However, it might be important to notice here that even the
|
||||
[ISO 80000](../appendix/references.md#ISO80000) admits that:
|
||||
|
||||
> It is customary to use the same term, "quantity", to refer to both general quantities, such as length,
|
||||
> mass, etc., and their instances, such as given lengths, given masses, etc. Accordingly, we are used to
|
||||
> saying both that length is a quantity and that a given length is a quantity by maintaining the specification
|
||||
> – "general quantity, $Q$" or "individual quantity, $Q_\textsf{a}$" – implicit and exploiting the linguistic
|
||||
> context to remove the ambiguity.
|
||||
|
||||
In the **mp-units** library, we have a:
|
||||
|
||||
- **quantity** - implemented as a `quantity` class template,
|
||||
- **quantity specification** - implemented with a `quantity_spec` class template that among others identifies
|
||||
a specific **quantity type/name**.
|
||||
|
||||
For example:
|
||||
|
||||
- `isq::length`, `isq::mass`, `isq::time`, `isq::electric_current`, `isq::thermodynamic_temperature`,
|
||||
`isq::amount_of_substance`, and `isq::luminous_intensity` are the specifications of base quantities
|
||||
in the [ISQ](../../appendix/glossary.md#isq).
|
||||
- `isq::width`, `isq::height`, `isq::radius`, and `isq::position_vector` are only a few of many
|
||||
quantities of a kind length specified in the [ISQ](../../appendix/glossary.md#isq).
|
||||
- `isq::area`, `isq::speed`, `isq::moment_of_force` are only a few of many derived quantities provided
|
||||
in the [ISQ](../../appendix/glossary.md#isq).
|
||||
|
||||
Quantity specification can be defined by the user in one of the following ways:
|
||||
|
||||
=== "C++23"
|
||||
|
||||
```cpp
|
||||
inline constexpr struct length : quantity_spec<dim_length> {} length;
|
||||
inline constexpr struct height : quantity_spec<length> {} height;
|
||||
inline constexpr struct speed : quantity_spec<length / time> {} speed;
|
||||
```
|
||||
|
||||
=== "C++20"
|
||||
|
||||
```cpp
|
||||
inline constexpr struct length : quantity_spec<length, dim_length> {} length;
|
||||
inline constexpr struct height : quantity_spec<height, length> {} height;
|
||||
inline constexpr struct speed : quantity_spec<speed, length / time> {} speed;
|
||||
```
|
||||
|
||||
=== "Portable"
|
||||
|
||||
```cpp
|
||||
QUANTITY_SPEC(length, dim_length);
|
||||
QUANTITY_SPEC(height, length);
|
||||
QUANTITY_SPEC(speed, length / time);
|
||||
```
|
||||
|
||||
The [quantity equation](../../appendix/glossary.md#quantity-equation) of `isq::length / isq::time` results
|
||||
in the `derived_quantity_spec<isq::length, per<isq::time>>` type.
|
||||
|
||||
|
||||
## Unit
|
||||
|
||||
A [unit](../../appendix/glossary.md#unit) is a concrete amount of a quantity that allows us to
|
||||
measure the values of [quantities of the same kind](systems_of_quantities.md#quantities-of-the-same-kind)
|
||||
and represent the result as a number being the ratio of the two quantities.
|
||||
|
||||
For example:
|
||||
|
||||
- `si::second`, `si::metre`, `si::kilogram`, `si::ampere`, `si::kelvin`, `si::mole`, and `si::candela`
|
||||
are the base units of the [SI](../../appendix/glossary.md#si).
|
||||
- `si::kilo<si::metre>` is a prefixed unit of length.
|
||||
- `si::radian`, `si::newton`, and `si::watt` are examples of named derived units within the
|
||||
[SI](../../appendix/glossary.md#si).
|
||||
- `non_si::minute` is an example of a scaled unit of time.
|
||||
- `si::si2019::speed_of_light_in_vacuum` is a physical constant standardized by the SI in 2019.
|
||||
|
||||
!!! note
|
||||
|
||||
In the **mp-units** library, [physical constants are also implemented as units](faster_than_lightspeed_constants.md).
|
||||
|
||||
A unit can be defined by the user in one of the following ways:
|
||||
|
||||
```cpp
|
||||
template<PrefixableUnit auto U> struct kilo_ : prefixed_unit<"k", mag_power<10, 3>, U> {};
|
||||
template<PrefixableUnit auto U> inline constexpr kilo_<U> kilo;
|
||||
|
||||
inline constexpr struct second : named_unit<"s", kind_of<isq::time>> {} second;
|
||||
inline constexpr struct minute : named_unit<"min", mag<60> * second> {} minute;
|
||||
inline constexpr struct gram : named_unit<"g", kind_of<isq::mass>> {} gram;
|
||||
inline constexpr struct kilogram : decltype(kilo<gram>) {} kilogram;
|
||||
inline constexpr struct newton : named_unit<"N", kilogram * metre / square(second)> {} newton;
|
||||
|
||||
inline constexpr struct speed_of_light_in_vacuum : named_unit<"c", mag<299'792'458> * metre / second> {} speed_of_light_in_vacuum;
|
||||
```
|
||||
|
||||
The [unit equation](../../appendix/glossary.md#unit-equation) of `si::metre / si::second` results
|
||||
in the `derived_unit<si::metre, per<si::second>>` type.
|
||||
|
||||
|
||||
## Quantity reference
|
||||
|
||||
ISO defines a quantity as:
|
||||
|
||||
!!! quote
|
||||
|
||||
property of a phenomenon, body, or substance, where the property has a magnitude
|
||||
that can be expressed as a number and a **_reference_**
|
||||
|
||||
After that, it says:
|
||||
|
||||
!!! quote
|
||||
|
||||
A reference can be a **_measurement unit_**, a measurement procedure, a reference material,
|
||||
or a combination of such.
|
||||
|
||||
In the **mp-units** library, a quantity reference provides all the domain-specific metadata for the quantity
|
||||
besides its [numerical value](../../appendix/glossary.md#numerical-value):
|
||||
|
||||
- all the data stored in the [quantity specification](#quantity-specification),
|
||||
- [unit](#unit).
|
||||
|
||||
Together with the value of a [representation type](#quantity-representation), it forms a quantity.
|
||||
|
||||
In the library, we have two different ways to provide a reference:
|
||||
|
||||
- every unit with the associated [quantity kind](systems_of_quantities.md#quantities-of-the-same-kind)
|
||||
is a valid reference,
|
||||
- providing a unit to an indexing operator of a quantity specification explicitly instantiates
|
||||
a `reference` class template with this quantity spec and a unit passed as arguments.
|
||||
|
||||
!!! note
|
||||
|
||||
All the units of the [SI](../../appendix/glossary.md#si) have associated quantity kinds
|
||||
and may serve as a reference.
|
||||
|
||||
For example:
|
||||
|
||||
- `si::metre` is defined in the [SI](../../appendix/glossary.md#si) as a unit of `isq::length`
|
||||
and thus can be used as a reference to instantiate a quantity of length (e.g., `42 * m`).
|
||||
- The expression `isq::height[m]` results with `reference<isq::height, si::metre>`, which can be used to
|
||||
instantiate a quantity of `isq::height` with a unit of `si::metre` (e.g., `42 * isq::height[m]`).
|
||||
|
||||
|
||||
## Quantity representation
|
||||
|
||||
Quantity representation defines the type used to store the
|
||||
[numerical value of a quantity](../../appendix/glossary.md#quantity-value). Such a type should be of
|
||||
a specific [quantity character](#quantity-character) provided in the
|
||||
[quantity specification](#quantity-specification).
|
||||
|
||||
!!! note
|
||||
|
||||
By default, all floating-point and integral (besides `bool`) types are treated as scalars.
|
||||
|
||||
|
||||
## Quantity
|
||||
|
||||
ISO defines a quantity as:
|
||||
|
||||
!!! quote
|
||||
|
||||
property of a phenomenon, body, or substance, where the property has a magnitude
|
||||
that can be expressed as a **_number_** and a **_reference_**
|
||||
|
||||
This is why a `quantity` class template is defined in the library as:
|
||||
|
||||
```cpp
|
||||
template<Reference auto R,
|
||||
RepresentationOf<get_quantity_spec(R).character> Rep = double>
|
||||
class quantity;
|
||||
```
|
||||
|
||||
Its value can be easily created by multiplying/dividing the [numerical value](#quantity-representation)
|
||||
and a [reference](#quantity-reference).
|
||||
|
||||
For example:
|
||||
|
||||
- All of `42 * m`, `42 * si::metre`, `42 * isq::height[m]`, and `isq::height(42 * m)` create a quantity.
|
||||
- A quantity type can also be specified explicitly (e.g., `quantity<si::metre, int>`,
|
||||
`quantity<isq::height[m]>`).
|
||||
|
||||
|
||||
## Point origin
|
||||
|
||||
In [the affine space theory](the_affine_space.md), the point origin specifies where the "zero" of our
|
||||
measurement's scale is.
|
||||
|
||||
In the **mp-units** library, we have two types of point origins:
|
||||
|
||||
- [absolute](the_affine_space.md#absolute-point-origin) - defines an absolute "zero" for our point,
|
||||
- [relative](the_affine_space.md#relative-point-origin) - defines an origin that has some "offset" relative
|
||||
to an absolute point.
|
||||
|
||||
For example:
|
||||
|
||||
- the absolute point origin can be defined in the following way:
|
||||
|
||||
```cpp
|
||||
inline constexpr struct absolute_zero : absolute_point_origin<isq::thermodynamic_temperature> {} absolute_zero;
|
||||
```
|
||||
|
||||
- the relative point origin can be defined in the following way:
|
||||
|
||||
```cpp
|
||||
inline constexpr struct ice_point : relative_point_origin<absolute_zero + 273.15 * kelvin> {} ice_point;
|
||||
```
|
||||
|
||||
|
||||
## Quantity point
|
||||
|
||||
Quantity point implements a _point_ in [the affine space theory](the_affine_space.md).
|
||||
|
||||
In the **mp-units** library, the quantity point is implemented as:
|
||||
|
||||
```cpp
|
||||
template<Reference auto R,
|
||||
PointOriginFor<get_quantity_spec(R)> auto PO,
|
||||
RepresentationOf<get_quantity_spec(R).character> Rep = double>
|
||||
class quantity_point;
|
||||
```
|
||||
|
||||
Its value can be easily created by adding/subtracting the [quantity](#quantity) with
|
||||
a [point origin](#point-origin).
|
||||
|
||||
For example:
|
||||
|
||||
- The following specifies a quantity point defined in terms of an `ice_point` provided in
|
||||
the previous example:
|
||||
|
||||
```cpp
|
||||
constexpr auto room_reference_temperature = ice_point + isq::Celsius_temperature(21 * deg_C);
|
||||
```
|
@ -107,7 +107,7 @@ accepts everything:
|
||||
|
||||
## Constraining function template arguments with concepts
|
||||
|
||||
Much better generic code can be implemented using [basic concepts](basic_concepts.md)
|
||||
Much better generic code can be implemented using [basic concepts](concepts.md)
|
||||
provided with the library:
|
||||
|
||||
```cpp
|
||||
@ -119,7 +119,7 @@ auto avg_speed(QuantityOf<isq::length> auto distance,
|
||||
```
|
||||
|
||||
This explicitly states that the arguments passed by the user must not only satisfy
|
||||
a [`Quantity`](basic_concepts.md#Quantity) concept but also their quantity specification must
|
||||
a [`Quantity`](concepts.md#Quantity) concept but also their quantity specification must
|
||||
be implicitly convertible to `isq::length` and `isq::time` accordingly. This no longer leaves
|
||||
room for error while still allowing the compiler to generate the most efficient code.
|
||||
|
||||
@ -192,4 +192,4 @@ what we expected here.
|
||||
|
||||
The `QuantityOf` and `QuantityPointOf` concepts are probably the most useful, but there
|
||||
are a few more to play with. A list of all the concepts can be found in
|
||||
[the "Basic Concepts" chapter](basic_concepts.md).
|
||||
[the "Basic Concepts" chapter](concepts.md).
|
||||
|
@ -138,7 +138,7 @@ template<PrefixableUnit auto U> struct quecto_ : prefixed_unit<"q", mag_power<10
|
||||
template<PrefixableUnit auto U> inline constexpr quecto_<U> quecto;
|
||||
```
|
||||
|
||||
and then a [PrefixableUnit](basic_concepts.md#PrefixableUnit) can be prefixed in the following
|
||||
and then a [PrefixableUnit](concepts.md#PrefixableUnit) can be prefixed in the following
|
||||
way:
|
||||
|
||||
```cpp
|
||||
|
@ -55,7 +55,7 @@ the affine space.
|
||||
|
||||
In the **mp-units** library the _point_ abstraction is modelled by:
|
||||
|
||||
- [`PointOrigin` concept](basic_concepts.md#PointOrigin) that specifies measurement origin,
|
||||
- [`PointOrigin` concept](concepts.md#PointOrigin) that specifies measurement origin,
|
||||
- `quantity_point` class template that specifies a _point_ relative to a specific predefined origin.
|
||||
|
||||
### Absolute _point_ origin
|
||||
@ -79,7 +79,7 @@ class quantity_point;
|
||||
```
|
||||
|
||||
As we can see above, the `quantity_point` class template exposes one additional parameter compared
|
||||
to `quantity`. The `PO` parameter satisfies a [`PointOriginFor` concept](basic_concepts.md#PointOriginFor)
|
||||
to `quantity`. The `PO` parameter satisfies a [`PointOriginFor` concept](concepts.md#PointOriginFor)
|
||||
and specifies the origin of our measurement scale.
|
||||
|
||||
!!! tip
|
||||
|
@ -111,8 +111,8 @@ nav:
|
||||
- User's Guide:
|
||||
- Terms and Definitions: users_guide/terms_and_definitions.md
|
||||
- Framework Basics:
|
||||
- Basic Concepts: users_guide/framework_basics/basic_concepts.md
|
||||
- Interface Introduction: users_guide/framework_basics/interface_introduction.md
|
||||
- Design Overview: users_guide/framework_basics/design_overview.md
|
||||
- Systems of Quantities: users_guide/framework_basics/systems_of_quantities.md
|
||||
- Systems of Units: users_guide/framework_basics/systems_of_units.md
|
||||
- Simple and Typed Quantities: users_guide/framework_basics/simple_and_typed_quantities.md
|
||||
@ -124,6 +124,7 @@ nav:
|
||||
- Faster-than-lightspeed Constants: users_guide/framework_basics/faster_than_lightspeed_constants.md
|
||||
- The Affine Space: users_guide/framework_basics/the_affine_space.md
|
||||
- Obtaining Metadata: users_guide/framework_basics/obtaining_metadata.md
|
||||
- Concepts: users_guide/framework_basics/concepts.md
|
||||
- Text Output: users_guide/framework_basics/text_output.md
|
||||
- Defining Systems:
|
||||
- Introduction: users_guide/defining_systems/introduction.md
|
||||
|
Reference in New Issue
Block a user