C++ Logo

std-proposals

Advanced search

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

From: Charles R Hogg <charles.r.hogg_at_[hidden]>
Date: Tue, 18 Jun 2024 14:20:27 -0400
On Tue, Jun 18, 2024 at 1:53 PM Tiago Freire <tmiguelf_at_[hidden]> wrote:

> > A basic design principle for a units library is that the result of a
> computation shouldn't conjure up any units not mentioned in the inputs.
>
>
>
> I disagree. mp_units does exactly the same thing, the only difference is
> that you are hiding the units behind CTAD, but your quantity needs a unit.
>

I admit that I have less working familiarity with mp-units than Au, simply
because I use the latter in my day to day work. But could you please give
a more explicit example where the result of an mp-units computation
conjures up units that weren't mentioned in any of the inputs? I don't
know any, but, again --- I'm less familiar.


> The exact same could be done with this library except I chose to be
> explicit here for simplicity sake, “unit::kelvin” is not the interesting
> bit here, it is the fact that a temperature in Celsius is a different type
> of quantity, one where the math works differently and forces you to be
> explicit about converting to a quantity type that follows familiar
> arithmetic rules, one where there is no ambiguity or surprises of what
> things mean, one where you can’t have “delta celsius” because that is what
> causes problems.
>

"a different type of quantity, one where the math works differently and
forces you to be explicit about converting to a quantity type that follows
familiar arithmetic rules"

This sounds like a really useful concept. Have you given it a name?

If not, may I suggest "quantity point"?


> I’m not trying to sell you my library, I’m just trying to sell you its
> better features.
>
>
>
>
>
> > When humans subtract two temperatures in Celsius, they invariably write
> the result in Celsius. If we're writing software for humans, we should
> find a way to meet this bar.
>
>
>
> I would like perhaps to sell you that this humans would be mostly
> scientists or at least someone with basic knowledge of engineering, and
> would be familiar with the concept of Kelvin.
>
> I myself as an engineer when subtracting 2 temperatures in Celsius, I
> always write down Kelvin, because it is Kelvin not Celsius.
>

"When humans subtract two temperatures in Celsius, they invariably write
the result in Celsius."
"I myself as an engineer when subtracting 2 temperatures in Celsius, I
always write down Kelvin"

First off: I did *not* mean to imply that you're not human for not writing
the result in Celsius! :) There's a great diversity of ways to be human,
and I'd like to acknowledge and celebrate that.

I think it's fine to write the result in Kelvins if you like, but please
recognize that in so doing, you are performing a unit conversion. It's a
very easy conversion, but it is a conversion nonetheless: you have
converted the temperature difference from Celsius to Kelvins.

If there were no such thing as a difference of degrees Celsius, then heat
capacities would never be represented as "Joules per kilogram degree
Celsius" --- and yet, they very commonly are.

I think it is rather easier to understand this if I write the
> representation of the units in a different notation:
>
> For example, what do we mean by 1.6m?
>
> Well we have:
>
> 1. a unit “m” which represents a physical reference, in this case the
> length light in a vacuum travels in 1/299792458 of a second
> 2. a radical 1.6
> 3. And the relationship between the radical and the unit is one of
> multiplication 1.6 * m. The literal meaning being “you know the lenght
> light in a vacuum travels in 1/299792458 of a second? It is that ×1.6”
>
> This can be expressed by the following equation:
>
>
>
> Lm(x) = x⋅G
>
> Where:
>
> Lm(x) - Is the lenght as expressed by x in meters (ex. as expressed in
> Lm(1.6), i.e. what 1.6m means)
>
> x - Is the associated value (ex. the value 1.6)
>
> G - Is a constant representing the reference gauge (ex. the lenght of a
> meter, i.e. length light in a vacuum travels in 1/299792458 of a second)
>
>
>
> But degrees Celsius works like this:
>
> T°C(x) = T0 + x⋅R
>
> Where:
>
> T°C(x) - Is the temperature as expressed by x in degrees celcius
>
> x - Is the associated value
>
> T0 - Is a constant offset (ex. the temperature at which below water
> freezes under specific conditions)
>
> R - Is the reference gauge (ex. gauge such that at the temperature water
> boils under specific conditions, x marks 100)
>
>
>
> The reason why you can’t multiply degrees Celsius by simply multiplying
> the radical is because:
>
> A⋅T°C(x) = A⋅(T0 + x⋅R) = A⋅T0 + A⋅x⋅R = (A-1)⋅T0 + T0 + A⋅x⋅R = T°C(A⋅x)
> + (A-1)⋅T0
>
>
>
> And that last +(A-1)⋅T0 term is not for show.
>
>
>
> And this is what subtracting 2 temperatures is degrees Celsius looks like:
>
> T°C(A) - T°C(B) = (T0 + A⋅R) - (T0 + B⋅R) = T0 + A⋅R - T0 - B⋅R = A⋅R - B⋅R
> = (A - B)⋅R = T°C(A - B) - T0
>
>
>
> It’s the arithmetic that works differently, it has nothing to do with
> quantities or quantity points.
>

This approach is what we might call the "arbitrary functional forms"
approach. It's very ambitious for a units library, and there's a lot to
like about it. I believe that in principle, there are use cases that this
approach could handle that the quantity / quantity-point approach couldn't
(although I don't know any off the top of my head).

However, it seems to me that it has a defect: there are also cases that the
quantity / quantity-point approach can handle, that this one can't. One
example is the example earlier in the thread, which I'll decline to repeat
in detail. Let's focus in on the part that I think would be harder for
your approach. Suppose there's some climate scientist communicator who's
using C++, and wants a reliable way to convert temperature change
thresholds from Celsius to Fahrenheit. Suppose also that we take your
preferred design approach in the standard units library. What are you
going to tell this person to write?

Cheers,
Chip



> *From:* Charles R Hogg <charles.r.hogg_at_[hidden]>
> *Sent:* Tuesday, June 18, 2024 19:06
> *To:* std-proposals_at_[hidden]
> *Cc:* Mateusz Pusz <mateusz.pusz_at_[hidden]>; Tiago Freire <
> tmiguelf_at_[hidden]>; Chip Hogg <chogg_at_[hidden]>; Anthony Williams <
> anthony_at_[hidden]>; Johel Ernesto Guerrero Peña <
> johelegp_at_[hidden]>
> *Subject:* Re: [std-proposals] On the standardization of mp-units P3045R1
>
>
>
>
>
>
>
> On Tue, Jun 18, 2024 at 11:56 AM Tiago Freire via Std-Proposals <
> std-proposals_at_[hidden]> wrote:
>
> Ok.
>
> This is what I would do:
>
>
>
> //different library
>
> unit::cubic_metre Volume {1.0};
>
> unit::celcius Temperature{28.0};
>
>
>
> auto n_{0.04401 * unit::kilogram{} / unit::mol{}};
>
> auto R_boltzman{8.314 * unit::newton{} * unit::metre{} / unit::
> kelvin{} / unit::mol{}};
>
> unit::kilogram mass {40.0};
>
>
>
> //unit::kilopascal Pressure = R_boltzman * Temperature * mass / n_
> / Volume; //fails to compile
>
> unit::pascal Pressure = R_boltzman * unit::kelvin{Temperature} *
> mass / n_ / Volume; //explict is good
>
> std::cout << Pressure.value() << std::endl; //don't actually have
> print facilities
>
>
>
>
>
> In this example things like unit::kilogram are an alias to a template
> specialization of unit::Unit, that takes in a template parameter the gauge
> properties of the unit, this would be analogous to mp_units::quantity.
>
> unit::celcius however is a different type of unit called
> unit::Offset_Unit, for which mp_units has no analog (but if it had it would
> be something like offset_quantity), it is still a type of “quantity” just
> it is limited in the math that you can do. And a difference between 2
> temperatures in Celsius is a temperature in Kelvin, that is how it should
> work.
>
>
>
> Who invited "kelvins"?
>
>
>
> A basic design principle for a units library is that the result of a
> computation shouldn't conjure up any units not mentioned in the inputs.
> This keeps the library easy to reason about, and is more in line with
> users' expectations. When humans subtract two temperatures in Celsius,
> they invariably write the result in Celsius. If we're writing software for
> humans, we should find a way to meet this bar.
>
>
>
> By the way: suppose one of these humans takes your temperature-in-kelvins,
> and converts it back to Celsius, because that is what humans do. Can I
> assume that your proposed library would produce the correct result?
>
>
>
> This library has no “quantity_point” analog, because one is not needed.
>
>
>
> Great! Getting rid of quantity point would reduce the number of primary
> user-facing template types from 2 to 1, simplifying the library and making
> it easier to learn and use.
>
>
>
> Of course, to get rid of complexity, we need to make sure that it's
> "accidental" complexity (i.e., complexity specific to the solution, but not
> intrinsic to the underlying problem domain). Otherwise, if it's
> "essential" complexity (i.e., intrinsic to the underlying domain), then
> removing it would leave us unable to handle certain real-world use cases.
> Before I get cracking on the PR to remove quantity point, we'd better make
> sure about which category it's in! I can see you've handled the example
> you've provided (although I'm a little wary of the celsius type
> auto-converting to unmentioned kelvins in other use cases). How about this
> other example?
>
>
>
> ----- (begin example) -----
>
>
>
> Imagine you have been given full control of the design of the standard C++
> quantities library. All of its interfaces and types will be exactly as you
> prefer. Please show how the following use cases will look in this standard
> quantities library.
>
> 1. A user has a sensor which measures the outside temperature as 5 degrees
> celsius. Write the C++ source code that converts this to a temperature in
> Fahrenheit using your standard quantities library.
>
> 2. A user is modeling the climate effects of a catastrophic global
> temperature rise of 5 degrees celsius. Write the C++ source code that
> converts this temperature rise to Fahrenheit using your standard quantities
> library.
>
>
>
> ----- (end example) -----
>
>
>
> Fortunately, you don't need to go and write the actual library; you only
> need to imagine and write the source code that you would like for end users
> to use in each of these situations.
>
>
>
> So: what would that imagined source code look like?
>
>
>
> Cheers,
>
> Chip
>
>
>
>
>
>
>
>
>
>
>
>
>
> *From:* Mateusz Pusz <mateusz.pusz_at_[hidden]>
> *Sent:* Tuesday, June 18, 2024 16:51
> *To:* Tiago Freire <tmiguelf_at_[hidden]>
> *Cc:* std-proposals_at_[hidden]; Chip Hogg <chogg_at_[hidden]>;
> Anthony Williams <anthony_at_[hidden]>; Johel Ernesto
> Guerrero Peña <johelegp_at_[hidden]>
> *Subject:* Re: [std-proposals] On the standardization of mp-units P3045R1
>
>
>
> > I think there’s a better way to deal with this and I think I have
> provided a solution.
>
> > It didn’t go anywhere because you haven’t deemed a big enough problem to
> warrant consideration, and I didn’t press on the issue because I didn’t
> believe the design would have a chance to become part of the standard.
>
>
>
> This is not true. As I stated already, we are open to any feedback here
> and in other areas. We are also eager to refactor our proposal if the
> proposed solution is successful.
>
>
>
> To start a technical discussion, in this post
> https://github.com/mpusz/mp-units/discussions/552#discussioncomment-8435940,
> we asked you to provide a simple code example of how you would address a
> particular and narrow problem with your intended interface. Just type what
> users would have to type to solve the problem. We never got any solution
> from you. You stated that instead of working with us on this simple example
> or contributing to the mp-units repo, you prefer to reimplement your
> library https://github.com/tmiguelf/unit from scratch. You never came
> back to us with results, and there are no new commits in your library as
> well.
>
>
>
> If you implemented a solution on a side or have something new to share
> with us, please do it. If we find a better solution, we still have time to
> improve the proposal.
>
>
>
> Best
>
>
>
> Mat
>
>
>
> wt., 18 cze 2024 o 16:24 Tiago Freire <tmiguelf_at_[hidden]> napisał(a):
>
>
>
> > Tiago, some time has passed since your last complaint about the same
> problem. We invited you to our internal meeting, listened to your concerns,
> and discussed how we can improve here. As you know, the answer was not
> found at the meeting. Additionally, you stated that you don't want to work
> to contribute to our proposal and repository and that you will come back
> with a better interface soon. More info can be found here:
> https://github.com/mpusz/mp-units/discussions/552. Did you manage to find
> a better solution to this problem? If so we are open to rediscuss your
> solution whenever you are ready.
>
>
>
> Yes, as I have stated I already had an alternative that did this correctly
> 3 years ago. If I was the one designing it, Degrees Celsius should be
> defined as a different kind of unit where the arithmetic works differently
> and accounts for the fact that degrees Celsius are offset (and
> quantity_point is not the answer here). I think there’s a better way to
> deal with this and I think I have provided a solution.
>
> It didn’t go anywhere because you haven’t deemed a big enough problem to
> warrant consideration, and I didn’t press on the issue because I didn’t
> believe the design would have a chance to become part of the standard.
>
>
>
> But since it is being proposed to become part of the standard, I think it
> is a perfectly valid thing to ask these questions.
>
> If this is going to be part of my toolset, how are we supposed to deal
> with this?
>
> Do you agree with my observation that it was easier to do the wrong thing
> than to do the right thing?
>
> Can we change the design such that this is not an issue?
>
>
>
> Br,
>
> Tiago
>
>
>
>
>
> *From:* Mateusz Pusz <mateusz.pusz_at_[hidden]>
> *Sent:* Tuesday, June 18, 2024 15:55
> *To:* std-proposals_at_[hidden]
> *Cc:* Tiago Freire <tmiguelf_at_[hidden]>; Chip Hogg <chogg_at_[hidden]>;
> Anthony Williams <anthony_at_[hidden]>; Johel Ernesto
> Guerrero Peña <johelegp_at_[hidden]>
> *Subject:* Re: [std-proposals] On the standardization of mp-units P3045R1
>
>
>
> Hi,
>
>
>
> Tiago, some time has passed since your last complaint about the same
> problem. We invited you to our internal meeting, listened to your concerns,
> and discussed how we can improve here. As you know, the answer was not
> found at the meeting. Additionally, you stated that you don't want to work
> to contribute to our proposal and repository and that you will come back
> with a better interface soon. More info can be found here:
> https://github.com/mpusz/mp-units/discussions/552. Did you manage to find
> a better solution to this problem? If so we are open to rediscuss your
> solution whenever you are ready.
>
>
>
> For all other participants of this mailing list, here is a correct
> solution:
>
>
>
> #include <mp-units/ostream.h>
>
> #include <mp-units/systems/si.h>
>
> #include <iostream>
>
>
>
> using namespace mp_units;
>
>
>
> inline constexpr struct atmospheric_pressure final : named_unit<"atm",
> mag<101'325> * si::pascal> {} atmospheric_pressure;
>
>
>
> int main()
>
> {
>
> using namespace mp_units::si::unit_symbols;
>
>
>
> quantity Volume = 1.0 * m3;
>
> quantity_point Temperature(28.0 * deg_C);
>
> quantity n_ = 0.04401 * kg / mol;
>
> quantity R_boltzman = 8.314 * N * m / (K * mol);
>
> quantity mass = 40.0 * kg;
>
> quantity Pressure = R_boltzman * Temperature.in(K).quantity_from_zero()
> * mass / n_ / Volume;
>
> std::cout << Pressure.in(Pa) << "(" <<
> Pressure.in(atmospheric_pressure) << ")\n";
>
> }
>
>
>
> https://godbolt.org/z/E8bf51hKG
>
>
>
> Temperatures are tricky, and there is no good default here. People often
> mean either a point or a difference, depending on the context. In case
> anyone has an idea on how to improve, we are open to feedback.
>
>
>
> Best
>
>
>
> Mat
>
>
>
> wt., 18 cze 2024 o 15:30 Sebastian Wittmeier via Std-Proposals <
> std-proposals_at_[hidden]> napisał(a):
>
> How about the following scales? Are they also an issue?
>
>
>
>
>
> - Time (Calendar) relative to either anno domini or Unix time?
> - Position Coordinate relative to Greenwich?
> - Electric Potential relative to earth potential?
> - pH, pKa, pKb scales relative to a neutrality of 7?
> - Decibels, phon and sone relative to threshold of human hearing?
> - Pressure (hydraulic or blood) relative to atmospheric pressure?
> - Altitude relative to sea level?
>
> -> For pressure and altitude there are lots of other scales, e.g. used
> in aviation
> - Richter scale relative to detectable earthquakes?
> - Beaufort relative to calm wind instead of zero wind?
> - Borg physical exertion not starting at zero?
>
>
> --
> Std-Proposals mailing list
> Std-Proposals_at_[hidden]
> https://lists.isocpp.org/mailman/listinfo.cgi/std-proposals
>
>
>
> wt., 18 cze 2024 o 15:44 Tiago Freire via Std-Proposals <
> std-proposals_at_[hidden]> napisał(a):
>
> I understand what the problem is, that is why I’m bringing it forward.
>
> My concerned is that I haven’t written any code that anyone wouldn’t have
> written and got the wrong answer.
>
>
>
> > An absolute value in the paper is a quantity_point, a possibly relative
> value is a quantity.
>
>
>
> Which is a perspective, not convinced that it is the right thing. But That
> also poses the question, volume is also an absolute value, so is the mass,
> pressure, etc..
>
>
>
> Which means that the right way to write it would be this:
>
> ```
>
> quantity_point Volume {1.0 * m*m*m};
>
> quantity_point Temperature {si::ice_point + 28.0 * deg_C};
>
> quantity_point n_{0.04401 * kg / mol};
>
> quantity R_boltzman = 8.314 * N * m / (K * mol);
>
> quantity_point mass {40.0 * kg};
>
> quantity_point P = R_boltzman * Temperature * mass / n_ / Volume;
>
> std::cout << Pressure << std::endl;
>
> ```
>
>
>
> But this doesn’t compile because quantity_point can’t math.
>
> In order to get it to compile you would have to do this instead:
>
> ```
>
> quantity_point Pressure = quantity_point{0.0*Pa} + R_boltzman *
> (Temperature - mp_units::si::absolute_zero) * (mass -
> quantity_point{0.0*kg}) / (n_ - quantity_point{0.0*kg / mol}) / (Volume -
> quantity_point{0.0* m*m*m});
>
> ```
>
> Which doesn’t even module the problem properly because the values in
> PV=nRT are supposed to be absolute values, not deltas.
>
>
>
> Hence it raises the question, doing what it seems obvious is the wrong
> thing (thus questionably safe), and doing the right thing is kind of hard
> (thus questionably user-friendly). But that what is expected as the correct
> way to use it.
>
>
>
>
>
> *From:* Std-Proposals <std-proposals-bounces_at_[hidden]> *On Behalf
> Of *Sebastian Wittmeier via Std-Proposals
> *Sent:* Tuesday, June 18, 2024 15:03
> *To:* std-proposals_at_[hidden]
> *Cc:* Sebastian Wittmeier <wittmeier_at_[hidden]>
> *Subject:* Re: [std-proposals] On the standardization of mp-units P3045R1
>
>
>
> You are specifically talking about
>
>
>
>
> https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2024/p3045r1.html#potential-surprises-while-working-with-temperatures
>
>
>
>
>
> Discussing the difficulty, when to use a difference in temperature or an
> absolute temperature.
>
>
>
> An absolute value in the paper is a quantity_point, a possibly relative
> value is a quantity.
>
>
>
>
>
> If I understand correctly, in the current paper to initialize and use
> absolute temperatures
>
>
>
> quantity_point qp2 = (isq::Celsius_temperature(28.0 * deg_C)).in(K)
>
> and
>
> qp2.quantity_from_zero()
>
>
>
>
>
> would have to be used instead of
>
>
>
> quantity Temperature = (28.0 * deg_C).in(K);
>
>
>
> The paper also says
>
>
>
> "We have added the Celsius temperature quantity type for completeness and
> to gain more experience with it. Still, maybe a good decision would be to
> skip it in the standardization process not to confuse users."
>
>
>
>
>
>
>
>
>
>
>
>
>
> -----Ursprüngliche Nachricht-----
> *Von:* Sebastian Wittmeier <wittmeier_at_[hidden]>
> *Gesendet:* Di 18.06.2024 14:42
> *Betreff:* AW: [std-proposals] On the standardization of mp-units P3045R1
> *An:* std-proposals_at_[hidden];
>
> Hi Tiago,
>
> where does this difference of 11x come from?
>
> The temperature with 28°C vs. 301K?
>
>
> -----Ursprüngliche Nachricht-----
> *Von:* Tiago Freire via Std-Proposals <std-proposals_at_[hidden]>
> *Gesendet:* Di 18.06.2024 14:28
> *Betreff:* [std-proposals] On the standardization of mp-units P3045R1
> *An:* std-proposals_at_[hidden];
> *CC:* Tiago Freire <tmiguelf_at_[hidden]>;
>
> Hi, I will be participating in St. Louis.
>
> And one of the papers that interested me was P3045R1, unfortunately I may
> or may not be on time to participate in this particular session.
>
>
>
> There’s this question that I would like an answer too, and I wonder if
> there is anyone who will be attending St. Louis who would be willing to
> make this question on my behalf:
>
>
>
>
>
>
>
> A lab worker puts in 40Kg of dry ice into a 1 cubic meter pressure tank
> rated for 10atm, they then vacuum the tank and seal it.
>
> As the CO2 warms up to room temperature (which at a specific date was
> 28°C) it evaporates, and eventually following the ideal gas law:
>
> PV=nRT
>
>
>
> Is this setup dangerous?
>
>
>
> Using mp-units (with the exact same design as the one being proposed for
> standardization) to solve this problem:
>
>
>
> ```
>
> quantity Volume = 1.0 * m*m*m;
>
> quantity Temperature = (28.0 * deg_C).in(K);
>
> quantity n_ = 0.04401 * kg / mol;
>
> quantity R_boltzman = 8.314 * N * m / (K * mol);
>
> quantity mass = 40.0 * kg;
>
> quantity Pressure = R_boltzman * Temperature * mass / n_ / Volume;
>
> std::cout << Pressure << std::endl;
>
> ```
>
>
>
> We get the following result:
>
> `211581 N/m2`
>
> (=211.581kPa = 2,09 atm)
>
> But the correct answer is actually: 2275.629kPa = 22.5 atm
>
> (11 time s higher than what mp-units calculated)
>
>
>
> How is this considered a design feature and not a bug? (note that other
> similar libraries don’t have this problem)
>
> And how do the authors think this design choice impacts on safety and
> user-friendliness?
>
>
>
>
>
> Thanks.
>
>
>
>
>
> -- Std-Proposals mailing list Std-Proposals_at_[hidden] https://lists.isocpp.org/mailman/listinfo.cgi/std-proposals
>
>
>
> --
> Std-Proposals mailing list
> Std-Proposals_at_[hidden]
> https://lists.isocpp.org/mailman/listinfo.cgi/std-proposals
>
> --
> Std-Proposals mailing list
> Std-Proposals_at_[hidden]
> https://lists.isocpp.org/mailman/listinfo.cgi/std-proposals
>
>

Received on 2024-06-18 18:20:44