C++ Logo

std-proposals

Advanced search

Re: [std-proposals] On the standardization of mp-units P3045R1

From: Tiago Freire <tmiguelf_at_[hidden]>
Date: Wed, 19 Jun 2024 18:50:02 +0000
>> Can the type system actually help us solve this problem at all? My impression is that mp_units doesn't help us solve this problem.
> Sure! This is the solution with mp-units:

It doesn’t. ASL is too superficial a problem, when you start to get to things like ISA altitude or pressure altitude (used often in aeronautics), these things are unconvertible to each other, you just can’t do it! Or when you get to things like datums, where references are not just offset to each other, but they are also rotated, and it is a problem that can only be solved in R3, quantity_point is a patch that only works in R1. It can only get you so far.
But here’s the good news, you don’t actually have to solve this problem, and there is where things went wrong.

It’s an idea, may have some usage, but as I have stated affine spaces is a problem that is entirely unrelated to a unit system. In my opinion the only thing that a unit system needs is to have a metric, the ability to manage different dimensions, be able to convert between units of the same dimension, or correlate units to form new dimensions. It shouldn’t try to do anything else, but because it did it is crumbling under the weight of its own complexity.
Distinguishing between “absolute” and “relative” units, totally unnecessary, all lengths are the same. There’s are complications to handle things like temperatures, but quantity_point or affine spaces was never the solution, it’s s a make shift raft, it got this far but you have to recognize that the raft is sinking and you are unable to patch this hole. It’s not entirely your fault, ISO 80000 has really dropped the ball on this one, and anyone in good faith trying to follow it to the letter was always going to get a bloody nose.
Any design that was ever going to stand a chance would have to recognize this.



From: Std-Proposals <std-proposals-bounces_at_[hidden]> On Behalf Of Mateusz Pusz via Std-Proposals
Sent: Wednesday, June 19, 2024 18:55
To: Arthur O'Dwyer <arthur.j.odwyer_at_gmail.com>
Cc: Mateusz Pusz <mateusz.pusz_at_[hidden]>; std-proposals_at_[hidden]
Subject: Re: [std-proposals] On the standardization of mp-units P3045R1

Hi Arthur,

I would not like to start new discussions here until we address the issues discussed before. However, I will briefly answer some of your concerns here. If you would like to discuss this in more detail, could you please open a new discussion thread on the reflector?

It is fine to decide that we do not want units in the Standard Library. But please decide that now and not five years from now when all the contributors to the proposals will spend hundreds of hours working on it. This is what I asked a few meetings ago in LEWG, and the answer was to go ahead, as it seems that we want it standardized. The authors spent a lot of time writing proposals already since then.

I could argue that every measurement can (but does not have to) be modeled as a quantity point, even for length and time. For length, you read the value on the ruler or the odometer (notice that you do not have to zero the ruler or the odometer to read the value). For time, you read the value of a stopwatch. If you want to know how much time has passed or how long something is, you subtract the read value from another value read in a different measurement. However, it does not mean we do not need quantities. If we want to find out how different readouts differ, we subtract them to get a quantity.

> Can the type system actually help us solve this problem at all? My impression is that mp_units doesn't help us solve this problem.

Sure! This is the solution with mp-units:

inline constexpr struct altitude_above_sea_level final : quantity_spec<isq::altitude> {} altitude_above_sea_level;
inline constexpr struct altitude_above_terrain final : quantity_spec<isq::altitude> {} altitude_above_terrain;
inline constexpr struct height_of_the_terrain_above_sea_level final : quantity_spec<isq::height> {} height_of_the_terrain_above_sea_level;

QuantityOf<height_of_the_terrain_above_sea_level> auto
get_height_of_the_terrain_above_sea_level(QuantityOf<altitude_above_sea_level> auto asl,
                                          QuantityOf<altitude_above_terrain> auto aat)
{
  return height_of_the_terrain_above_sea_level(asl - aat);
}

int main()
{
  using namespace mp_units::si::unit_symbols;

  quantity asl = altitude_above_sea_level(1340 * m);
  quantity aat = altitude_above_terrain(340 * m);
  quantity res1 = get_height_of_the_terrain_above_sea_level(asl, aat);
  // quantity res2 = get_height_of_the_terrain_above_sea_level(aat, asl); // Compile-time error
  std::cout << res1 << "\n";
}

https://godbolt.org/z/193afPe4K

śr., 19 cze 2024 o 18:13 Arthur O'Dwyer <arthur.j.odwyer_at_[hidden]<mailto:arthur.j.odwyer_at_[hidden]>> napisał(a):
On Wed, Jun 19, 2024 at 11:29 AM Mateusz Pusz via Std-Proposals <std-proposals_at_[hidden]<mailto:std-proposals_at_[hidden]>> wrote:
I have an alternative proposal.

Let's consider adding `alternative(Reference)` and `relative(Reference)` modifiers that will influence how:

- multiply syntax works
- limit invalid use cases for quantity and quantity_point.

Here are the main points of this new design:
1. All references/units that do not specify point origin (are not offset units) would be considered `relative` by default. This means that `42 * m` will create a `quantity` and would be the same as calling `42 * relative(m)`.
2. Multiply syntax could be extended to allow quantity_point creation with the `42 * absolute(m)` syntax. This will provide an implicit zeroth point origin.
3. For units that specify a point origin (kelvin, degree_Celsius, and degree_Fahrenheit), the user would always need to specify a modifier. This means that:
  - `4 * deg_C` does not compile
  - `4 * relative(deg_C)` creates a `quantity`
  - `4 * absolute(deg_C)` creates a `quantity_point`
4. Constrain constructors of quantity or quantity_point to require the same:

quantity q1(4, m); // OK
quantity q2(4, relative(m)); // OK
quantity q3(4, absolute(m)); // Compile-time error
quantity_point qp1(4, m); // OK
quantity_point qp2(4, relative(m)); // Compile-time error
quantity_point qp3(4, absolute(m)); // OK

quantity q4(4, deg_C); // Compile-time error
quantity q5(4, relative(deg_C)); // OK
quantity q6(4, absolute(deg_C)); // Compile-time error
quantity_point qp4(4, deg_C); // Compile-time error
quantity_point qp5(4, relative(deg_C)); // Compile-time error
quantity_point qp6(4, absolute(deg_C)); // OK

Please note the above would also apply to Kelvin and Fahrenheit.

Does it solve the issue discussed here?

FWIW, I think:
- The WG21 discussion process might be good for mp_units' health, but ultimately I don't think mp_units belongs in the STL.
- (As Mateusz knows,) personally I'm enamored of absl::Duration's minimalist design<https://abseil.io/docs/cpp/guides/time#time-durations>, where you have strong typing for the dimension algebra (which is irreducible complexity) but the library makes a sensible-in-context choice of units (e.g. seconds) and representation types (e.g. `double`) and your program is happy with that choice or else you pick a different library to use. As with type-erasure types, there are just too many "knobs" to make something that everyone will be happy with. (That's how we ended up with `std::function` and `std::copyable_function`, as well as another ~3 standard type-erasure types.)
- The idea of affine spaces is indeed key — it is indispensable. Almost all of the "new" ideas in this thread have been simply reinventing or renaming the two fundamentals `quantity` (delta, relative) and `quantity_point` (absolute).
- IMO, Mateusz' informally proposed names `relative` and `absolute` are not good, because they are exactly the opposite of how I'd explain them to a layman. A temperature delta of 4 degrees (C/K) is absolute; it has a physical meaning. Now, if you take that delta relative to some arbitrary origin — e.g. the freezing point of water — then you get the temperature reading on a human thermometer (the thing Mateusz informally proposed to call `absolute`, even though the way we got it was to add our delta relative to something else). Now, personally I wouldn't be opposed to calling deltas by the name `delta` somehow — e.g. `4 * delta_m` — but I don't think that buys any clarity.
- In fact, temperature (like calendar) seems to be special, in that we have several human-invented origin points (epochs) relative to which you might want to represent a temperature (date). We absolutely do not have that for e.g. meters, or (in the physical realm) seconds.
- But meters and seconds are special because they were invented specifically to measure deltas in spacetime. They're the only two units that work that way. Most other units seem to measure "quantity_points" by default: This object weighs absolutely 4kg, not "4kg more than a weightless object." I'm applying absolutely 4Nm of torque (or, hmm, is it really that I'm applying "a delta of 4Nm more than there would have been without my input"?)
- It's not intuitively 100% obvious to me whether we have a natural "origin" for kilograms (i.e. "this object's mass is absolutely 4kg") or whether that's just an abuse of notation (like saying "this event took absolutely 42 seconds" when what you mean was "the delta between this event's start and end was 42 seconds"). If we understood that point, it might be easier to talk about the whole system.

Finally, since I'm here, I'll mention my one big concern with mp_units' design even though it's new to the thread AFAIK:
- I think anyone converting units is already in a state of sin, so I'm not too worried about that part. And I like the (high-level) design for preventing accidental conversions of dimension. I'm very concerned, though, with the idea of managing what might be called "soft" dimensions: altitude-above-sea-level and altitude-above-terrain are measured in exactly the same dimension (length), the same units (meters), in the same direction (height), even with a very similar name (altitude), in fact we sometimes want to do mixed-mode math on them (the one minus the other equals the height of the terrain above sea level)... but still, it is catastrophic to confuse them. Can the type system actually help us solve this problem at all? My impression is that mp_units doesn't help us solve this problem. (Although it does help us with other problems, such as mixing up altitude with rate-of-descent, because the dimensions/units are different in that case.) It's not clear to me whether this indicates "we have half a solution, which indicates we should keep searching for the whole solution," or merely "that's a second problem entirely; the first solution is still worthwhile for the first problem."

But I don't think any of this is pro or con "should mp_units go into the STL?". I'm pretty firmly against its going into the STL either way. This designy stuff is all about "can we come up with a minorly tweaked design that improves mp_units?" and "can we come up with a majorly different design that is self-consistent at all, or does every alternative design run into serious problems?" (I suspect the answer to the former is "no, not really" and the answer to the latter is "yes, plausible alternative designs are a dime a dozen.")

my $.02,
–Arthur

Received on 2024-06-19 18:50:07