From 70ada0ecf35e740d0d10a64b058b12ad32475ffa Mon Sep 17 00:00:00 2001 From: Chip Hogg Date: Wed, 20 Jul 2022 01:03:55 +0000 Subject: [PATCH 1/8] Update prefix documentation --- docs/framework/units.rst | 55 +++++++++++++++++++++------------------- 1 file changed, 29 insertions(+), 26 deletions(-) diff --git a/docs/framework/units.rst b/docs/framework/units.rst index f9981ba5..c29977b0 100644 --- a/docs/framework/units.rst +++ b/docs/framework/units.rst @@ -206,26 +206,27 @@ complete list of all the :term:`SI` prefixes supported by the library:: namespace si { - struct yocto : prefix {}; - struct zepto : prefix {}; - struct atto : prefix {}; - struct femto : prefix {}; - struct pico : prefix {}; - struct nano : prefix {}; - struct micro : prefix {}; - struct milli : prefix {}; - struct centi : prefix {}; - struct deci : prefix {}; - struct deca : prefix {}; - struct hecto : prefix {}; - struct kilo : prefix {}; - struct mega : prefix {}; - struct giga : prefix {}; - struct tera : prefix {}; - struct peta : prefix {}; - struct exa : prefix {}; - struct zetta : prefix {}; - struct yotta : prefix {}; + struct yocto : prefix(as_magnitude<10>())> {}; + struct zepto : prefix(as_magnitude<10>())> {}; + struct atto : prefix(as_magnitude<10>())> {}; + struct femto : prefix(as_magnitude<10>())> {}; + struct pico : prefix(as_magnitude<10>())> {}; + struct nano : prefix(as_magnitude<10>())> {}; + struct micro : prefix(as_magnitude<10>())> {}; + struct milli : prefix(as_magnitude<10>())> {}; + struct centi : prefix(as_magnitude<10>())> {}; + struct deci : prefix(as_magnitude<10>())> {}; + struct deca : prefix(as_magnitude<10>())> {}; + struct hecto : prefix(as_magnitude<10>())> {}; + struct kilo : prefix(as_magnitude<10>())> {}; + struct mega : prefix(as_magnitude<10>())> {}; + struct giga : prefix(as_magnitude<10>())> {}; + struct tera : prefix(as_magnitude<10>())> {}; + struct peta : prefix(as_magnitude<10>())> {}; + struct exa : prefix(as_magnitude<10>())> {}; + struct zetta : prefix(as_magnitude<10>())> {}; + struct yotta : prefix(as_magnitude<10>())> {}; } @@ -234,12 +235,14 @@ domain:: namespace iec80000 { - struct kibi : prefix {}; - struct mebi : prefix {}; - struct gibi : prefix {}; - struct tebi : prefix {}; - struct pebi : prefix {}; - struct exbi : prefix {}; + struct kibi : prefix(as_magnitude<2>())> {}; + struct mebi : prefix(as_magnitude<2>())> {}; + struct gibi : prefix(as_magnitude<2>())> {}; + struct tebi : prefix(as_magnitude<2>())> {}; + struct pebi : prefix(as_magnitude<2>())> {}; + struct exbi : prefix(as_magnitude<2>())> {}; + struct zebi : prefix(as_magnitude<2>())> {}; + struct yobi : prefix(as_magnitude<2>())> {}; } From 10b553bdbefe3d7f4bc5c997a0f7c51108ee3f39 Mon Sep 17 00:00:00 2001 From: Chip Hogg Date: Thu, 4 Aug 2022 19:13:53 +0000 Subject: [PATCH 2/8] Adapt Aurora's Magnitude docs for mp-units The major missing work here is to see how the latex math, inside dollar signs, translates to the docs. I also added a new constant, `pi`, to make the docs correct: this should be much more user friendly. This is not intended to be "complete". Rather, the goal is to deliver the raw content so that experts can massage it. --- docs/framework.rst | 1 + docs/framework/magnitudes.rst | 119 +++++++++++++++++++++++++++++ src/core/include/units/magnitude.h | 5 ++ 3 files changed, 125 insertions(+) create mode 100644 docs/framework/magnitudes.rst diff --git a/docs/framework.rst b/docs/framework.rst index cacfa71b..952d66fc 100644 --- a/docs/framework.rst +++ b/docs/framework.rst @@ -17,6 +17,7 @@ Framework Basics framework/quantity_points framework/quantity_kinds framework/dimensions + framework/magnitudes framework/units framework/arithmetics framework/constants diff --git a/docs/framework/magnitudes.rst b/docs/framework/magnitudes.rst new file mode 100644 index 00000000..4cff7c51 --- /dev/null +++ b/docs/framework/magnitudes.rst @@ -0,0 +1,119 @@ +.. namespace:: units + +Magnitudes +========== + +The ratio of two Units of the same Dimension---say, `inches` and `centi`---is some constant +number, which is known at compile time. It's a positive real number---a _Magnitude_. + +We also use Magnitudes for _Dimensionless_ Units. `percent` has a Magnitude of $1/100$, and `dozen` +would have a Magnitude of $12$. + +Interestingly, it turns out that the usual numeric types are not up to this task. We need +a Magnitude representation that can do everything Units can do. This means, among other things: + +1. We need _exact_ symbolic computation of the core operations of Quantity Calculus (i.e., products + and rational powers). + +2. We must support _irrational_ Magnitudes, because they frequently occur in practice (e.g., + consider the ratio between `degrees` and `radians`). + +3. We should _avoid overflow_ wherever possible (note that `std::intmax_t` can't even handle certain + simple SI prefixes, such as `yotta`, representing $10^{24}$). + +Integers' inadequacies are clear enough, but even floating point falls short. Imagine if we +implemented all angular units in terms of `radians`: then both `degrees` and `revolutions` pick up +a factor of $\pi$. The arithmetic with _its floating point representation_ is unlikely to cancel +_exactly_. + +Another common alternative choice is `std::ratio`, but this fails the first requirement: rational +numbers are ([rather infamously](https://hsm.stackexchange.com/a/7)!) _not_ closed under rational +powers. + +The only viable solution we have yet encountered is the _vector space representation_. The +implementation is fascinating---but, for purposes of this present page, it's also a distraction. +_Here,_ we're more focused on how to _use_ these Magnitudes. + +One type per Magnitude, one value per type +------------------------------------------ + +Each typical numeric type (`double`, `int64_t`, ...) can represent a wide variety of values: the +more, the better. However, Magnitudes are **not** like that. Instead, they comprise a _variety_ of +types, and each type can hold only _one_ value. + +.. tip:: + + A given Magnitude represents the _same_ number, whether you use it as a _type_, or as a _value_ + (i.e., an _instance_ of that type). + + Use whichever is more convenient. (In practice, this is usually the _value_: especially for end + users rather than library developers.) + +If these types can only represent one value each, why would we bother to instantiate them? Because +_values are easier to use_. + +- `mag()` gives the Magnitude value corresponding to any integer `N`. +- You can combine values in the usual way using `*`, `/`, `==`, and `!=`, as well as `pow(m)` and + `root(m)` for any Magnitude value `m`. + +Traits: integers and rational Magnitudes +---------------------------------------- + +If you have a Magnitude instance `m`, we provide traits to help you reason about integers and +rational numbers, or manipulate integer or rational parts. + +- `is_integral(m)`: indicates whether `m` represents an _integral_ Magnitude. +- `is_rational(m)`: indicates whether `m` represents a _rational_ Magnitude. + +The above traits indicate what kind of Magnitude we already have. The next traits _manipulate_ a +Magnitude, letting us break it apart into _constituent_ Magnitudes which may be more meaningful. +(For example, imagine going from `inches` to `feet`. Naively, we might multiply by the floating +point representation of `1.0 / 12.0`. However, if we broke this apart into separate numerator and +denominator, it would let us simply _divide by 12_, yielding **exact** results for inputs that +happen to be multiples of 12.) + +- `numerator(m)` (value): a Magnitude representing the "numerator", i.e., the largest integer which + divides `m`, without turning any of its base powers' exponents negative (or making any + previously-negative exponents _more_ negative). +- `denominator(m)` (value): the "numerator" of the _inverse_ of `m`. + +These traits interact as one would hope. For example, `is_rational(m)` is exactly equivalent to +`m == numerator(m) / denominator(m)`. + +Why these particular definitions? Because they are equivalent to the numerator and denominator when +we have a rational number, and they are compatible with how humans write numbers when we don't. +Example: + +- $m1 = \frac{27 \pi^2}{25}$. Then `numerator(m1) == mag<27>()`, and + `denominator(m1) == mag<25>()`. +- $m2 = \sqrt{m1}$. Then `numerator(m2) == mag<3>()`, and `denominator(m2) == mag<5>()`. Note that + this is consistent with how humans would typically write `m2`, as $\frac{3\sqrt{3} \pi}{5}$. + +Getting values out +------------------ + +Magnitude types represent numbers in non-numeric types. They've got some amazing strengths (exact +rational powers!), and some significant weaknesses (no support for basic addition!). So what if you +just want to turn a Magnitude `m` into a traditional numeric type `T`? + +You call `get_value(m)`. + +This does what it looks like it does, and it does it at compile time. Any intermediate computations +take place in the "widest type in category"---`long double` for floating point, and `std::intmax_t` +or `std::uintmax_t` for signed or unsigned integers---before ultimately being cast back to the +target type. For `T = float`, say, this means we get all the precision we'd have with something +like `long double`, but without any speed penalty at runtime! + +`get_value(m)` also has the protections you would hope: for example, if `T` is an integral type, +we require `is_integral(m)`. + +How to use Magnitudes +--------------------- + +- First, start with your basic inputs: this will typically be `mag()` for any integer `N`, or the + built-in Magnitude constant `pi`. (Again, these are all _values_, not types.) + +- Next, combine and manipulate these using the various "Magnitude math" operations, all of which are + **exact**: `*`, `/`, `pow`, `root`, `numerator()`, `denominator()`. + +- If you need to translate a Magnitude `m` to a "real" numeric type `T`, call `get_value(m)`. diff --git a/src/core/include/units/magnitude.h b/src/core/include/units/magnitude.h index c81fb538..88a50c3f 100644 --- a/src/core/include/units/magnitude.h +++ b/src/core/include/units/magnitude.h @@ -398,6 +398,11 @@ struct pi_base { static constexpr long double value = std::numbers::pi_v; }; +/** + * @brief A convenient Magnitude constant for pi, which we can manipulate like a regular number. + */ +inline constexpr Magnitude auto pi = magnitude{}>{}; + //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Magnitude equality implementation. From 8076ecf50f8d133a66dfccdaf6d0cc040e4199bc Mon Sep 17 00:00:00 2001 From: Chip Hogg Date: Wed, 10 Aug 2022 01:14:00 +0000 Subject: [PATCH 3/8] Update CMakeLists --- docs/CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/CMakeLists.txt b/docs/CMakeLists.txt index 04c7fc08..87801659 100644 --- a/docs/CMakeLists.txt +++ b/docs/CMakeLists.txt @@ -87,6 +87,7 @@ set(unitsSphinxDocs "${CMAKE_CURRENT_SOURCE_DIR}/framework/constants.rst" "${CMAKE_CURRENT_SOURCE_DIR}/framework/conversions_and_casting.rst" "${CMAKE_CURRENT_SOURCE_DIR}/framework/dimensions.rst" + "${CMAKE_CURRENT_SOURCE_DIR}/framework/magnitudes.rst" "${CMAKE_CURRENT_SOURCE_DIR}/framework/quantities.rst" "${CMAKE_CURRENT_SOURCE_DIR}/framework/quantity_kinds.rst" "${CMAKE_CURRENT_SOURCE_DIR}/framework/quantity_like.rst" From d0325da46a5dd681775de2a86f8497d02aba8657 Mon Sep 17 00:00:00 2001 From: Chip Hogg Date: Wed, 10 Aug 2022 01:14:12 +0000 Subject: [PATCH 4/8] Fix math notation in magnitude doc --- docs/framework/magnitudes.rst | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/docs/framework/magnitudes.rst b/docs/framework/magnitudes.rst index 4cff7c51..b0efc165 100644 --- a/docs/framework/magnitudes.rst +++ b/docs/framework/magnitudes.rst @@ -6,8 +6,8 @@ Magnitudes The ratio of two Units of the same Dimension---say, `inches` and `centi`---is some constant number, which is known at compile time. It's a positive real number---a _Magnitude_. -We also use Magnitudes for _Dimensionless_ Units. `percent` has a Magnitude of $1/100$, and `dozen` -would have a Magnitude of $12$. +We also use Magnitudes for _Dimensionless_ Units. `percent` has a Magnitude of :math:`1/100`, and +`dozen` would have a Magnitude of :math:`12`. Interestingly, it turns out that the usual numeric types are not up to this task. We need a Magnitude representation that can do everything Units can do. This means, among other things: @@ -19,12 +19,12 @@ a Magnitude representation that can do everything Units can do. This means, amo consider the ratio between `degrees` and `radians`). 3. We should _avoid overflow_ wherever possible (note that `std::intmax_t` can't even handle certain - simple SI prefixes, such as `yotta`, representing $10^{24}$). + simple SI prefixes, such as `yotta`, representing :math:`10^{24}`). Integers' inadequacies are clear enough, but even floating point falls short. Imagine if we implemented all angular units in terms of `radians`: then both `degrees` and `revolutions` pick up -a factor of $\pi$. The arithmetic with _its floating point representation_ is unlikely to cancel -_exactly_. +a factor of :math:`\pi`. The arithmetic with _its floating point representation_ is unlikely to +cancel _exactly_. Another common alternative choice is `std::ratio`, but this fails the first requirement: rational numbers are ([rather infamously](https://hsm.stackexchange.com/a/7)!) _not_ closed under rational @@ -84,10 +84,11 @@ Why these particular definitions? Because they are equivalent to the numerator we have a rational number, and they are compatible with how humans write numbers when we don't. Example: -- $m1 = \frac{27 \pi^2}{25}$. Then `numerator(m1) == mag<27>()`, and +- :math:`m1 = \frac{27 \pi^2}{25}`. Then `numerator(m1) == mag<27>()`, and `denominator(m1) == mag<25>()`. -- $m2 = \sqrt{m1}$. Then `numerator(m2) == mag<3>()`, and `denominator(m2) == mag<5>()`. Note that - this is consistent with how humans would typically write `m2`, as $\frac{3\sqrt{3} \pi}{5}$. +- :math:`m2 = \sqrt{m1}`. Then `numerator(m2) == mag<3>()`, and `denominator(m2) == mag<5>()`. + Note that this is consistent with how humans would typically write `m2`, as :math:`\frac{3\sqrt{3} + \pi}{5}`. Getting values out ------------------ From ce3f0484566cf14ebd890864483aaa8d28f3bc2a Mon Sep 17 00:00:00 2001 From: Chip Hogg Date: Wed, 10 Aug 2022 23:36:44 +0000 Subject: [PATCH 5/8] Address remaining comments for `magnitudes.rst` --- docs/framework/magnitudes.rst | 119 +++++++++++++++++----------------- 1 file changed, 60 insertions(+), 59 deletions(-) diff --git a/docs/framework/magnitudes.rst b/docs/framework/magnitudes.rst index b0efc165..e903b86d 100644 --- a/docs/framework/magnitudes.rst +++ b/docs/framework/magnitudes.rst @@ -3,118 +3,119 @@ Magnitudes ========== -The ratio of two Units of the same Dimension---say, `inches` and `centi`---is some constant -number, which is known at compile time. It's a positive real number---a _Magnitude_. +The ratio of two Units of the same Dimension---say, ``inches`` and ``centimeters``---is some +constant number, which is known at compile time. It's a positive real number---a _Magnitude_. -We also use Magnitudes for _Dimensionless_ Units. `percent` has a Magnitude of :math:`1/100`, and -`dozen` would have a Magnitude of :math:`12`. +We also use Magnitudes for _Dimensionless_ Units. ``percent`` has a Magnitude of :math:`1/100`, and +``dozen`` would have a Magnitude of :math:`12`. -Interestingly, it turns out that the usual numeric types are not up to this task. We need -a Magnitude representation that can do everything Units can do. This means, among other things: +Interestingly, it turns out that the usual numeric types are not up to this task. We need a +Magnitude representation that can do everything Units can do. This means, among other things: -1. We need _exact_ symbolic computation of the core operations of Quantity Calculus (i.e., products +1. We need *exact* symbolic computation of the core operations of Quantity Calculus (i.e., products and rational powers). -2. We must support _irrational_ Magnitudes, because they frequently occur in practice (e.g., - consider the ratio between `degrees` and `radians`). +2. We must support *irrational* Magnitudes, because they frequently occur in practice (e.g., + consider the ratio between ``degrees`` and ``radians``). -3. We should _avoid overflow_ wherever possible (note that `std::intmax_t` can't even handle certain - simple SI prefixes, such as `yotta`, representing :math:`10^{24}`). +3. We should *avoid overflow* wherever possible (note that ``std::intmax_t`` can't even handle + certain simple SI prefixes, such as ``yotta``, representing :math:`10^{24}`). Integers' inadequacies are clear enough, but even floating point falls short. Imagine if we -implemented all angular units in terms of `radians`: then both `degrees` and `revolutions` pick up -a factor of :math:`\pi`. The arithmetic with _its floating point representation_ is unlikely to -cancel _exactly_. +implemented all angular units in terms of ``radians``: then both ``degrees`` and ``revolutions`` +pick up a factor of :math:`\pi`. The arithmetic with *its floating point representation* is +unlikely to cancel *exactly*. -Another common alternative choice is `std::ratio`, but this fails the first requirement: rational -numbers are ([rather infamously](https://hsm.stackexchange.com/a/7)!) _not_ closed under rational +Another common alternative choice is ``std::ratio``, but this fails the first requirement: rational +numbers are (`rather infamously `_!) *not* closed under rational powers. -The only viable solution we have yet encountered is the _vector space representation_. The +The only viable solution we have yet encountered is the *vector space representation*. The implementation is fascinating---but, for purposes of this present page, it's also a distraction. -_Here,_ we're more focused on how to _use_ these Magnitudes. +*Here,* we're more focused on how to *use* these Magnitudes. One type per Magnitude, one value per type ------------------------------------------ -Each typical numeric type (`double`, `int64_t`, ...) can represent a wide variety of values: the -more, the better. However, Magnitudes are **not** like that. Instead, they comprise a _variety_ of -types, and each type can hold only _one_ value. +Each typical numeric type (``double``, ``int64_t``, ...) can represent a wide variety of values: the +more, the better. However, Magnitudes are **not** like that. Instead, they comprise a *variety* of +types, and each type can hold only *one* value. .. tip:: - A given Magnitude represents the _same_ number, whether you use it as a _type_, or as a _value_ - (i.e., an _instance_ of that type). + A given Magnitude represents the *same* number, whether you use it as a *type*, or as a *value* + (i.e., an *instance* of that type). - Use whichever is more convenient. (In practice, this is usually the _value_: especially for end + Use whichever is more convenient. (In practice, this is usually the *value*: especially for end users rather than library developers.) If these types can only represent one value each, why would we bother to instantiate them? Because -_values are easier to use_. +*values are easier to use*. -- `mag()` gives the Magnitude value corresponding to any integer `N`. -- You can combine values in the usual way using `*`, `/`, `==`, and `!=`, as well as `pow(m)` and - `root(m)` for any Magnitude value `m`. +- ``mag()`` gives the Magnitude value corresponding to any integer ``N``. - You can combine + values in the usual way using ``*``, ``/``, ``==``, and ``!=``, as well as ``pow(m)`` and + ``root(m)`` for any Magnitude value ``m``. Traits: integers and rational Magnitudes ---------------------------------------- -If you have a Magnitude instance `m`, we provide traits to help you reason about integers and +If you have a Magnitude instance ``m``, we provide traits to help you reason about integers and rational numbers, or manipulate integer or rational parts. -- `is_integral(m)`: indicates whether `m` represents an _integral_ Magnitude. -- `is_rational(m)`: indicates whether `m` represents a _rational_ Magnitude. +- ``is_integral(m)``: indicates whether ``m`` represents an *integral* Magnitude. +- ``is_rational(m)``: indicates whether ``m`` represents a *rational* Magnitude. -The above traits indicate what kind of Magnitude we already have. The next traits _manipulate_ a -Magnitude, letting us break it apart into _constituent_ Magnitudes which may be more meaningful. -(For example, imagine going from `inches` to `feet`. Naively, we might multiply by the floating -point representation of `1.0 / 12.0`. However, if we broke this apart into separate numerator and -denominator, it would let us simply _divide by 12_, yielding **exact** results for inputs that +The above traits indicate what kind of Magnitude we already have. The next traits *manipulate* a +Magnitude, letting us break it apart into *constituent* Magnitudes which may be more meaningful. +(For example, imagine going from ``inches`` to ``feet``. Naively, we might multiply by the floating +point representation of ``1.0 / 12.0````. However, if we broke this apart into separate numerator +and denominator, it would let us simply *divide by 12*, yielding **exact** results for inputs that happen to be multiples of 12.) -- `numerator(m)` (value): a Magnitude representing the "numerator", i.e., the largest integer which - divides `m`, without turning any of its base powers' exponents negative (or making any - previously-negative exponents _more_ negative). -- `denominator(m)` (value): the "numerator" of the _inverse_ of `m`. +- ``numerator(m)`` (value): a Magnitude representing the "numerator", i.e., the largest integer + which divides ``m``, without turning any of its base powers' exponents negative (or making any + previously-negative exponents *more* negative). - ``denominator(m)`` (value): the "numerator" of + the *inverse* of ``m``. -These traits interact as one would hope. For example, `is_rational(m)` is exactly equivalent to -`m == numerator(m) / denominator(m)`. +These traits interact as one would hope. For example, ``is_rational(m)`` is exactly equivalent to +``m == numerator(m) / denominator(m)``. Why these particular definitions? Because they are equivalent to the numerator and denominator when we have a rational number, and they are compatible with how humans write numbers when we don't. Example: -- :math:`m1 = \frac{27 \pi^2}{25}`. Then `numerator(m1) == mag<27>()`, and - `denominator(m1) == mag<25>()`. -- :math:`m2 = \sqrt{m1}`. Then `numerator(m2) == mag<3>()`, and `denominator(m2) == mag<5>()`. - Note that this is consistent with how humans would typically write `m2`, as :math:`\frac{3\sqrt{3} - \pi}{5}`. +- :math:`m1 = \frac{27 \pi^2}{25}`. Then ``numerator(m1) == mag<27>()``, and + ``denominator(m1) == mag<25>()``. +- :math:`m2 = \sqrt{m1}`. Then ``numerator(m2) == mag<3>()``, and ``denominator(m2) == mag<5>()``. + Note that this is consistent with how humans would typically write ``m2``, as + :math:`\frac{3\sqrt{3} \pi}{5}`. Getting values out ------------------ Magnitude types represent numbers in non-numeric types. They've got some amazing strengths (exact rational powers!), and some significant weaknesses (no support for basic addition!). So what if you -just want to turn a Magnitude `m` into a traditional numeric type `T`? +just want to turn a Magnitude ``m`` into a traditional numeric type ``T``? -You call `get_value(m)`. +You call ``get_value(m)``. This does what it looks like it does, and it does it at compile time. Any intermediate computations -take place in the "widest type in category"---`long double` for floating point, and `std::intmax_t` -or `std::uintmax_t` for signed or unsigned integers---before ultimately being cast back to the -target type. For `T = float`, say, this means we get all the precision we'd have with something -like `long double`, but without any speed penalty at runtime! +take place in the "widest type in category"---``long double`` for floating point, and +``std::intmax_t`` or ``std::uintmax_t`` for signed or unsigned integers---before ultimately being +cast back to the target type. For ``T = float``, say, this means we get all the precision we'd have +with something like ``long double``, but without any speed penalty at runtime! -`get_value(m)` also has the protections you would hope: for example, if `T` is an integral type, -we require `is_integral(m)`. +``get_value(m)`` also has the protections you would hope: for example, if ``T`` is an integral +type, we require ``is_integral(m)``. How to use Magnitudes --------------------- -- First, start with your basic inputs: this will typically be `mag()` for any integer `N`, or the - built-in Magnitude constant `pi`. (Again, these are all _values_, not types.) +- First, start with your basic inputs: this will typically be ``mag()`` for any integer ``N``, or + the built-in Magnitude constant ``pi``. (Again, these are all *values*, not types.) - Next, combine and manipulate these using the various "Magnitude math" operations, all of which are - **exact**: `*`, `/`, `pow`, `root`, `numerator()`, `denominator()`. + **exact**: ``*``, ``/``, ``pow``, ``root``, ``numerator()``, ``denominator()``. -- If you need to translate a Magnitude `m` to a "real" numeric type `T`, call `get_value(m)`. +- If you need to translate a Magnitude ``m`` to a "real" numeric type ``T``, call + ``get_value(m)``. From 28d8a7c4b183608719b3b1355b25d8e5f019d540 Mon Sep 17 00:00:00 2001 From: Chip Hogg Date: Wed, 10 Aug 2022 23:38:50 +0000 Subject: [PATCH 6/8] Update documented prefixes --- docs/framework/units.rst | 56 ++++++++++++++++++++-------------------- 1 file changed, 28 insertions(+), 28 deletions(-) diff --git a/docs/framework/units.rst b/docs/framework/units.rst index 11243103..c3ad6b96 100644 --- a/docs/framework/units.rst +++ b/docs/framework/units.rst @@ -203,27 +203,27 @@ complete list of all the :term:`SI` prefixes supported by the library:: namespace si { - struct yocto : prefix(as_magnitude<10>())> {}; - struct zepto : prefix(as_magnitude<10>())> {}; - struct atto : prefix(as_magnitude<10>())> {}; - struct femto : prefix(as_magnitude<10>())> {}; - struct pico : prefix(as_magnitude<10>())> {}; - struct nano : prefix(as_magnitude<10>())> {}; + struct yocto : prefix(mag<10>())> {}; + struct zepto : prefix(mag<10>())> {}; + struct atto : prefix(mag<10>())> {}; + struct femto : prefix(mag<10>())> {}; + struct pico : prefix(mag<10>())> {}; + struct nano : prefix(mag<10>())> {}; struct micro : prefix(as_magnitude<10>())> {}; - struct milli : prefix(as_magnitude<10>())> {}; - struct centi : prefix(as_magnitude<10>())> {}; - struct deci : prefix(as_magnitude<10>())> {}; - struct deca : prefix(as_magnitude<10>())> {}; - struct hecto : prefix(as_magnitude<10>())> {}; - struct kilo : prefix(as_magnitude<10>())> {}; - struct mega : prefix(as_magnitude<10>())> {}; - struct giga : prefix(as_magnitude<10>())> {}; - struct tera : prefix(as_magnitude<10>())> {}; - struct peta : prefix(as_magnitude<10>())> {}; - struct exa : prefix(as_magnitude<10>())> {}; - struct zetta : prefix(as_magnitude<10>())> {}; - struct yotta : prefix(as_magnitude<10>())> {}; + pow<-6>(mag<10>())> {}; + struct milli : prefix(mag<10>())> {}; + struct centi : prefix(mag<10>())> {}; + struct deci : prefix(mag<10>())> {}; + struct deca : prefix(mag<10>())> {}; + struct hecto : prefix(mag<10>())> {}; + struct kilo : prefix(mag<10>())> {}; + struct mega : prefix(mag<10>())> {}; + struct giga : prefix(mag<10>())> {}; + struct tera : prefix(mag<10>())> {}; + struct peta : prefix(mag<10>())> {}; + struct exa : prefix(mag<10>())> {}; + struct zetta : prefix(mag<10>())> {}; + struct yotta : prefix(mag<10>())> {}; } @@ -232,14 +232,14 @@ domain:: namespace iec80000 { - struct kibi : prefix(as_magnitude<2>())> {}; - struct mebi : prefix(as_magnitude<2>())> {}; - struct gibi : prefix(as_magnitude<2>())> {}; - struct tebi : prefix(as_magnitude<2>())> {}; - struct pebi : prefix(as_magnitude<2>())> {}; - struct exbi : prefix(as_magnitude<2>())> {}; - struct zebi : prefix(as_magnitude<2>())> {}; - struct yobi : prefix(as_magnitude<2>())> {}; + struct kibi : prefix(mag<2>())> {}; + struct mebi : prefix(mag<2>())> {}; + struct gibi : prefix(mag<2>())> {}; + struct tebi : prefix(mag<2>())> {}; + struct pebi : prefix(mag<2>())> {}; + struct exbi : prefix(mag<2>())> {}; + struct zebi : prefix(mag<2>())> {}; + struct yobi : prefix(mag<2>())> {}; } From 327892a9b325c393679914891b7d798d0b841fd9 Mon Sep 17 00:00:00 2001 From: Chip Hogg Date: Thu, 11 Aug 2022 13:43:04 +0000 Subject: [PATCH 7/8] Fix underscores and excess backticks --- docs/framework/magnitudes.rst | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/framework/magnitudes.rst b/docs/framework/magnitudes.rst index e903b86d..afdb5b43 100644 --- a/docs/framework/magnitudes.rst +++ b/docs/framework/magnitudes.rst @@ -4,9 +4,9 @@ Magnitudes ========== The ratio of two Units of the same Dimension---say, ``inches`` and ``centimeters``---is some -constant number, which is known at compile time. It's a positive real number---a _Magnitude_. +constant number, which is known at compile time. It's a positive real number---a *Magnitude*. -We also use Magnitudes for _Dimensionless_ Units. ``percent`` has a Magnitude of :math:`1/100`, and +We also use Magnitudes for *Dimensionless* Units. ``percent`` has a Magnitude of :math:`1/100`, and ``dozen`` would have a Magnitude of :math:`12`. Interestingly, it turns out that the usual numeric types are not up to this task. We need a @@ -68,8 +68,8 @@ rational numbers, or manipulate integer or rational parts. The above traits indicate what kind of Magnitude we already have. The next traits *manipulate* a Magnitude, letting us break it apart into *constituent* Magnitudes which may be more meaningful. (For example, imagine going from ``inches`` to ``feet``. Naively, we might multiply by the floating -point representation of ``1.0 / 12.0````. However, if we broke this apart into separate numerator -and denominator, it would let us simply *divide by 12*, yielding **exact** results for inputs that +point representation of ``1.0 / 12.0``. However, if we broke this apart into separate numerator and +denominator, it would let us simply *divide by 12*, yielding **exact** results for inputs that happen to be multiples of 12.) - ``numerator(m)`` (value): a Magnitude representing the "numerator", i.e., the largest integer From df290a74f0c63c63176d7c42b90065aa1eee4c42 Mon Sep 17 00:00:00 2001 From: Chip Hogg Date: Thu, 11 Aug 2022 15:56:10 +0000 Subject: [PATCH 8/8] Remove shadowing declaration of `pi` --- test/unit_test/runtime/magnitude_test.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/test/unit_test/runtime/magnitude_test.cpp b/test/unit_test/runtime/magnitude_test.cpp index a861b66c..d4e17e9a 100644 --- a/test/unit_test/runtime/magnitude_test.cpp +++ b/test/unit_test/runtime/magnitude_test.cpp @@ -193,7 +193,6 @@ TEST_CASE("magnitude converts to numerical value") SECTION("pi to the 1 supplies correct values") { - constexpr auto pi = pi_to_the<1>(); check_same_type_and_value(get_value(pi), std::numbers::pi_v); check_same_type_and_value(get_value(pi), std::numbers::pi_v); check_same_type_and_value(get_value(pi), std::numbers::pi_v);