| 
									
										
										
										
											2023-07-10 17:56:05 +02:00
										 |  |  | # Dimensionless Quantities
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | The quantities we discussed so far always had some specific type and physical dimension. | 
					
						
							|  |  |  | However, this is not always the case. While performing various computations, we sometimes end up with | 
					
						
							| 
									
										
										
										
											2023-12-26 11:07:21 +01:00
										 |  |  | so-called "dimensionless" quantities, which ISO defines as | 
					
						
							| 
									
										
										
										
											2023-08-03 21:23:34 +02:00
										 |  |  | [quantities of dimension one](../../appendix/glossary.md#dimensionless-quantity): | 
					
						
							| 
									
										
										
										
											2023-07-10 17:56:05 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | !!! quote "ISO/IEC Guide 99" | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     - Quantity for which all the exponents of the factors corresponding to the base quantities in | 
					
						
							|  |  |  |       its quantity dimension are zero. | 
					
						
							|  |  |  |     - The measurement units and values of quantities of dimension one are numbers, but such quantities | 
					
						
							|  |  |  |       convey more information than a number. | 
					
						
							|  |  |  |     - Some quantities of dimension one are defined as the ratios of two quantities of the same kind. | 
					
						
							|  |  |  |     - Numbers of entities are quantities of dimension one. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ## Dividing two quantities of the same kind
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Dividing two quantities of the same kind always results in a | 
					
						
							| 
									
										
										
										
											2023-08-03 21:23:34 +02:00
										 |  |  | [quantity of dimension one](../../appendix/glossary.md#dimensionless-quantity). | 
					
						
							| 
									
										
										
										
											2023-07-10 17:56:05 +02:00
										 |  |  | However, depending on what type of quantities we divide or what their units are, we may end up | 
					
						
							|  |  |  | with slightly different results. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | !!! note | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     In **mp-units**, dividing two quantities of the same dimension always results in a quantity | 
					
						
							|  |  |  |     with the dimension being `dimension_one`. This is often different for other physical units | 
					
						
							|  |  |  |     libraries, which may return a raw representation type for such cases. A raw value is also always | 
					
						
							|  |  |  |     returned from the division of two `std::chrono::duration` objects. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     To read more about the reasoning for this design decision, please check our | 
					
						
							| 
									
										
										
										
											2023-08-03 21:23:34 +02:00
										 |  |  |     [FAQ](../../getting_started/faq.md#why-a-dimensionless-quantity-is-not-just-a-fundamental-arithmetic-type). | 
					
						
							| 
									
										
										
										
											2023-07-10 17:56:05 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ### Dividing quantities of the same type
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | First, let's analyze what happens if we divide two quantities of the same type: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ```cpp | 
					
						
							|  |  |  | constexpr QuantityOf<dimensionless> auto q = isq::height(200 * m) / isq::height(50 * m); | 
					
						
							|  |  |  | ``` | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | In such a case, we end up with a dimensionless quantity that has the following properties: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ```cpp | 
					
						
							|  |  |  | static_assert(q.quantity_spec == dimensionless); | 
					
						
							|  |  |  | static_assert(q.dimension == dimension_one); | 
					
						
							|  |  |  | static_assert(q.unit == one); | 
					
						
							|  |  |  | ``` | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | In case we would like to print its value, we would see a raw value of `4` in the output with no unit | 
					
						
							|  |  |  | being printed. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ### Dividing quantities of different types
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Now let's see what happens if we divide quantities of the same dimension and unit but which have | 
					
						
							|  |  |  | different quantity types: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ```cpp | 
					
						
							|  |  |  | constexpr QuantityOf<dimensionless> auto q = isq::work(200 * J) / isq::heat(50 * J); | 
					
						
							|  |  |  | ``` | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Again we end up with `dimension_one` and `one`, but this time: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ```cpp | 
					
						
							|  |  |  | static_assert(q.quantity_spec == isq::work / isq::heat); | 
					
						
							|  |  |  | ``` | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | As shown above, the result is not of a `dimensionless` type anymore. Instead, we get a quantity type | 
					
						
							| 
									
										
										
										
											2023-08-03 21:23:34 +02:00
										 |  |  | derived from the performed [quantity equation](../../appendix/glossary.md#quantity-equation). | 
					
						
							| 
									
										
										
										
											2023-12-26 11:07:21 +01:00
										 |  |  | According to the [ISQ](../../appendix/glossary.md#isq), _work_ divided by _heat_ is the recipe for | 
					
						
							|  |  |  | the _thermodynamic efficiency_ quantity, thus: | 
					
						
							| 
									
										
										
										
											2023-07-10 17:56:05 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | ```cpp | 
					
						
							|  |  |  | static_assert(implicitly_convertible(q.quantity_spec, isq::efficiency_thermodynamics)); | 
					
						
							|  |  |  | ``` | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | !!! note | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     The quantity of `isq::efficiency_thermodynamics` is of a kind `dimensionless`, so it is implicitly | 
					
						
							|  |  |  |     convertible to `dimensionless` and satisfies the `QuantityOf<dimensionless>` concept. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ### Dividing quantities of different units
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Now, let's see what happens when we divide two quantities of the same type but different units: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ```cpp | 
					
						
							|  |  |  | constexpr QuantityOf<dimensionless> auto q = isq::height(4 * km) / isq::height(2 * m); | 
					
						
							|  |  |  | ``` | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-12-26 11:07:21 +01:00
										 |  |  | This time, we still get a quantity of the `dimensionless` type with a `dimension_one` as its dimension. | 
					
						
							| 
									
										
										
										
											2023-07-10 17:56:05 +02:00
										 |  |  | However, the resulting unit is not `one` anymore: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ```cpp | 
					
						
							|  |  |  | static_assert(q.unit == mag_power<10, 3> * one); | 
					
						
							|  |  |  | ``` | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | In case we would print the text output of this quantity, we would not see a raw value of `2000`, | 
					
						
							|  |  |  | but `2 km/m`. | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-12-26 11:07:21 +01:00
										 |  |  | First, it may look surprising, but this is consistent with dividing quantities | 
					
						
							| 
									
										
										
										
											2023-07-10 17:56:05 +02:00
										 |  |  | of different dimensions. For example, if we divide `4 * km / 2 * s`, we do not expect `km` to be | 
					
						
							|  |  |  | "expanded" to `m` before the division, right? We would expect the result of `2 km/s`, which is | 
					
						
							|  |  |  | exactly what we get when we divide quantities of the same kind. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | This is a compelling feature that allows us to express huge or tiny ratios without the need | 
					
						
							|  |  |  | for big and expensive representation types. With this, we can easily define things like | 
					
						
							| 
									
										
										
										
											2023-12-26 11:07:21 +01:00
										 |  |  | a [_Hubble's constant_](https://en.wikipedia.org/wiki/Hubble%27s_law#Dimensionless_Hubble_constant) | 
					
						
							| 
									
										
										
										
											2023-07-10 17:56:05 +02:00
										 |  |  | that uses a unit that is proportional to the ratio of kilometers per megaparsecs, which are both | 
					
						
							| 
									
										
										
										
											2023-12-26 11:07:21 +01:00
										 |  |  | units of _length_: | 
					
						
							| 
									
										
										
										
											2023-07-10 17:56:05 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | ```cpp | 
					
						
							|  |  |  | inline constexpr struct hubble_constant : | 
					
						
							|  |  |  |     named_unit<basic_symbol_text{"H₀", "H_0"}, mag<ratio{701, 10}> * si::kilo<si::metre> / si::second / si::mega<parsec>> {} hubble_constant; | 
					
						
							|  |  |  | ``` | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ## Counts of things
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Another important use case for dimensionless quantities is to provide strong types for counts | 
					
						
							|  |  |  | of things. For example: | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-12-26 11:07:21 +01:00
										 |  |  | - ISO-80000-3 provides a _rotation_ quantity defined as the number of revolutions, | 
					
						
							|  |  |  | - IEC-80000-6 provides a _number of turns in a winding_ quantity, | 
					
						
							|  |  |  | - IEC-80000-13 provides a _Hamming distance_ quantity defined as the number of digit positions | 
					
						
							| 
									
										
										
										
											2023-07-10 17:56:05 +02:00
										 |  |  |   in which the corresponding digits of two words of the same length are different. | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-12-26 11:07:21 +01:00
										 |  |  | Thanks to assigning strong names to such quantities, later on, they can be explicitly used as | 
					
						
							| 
									
										
										
										
											2023-08-03 21:23:34 +02:00
										 |  |  | arguments in the [quantity equations](../../appendix/glossary.md#quantity-equation) of other | 
					
						
							| 
									
										
										
										
											2023-07-10 17:56:05 +02:00
										 |  |  | quantities deriving from them. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ## Predefined units of the dimensionless quantity
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | As we observed above, the most common unit for dimensionless quantities is `one`. It has the | 
					
						
							|  |  |  | ratio of `1` and does not output any textual symbol. | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-10-25 14:14:26 +02:00
										 |  |  | !!! important "Important: `one` is an identity" | 
					
						
							| 
									
										
										
										
											2023-07-10 17:56:05 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |     A unit `one` is special in the entire type system of units as it is considered to be | 
					
						
							| 
									
										
										
										
											2023-08-03 21:23:34 +02:00
										 |  |  |     [an identity operand in the unit expression templates](interface_introduction.md#identities). | 
					
						
							| 
									
										
										
										
											2023-07-10 17:56:05 +02:00
										 |  |  |     This means that, for example: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     ```cpp | 
					
						
							|  |  |  |     static_assert(one * one == one); | 
					
						
							|  |  |  |     static_assert(one * si::metre == si::metre); | 
					
						
							|  |  |  |     static_assert(si::metre / si::metre == one); | 
					
						
							|  |  |  |     ``` | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     The same is also true for `dimension_one` and `dimensionless` in the domains of dimensions | 
					
						
							|  |  |  |     and quantity specifications. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Besides the unit `one`, there are a few other scaled units predefined in the library for usage | 
					
						
							|  |  |  | with dimensionless quantities: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ```cpp | 
					
						
							|  |  |  | inline constexpr struct percent : named_unit<"%", mag<ratio{1, 100}> * one> {} percent; | 
					
						
							|  |  |  | inline constexpr struct per_mille : named_unit<basic_symbol_text{"‰", "%o"}, mag<ratio(1, 1000)> * one> {} per_mille; | 
					
						
							|  |  |  | ``` | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ## Angular quantities
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-12-26 11:07:21 +01:00
										 |  |  | Special, often controversial, examples of dimensionless quantities are an _angular measure_ | 
					
						
							|  |  |  | and _solid angular measure_ quantities that are defined in the [ISQ](../../appendix/glossary.md#isq) | 
					
						
							|  |  |  | to be the result of a division of $arc\; length / radius$ and $area / radius^2$ respectively. | 
					
						
							| 
									
										
										
										
											2023-08-03 21:23:34 +02:00
										 |  |  | Moreover, [ISQ](../../appendix/glossary.md#isq) also explicitly states that both can be | 
					
						
							| 
									
										
										
										
											2023-12-26 11:07:21 +01:00
										 |  |  | expressed in the unit `one`. This means that both _angular measure_ and _solid angular measure_ | 
					
						
							|  |  |  | should be of a [kind](../../appendix/glossary.md#kind) dimensionless. | 
					
						
							| 
									
										
										
										
											2023-07-10 17:56:05 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-12-26 11:07:21 +01:00
										 |  |  | On the other hand, [ISQ](../../appendix/glossary.md#isq) also specifies that a unit radian can | 
					
						
							|  |  |  | be used for _angular measure_, and a unit steradian can be used for _solid angular measure_. | 
					
						
							| 
									
										
										
										
											2023-07-10 17:56:05 +02:00
										 |  |  | Those should not be mixed or used to express other types of dimensionless quantities. This means | 
					
						
							| 
									
										
										
										
											2023-12-26 11:07:21 +01:00
										 |  |  | that both _angular measure_ and _solid angular measure_ should also be | 
					
						
							| 
									
										
										
										
											2023-08-03 21:23:34 +02:00
										 |  |  | [quantity kinds](../../appendix/glossary.md#kind) by themselves. | 
					
						
							| 
									
										
										
										
											2023-07-10 17:56:05 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | !!! note | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     Many people claim that angle being a dimensionless quantity is a bad idea. There are | 
					
						
							|  |  |  |     proposals submitted to make an angle a base quantity and `rad` to become a base unit. More on this | 
					
						
							| 
									
										
										
										
											2023-08-03 21:23:34 +02:00
										 |  |  |     topic can be found in the ["Strong Angular System" chapter](../defining_systems/strong_angular_system.md). | 
					
						
							| 
									
										
										
										
											2023-07-10 17:56:05 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ## Nested quantity kinds
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-12-26 11:07:21 +01:00
										 |  |  | Angular quantities are not the only ones with such a "strange" behavior. Another but a similar case | 
					
						
							|  |  |  | is a _storage capacity_ quantity specified in IEC-80000-13 that again allows expressing it in both | 
					
						
							| 
									
										
										
										
											2023-07-10 17:56:05 +02:00
										 |  |  | `one` and `bit` units. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Those cases make dimensionless quantities an exceptional tree in the library. This is the only | 
					
						
							| 
									
										
										
										
											2023-08-03 21:23:34 +02:00
										 |  |  | [quantity hierarchy](../../appendix/glossary.md#quantity-hierarchy) that contains more than one | 
					
						
							|  |  |  | [quantity kind](../../appendix/glossary.md#kind) in its tree: | 
					
						
							| 
									
										
										
										
											2023-07-10 17:56:05 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | ```mermaid | 
					
						
							|  |  |  | flowchart TD | 
					
						
							|  |  |  |     dimensionless["dimensionless\n[one]"] | 
					
						
							|  |  |  |     dimensionless --- rotation | 
					
						
							|  |  |  |     dimensionless --- efficiency | 
					
						
							|  |  |  |     dimensionless --- angular_measure["angular_measure\n[rad]"] | 
					
						
							|  |  |  |     angular_measure --- rotational_displacement | 
					
						
							|  |  |  |     angular_measure --- phase_angle | 
					
						
							|  |  |  |     dimensionless --- solid_angular_measure["solid_angular_measure\n[sr]"] | 
					
						
							|  |  |  |     dimensionless --- drag_factor | 
					
						
							|  |  |  |     dimensionless --- storage_capacity["storage_capacity\n[bit]"] --- equivalent_binary_storage_capacity | 
					
						
							|  |  |  |     dimensionless --- ... | 
					
						
							|  |  |  | ``` | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | To provide such support in the library, we provided an `is_kind` specifier that can be appended | 
					
						
							|  |  |  | to the quantity specification: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | === "C++23" | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     ```cpp | 
					
						
							|  |  |  |     inline constexpr struct angular_measure : quantity_spec<dimensionless, arc_length / radius, is_kind> {} angular_measure; | 
					
						
							|  |  |  |     inline constexpr struct solid_angular_measure : quantity_spec<dimensionless, area / pow<2>(radius), is_kind> {} solid_angular_measure; | 
					
						
							|  |  |  |     inline constexpr struct storage_capacity : quantity_spec<dimensionless, is_kind> {} storage_capacity; | 
					
						
							|  |  |  |     ``` | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-07-11 17:22:32 +02:00
										 |  |  | === "C++20" | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     ```cpp | 
					
						
							|  |  |  |     inline constexpr struct angular_measure : quantity_spec<angular_measure, dimensionless, arc_length / radius, is_kind> {} angular_measure; | 
					
						
							|  |  |  |     inline constexpr struct solid_angular_measure : quantity_spec<solid_angular_measure, dimensionless, area / pow<2>(radius), is_kind> {} solid_angular_measure; | 
					
						
							|  |  |  |     inline constexpr struct storage_capacity : quantity_spec<storage_capacity, dimensionless, is_kind> {} storage_capacity; | 
					
						
							|  |  |  |     ``` | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-07-10 17:56:05 +02:00
										 |  |  | === "Portable" | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     ```cpp | 
					
						
							|  |  |  |     QUANTITY_SPEC(angular_measure, dimensionless, arc_length / radius, is_kind); | 
					
						
							|  |  |  |     QUANTITY_SPEC(solid_angular_measure, dimensionless, area / pow<2>(radius), is_kind); | 
					
						
							|  |  |  |     QUANTITY_SPEC(storage_capacity, dimensionless, is_kind); | 
					
						
							|  |  |  |     ``` | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | With the above, we can constrain `radian`, `steradian`, and `bit` to be allowed for usage with | 
					
						
							|  |  |  | specific quantity kinds only: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ```cpp | 
					
						
							|  |  |  | inline constexpr struct radian : named_unit<"rad", metre / metre, kind_of<isq::angular_measure>> {} radian; | 
					
						
							|  |  |  | inline constexpr struct steradian : named_unit<"sr", square(metre) / square(metre), kind_of<isq::solid_angular_measure>> {} steradian; | 
					
						
							|  |  |  | inline constexpr struct bit : named_unit<"bit", one, kind_of<storage_capacity>> {} bit; | 
					
						
							|  |  |  | ``` | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-12-26 11:07:21 +01:00
										 |  |  | but still allow the usage of `one` and its scaled versions for such quantities. |