Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update alternatives matrix #147

Merged
merged 12 commits into from
Jul 21, 2023
Merged

Update alternatives matrix #147

merged 12 commits into from
Jul 21, 2023

Conversation

chiphogg
Copy link
Contributor

@chiphogg chiphogg commented Jul 11, 2023

Our alternatives matrix is long overdue for a refresh.

The first core change is to explicitly list each library, indicate which
version we evaluated, and link to it. We also say a few words about why
that library made our shortlist. Along this vein, we add a new library,
bernedom/SI, to the list. It's an impressively popular library (400
GitHub stars!) which didn't get included when we released the library
simply because it wasn't on my radar: at the time, it didn't have the
dimensional-analysis tag which most of the others had, so it didn't
show up in my searches. This fixes #108.

We also clarify for the first time that the rows in our "big" matrix are
ordered (very roughly) by importance, which is a critical piece of
context for the reader.

We add several new rows to our comparison, namely:

  • Unit-aware I/O
  • Unit-aware math
  • Linear algebra
  • Physical constants

Next, I updated the results for mp-units for the first time since its
major 2.0 API upgrade. mp-units improved significantly, and those
improvements were concentrated in the more important categories, such as
"Unit Safety" and "Composability". (It also regressed in "Macros", but
that's the least important category.)

Finally, I made a few tweaks for previous assessments that I couldn't
really justify in retrospect.

@mpusz
Copy link

mpusz commented Jul 11, 2023

  1. Compiler Error Readability
    • you could mention a new expression template syntax
    • maybe with expression templates the readability is better? 😉
  2. Low Friction
  3. Composability
    • mp-units can compose units, prefixes, dimensions, and quantity types
  4. "User-defined literals (UDLs)" should probably be renamed to "Construction helpers"
    • using UDLs is actually considered a bad practice here
  5. Kind Types
    • I think that this category should be split into two separate rows: "separation of quantities of the same dimension but different kinds" and "hierarchy of quantities of the same kind" as those features are somehow orthogonal, and could be added in isolation, and may have different importance
  6. Units as types
    • I am not sure what you mean here
    • Au mentions "Can form instances and do arithmetic"
    • in mp-units you can do equations on units, dimensions, quantity specs, and quantities

Categories that are possibly missing:

This gives us much more room for the table.
@chiphogg chiphogg added the release notes: 📝 documentation PR affecting library documentation label Jul 12, 2023
@chiphogg
Copy link
Contributor Author

Thanks for the thorough review comment! I've tried to address all of the points.

  1. Compiler Error Readability

    • you could mention a new expression template syntax
    • maybe with expression templates the readability is better? wink

What a blind spot for me: I forgot to check the first two tables! I was only focused on the main one. I hadn't noticed that the new update drops the explicit dimension parameter from the quantity template --- very nice improvement. I've upgraded mp-units to "good" and dropped our own "best" down to "good".

  1. Low Friction

It's a nice improvement, since now there's just one file to include per system. I'll take the "x" off, as I think this is now in a similar place to the bernedom/SI entry.

From a big picture perspective, I think the row as a whole is in a good place.

  • nholthaus should be "good", because the library excels at a low-friction experience. I've used it before, and it's so easy to pick it up and get going!
  • Au should be "best", because we have all of the same advantages as nholthaus here, but also a simpler and shorter namespace structure and more configurability.
  • Boost should be "poor", because the library is simply very hard to use. That's been my experience, and also the experience of every user I've talked to, including those who advocate it.
  • mp-units and SI are "middle ground" here. Clearly easier to use than Boost, but also clearly more friction than nholthaus.
  1. Composability

    • mp-units can compose units, prefixes, dimensions, and quantity types

Done.

  1. "User-defined literals (UDLs)" should probably be renamed to "Construction helpers"

    • using UDLs is actually considered a bad practice here

I don't know if I'd say it's a bad practice, but yeah --- as you've shown elsewhere, UDLs for quantities have a lot of drawbacks, and Quantity References are just straight-up better. I went with "Abbreviated construction" instead of "Construction helpers", since the abbreviated nature is I think really key to its benefits.

  1. Kind Types

    • I think that this category should be split into two separate rows: "separation of quantities of the same dimension but different kinds" and "hierarchy of quantities of the same kind" as those features are somehow orthogonal, and could be added in isolation, and may have different importance

I decided to put these in the explanation for this row. I think giving multiple rows to kinds would over-emphasize a feature whose usefulness I've come to see, but which I still think is marginal in the big picture.

  1. Units as types

    • I am not sure what you mean here
    • Au mentions "Can form instances and do arithmetic"
    • in mp-units you can do equations on units, dimensions, quantity specs, and quantities

I had overlooked this update --- nice catch! Fixed.

Categories that are possibly missing:

I think this is covered under "Explicit Systems of Measurement".

Thanks! Added.

I'm giving everyone a "fair" rating as a baseline here because basically any units library here would work out of the box with a linear algebra library that doesn't make strong assumptions. We had a patched version of Eigen that was like this at ATG, and I hope given the conversation in #70 that this kind of patch can start making its way upstream. There really wasn't too much patching required to get it to work. The overall user experience with this approach at ATG was... well, "fair". 🙂

  • pure dimensional analysis

I'm not sure when users would reach for this. We do support this as well in Au, but with our idioms, end users virtually never work with dimensions directly anyway.

Yes, definitely! This is one feature I'm really excited about adding in 0.4.0.

  • std::format support

Added a unit-aware I/O section near the top.

@mpusz
Copy link

mpusz commented Jul 13, 2023

I agree with the things you wrote and are which are not mentioned below explicitly. But I also have more comments on your answers 😉

I decided to put these in the explanation for this row

Unfortunately, your description has issues. By the "separation of quantities of the same dimension but different kinds" I meant things like frequency, activity, modulation rate, etc. We probably agree that 1 Hz + 1 Bq + 1 Bd should not work, and I think it is quite an important feature (maybe more important than quantities of the same kind like height and radius). Unfortunately, most or maybe even all libraries allow this operation even though ISO explicitly says it is not allowed. This is why I recommended having those two as separate categories.

I think this is covered under "Explicit Systems of Measurement".

I do not think so. Explicit systems of measurement are understood by people as having the imperial, USC, international, CGS, etc. But most libraries implement them either just as system of units or mix of units and quantities. System of Quantities is about modeling dependencies between quantities without mentioning units, numbers, representation types, etc, at all. See the official definition here: https://mpusz.github.io/mp-units/2.0/appendix/glossary/#system-of-quantities. mp-units, and possibly Boost.Units, are the only libraries that separate Systems of Quantities from Systems of Units. You can define them totally independently (i.e. for the Natural Units system) or base System of Units on the underlying System of Quantities like SI explicitly does (https://mpusz.github.io/mp-units/2.0/appendix/glossary/#si).

I'm giving everyone a "fair" rating as a baseline here because basically any units library here would work out of the box with a linear algebra library that doesn't make strong assumptions

That is actually wrong. My understanding is that besides mp-units (actually the code I have locally on my computer and not pushed yet) none of the libraries work at all with vector quanties. Using any of the libraries on the list, how would you construct angular momentum quantity from position vector and momentum? Note that both arguments are vector quantities so should be expressed with the linear algebra vector type. All of the libraries assume that agular_momentum = position_vector * momentum, but if you actually add an underlying type like (la_vector{1, 2, 3} * m) * (la_vector{3, 2, 1} * (kg * m / s)) how can it mathematically work? How would you obtain angular momentum as a result of those in AU?

I'm not sure when users would reach for this. We do support this as well in Au, but with our idioms, end users virtually never work with dimensions directly anyway.

Well, I didn't think about this as a really important feature as well, but some people from national labs asked me about it at ISO meetings some time ago, and also @bernedom asked for this explicitly during our last meeting.

Added a unit-aware I/O section near the top.

mp-units also supports "Unit labels available even without <iostream>". See:

It even works at compile-time 😉

@mpusz
Copy link

mpusz commented Jul 13, 2023

BTW, there are also a few points where I disagree with your assessment of AU (or maybe I just do not know enough about it).

  • Single header is nice, assuming that it has the same content every time and if it compiles fast. Allowing customization of the contents of this header is, in my opinion, a huge mistake. Consider two vendors using Au with different sets of units and a third one that tries to use the products provided by the former. The same header file in dependencies with different content is asking for problems.
  • I do not think that extensibility can be marked as good when you need to write multiple lines of code to add one quantity or unit. It is a huge effort on a larger scale. And macros are not welcomed either ;-)
  • Do you think that "No 'preferred' Rep" is a better solution than = double? I could remove the default in mp-units, but I am not so sure if users would be happy about it? Anyway, in V2 we promote 123 * m syntax so during the construction Rep is always explicitly provided by the user. = default is useful in the interfaces (i.e. void foo(quantity<si::metre, double> q) would be too verbose IMHO and double seems to be a good default based on the established practice in other libraries).
  • I am not sure if "sizeof()-friendly unit label representation" is a killer feature for embedded 😉, but in mp-units you can easily get the size of any unit at compile time as well (https://github.com/mpusz/mp-units/blob/master/test/unit_test/static/unit_symbol_test.cpp).

@mpusz
Copy link

mpusz commented Jul 13, 2023

Ohh, and according to my understanding, mp-units is probably the only one that provides a system of quantities where an angle is a strong dimension/quantity. The docs are TBD (they were provided for 0.8.0), but you can find more here:

@mpusz
Copy link

mpusz commented Jul 14, 2023

I just thought of possible additional rows to the comparison table:

  • basic math on quantities (abs, floor, ceil, round, hypot, pow, sqrt, cbrt, exp)
  • trigonometric functions for angular quantities (could also extend already existing "Angles" row as an additional criteria for comparison)
  • one of my users contributed random generators for quantities claiming it is important for their domain as well

You can find all of the above in: https://github.com/mpusz/mp-units/tree/master/src/utility/include/mp-units.

- Enumerate more I/O features of mp-units
- Add placeholder row for unit-aware math
- Simplify "Kinds" definition
- Mention Dimensions in Units-as-types
@chiphogg
Copy link
Contributor Author

Thanks for another thorough review!

A good thing to keep in mind is that this page is not the internet's authoritative comparison of C++ units libraries; it's merely the comparison from the point of view of Au, and of myself as its primary author. This means that relative to others, we'll emphasize some things we think are underappreciated (unit-safe APIs; composability; migration helpers; embedded friendliness; ZERO; etc.), and de-emphasize things we find less important ("Kind" APIs; explicit systems of measurement; etc.).

I think it'd be great to see more comparison matrices from other units libraries. Of course, each one would have somewhat different emphases according to its values. But I expect a clear picture of the strengths, weaknesses, and other attributes of each library would emerge from comparing these comparisons, as it were. This would be more valuable for end users than any one comparison table could be.

Having said that, I'll go through your review comments in chronological order (and thanks again for them!).

I agree with the things you wrote and are which are not mentioned below explicitly. But I also have more comments on your answers wink

I decided to put these in the explanation for this row

Unfortunately, your description has issues. By the "separation of quantities of the same dimension but different kinds" I meant things like frequency, activity, modulation rate, etc. We probably agree that 1 Hz + 1 Bq + 1 Bd should not work, and I think it is quite an important feature (maybe more important than quantities of the same kind like height and radius). Unfortunately, most or maybe even all libraries allow this operation even though ISO explicitly says it is not allowed. This is why I recommended having those two as separate categories.

I think preventing 1 Hz + 1 Bq + 1 Bd from compiling is a "nice-to-have". Distinguishing same-dimension-same-magnitude types is hard to do without adding friction for legitimate use cases, such as adding the results of intermediate computations --- which may produce something like meter * hertz / second --- to an acceleration in meters / squared(second). I also haven't seen evidence that same-dimension-same-magntiude errors are anywhere near as common and pernicious as "right dimension wrong units" errors, the overwhelmingly most important category. So from my point of view, giving this nice-to-have category more than one row would be an over-emphasis.

To address your comments on the wording of the explanation text, I clarified and simplified it. By "kind", we mean "any distinction finer than same-dimension-same-magnitude".

Now, to be clear, I think the new 2.0 syntax of mp-units has by far the most exciting "kind" solution I've seen. It looks very likely to minimize the "cost" side of the equation, while delivering all of the benefits. If (as I hope and expect) practical experience proves it out, I think it's likely I'll eventually try to figure out a way to bring the same kind of feature into Au, and turn one of our orange boxes blue. 🙂 Even then, though, I doubt I'd give it more than one row.

I think this is covered under "Explicit Systems of Measurement".

I do not think so. Explicit systems of measurement are understood by people as having the imperial, USC, international, CGS, etc. But most libraries implement them either just as system of units or mix of units and quantities. System of Quantities is about modeling dependencies between quantities without mentioning units, numbers, representation types, etc, at all. See the official definition here: https://mpusz.github.io/mp-units/2.0/appendix/glossary/#system-of-quantities. mp-units, and possibly Boost.Units, are the only libraries that separate Systems of Quantities from Systems of Units. You can define them totally independently (i.e. for the Natural Units system) or base System of Units on the underlying System of Quantities like SI explicitly does (https://mpusz.github.io/mp-units/2.0/appendix/glossary/#si).

The "measurement" in "Explicit systems of measurement" is intentionally a more generic term. It covers systems of quantities, systems of units, and systems of whatever else may be useful. The question this row answers is: do we allow the simultaneous representation of measurements which may have incompatible ideas about "which dimensions exist", or do we not?

I find it very hard to articulate why an end user would evaluate a units library separately based on explicit-systems-of-units support and explicit-systems-of-quantities support. I think the bar for making the case to consider them separately would be to describe realistic library designs in each of the four quadrants --- "yes/no" on explicit systems of "units/quantities" --- or, if any quadrant is empty, to explain why.

That said, and just to be clear ahead of time, I'd probably need a great deal of convincing to actually put separate rows here, even once I do understand the distinction. "Explicit systems" (generically) is a pretty clear tradeoff: you get more flexibility at the cost of a steeper learning curve. With this many rows, we're probably risking decision fatigue for the reader as it is.

I'm giving everyone a "fair" rating as a baseline here because basically any units library here would work out of the box with a linear algebra library that doesn't make strong assumptions

That is actually wrong. My understanding is that besides mp-units (actually the code I have locally on my computer and not pushed yet) none of the libraries work at all with vector quanties. Using any of the libraries on the list, how would you construct angular momentum quantity from position vector and momentum? Note that both arguments are vector quantities so should be expressed with the linear algebra vector type. All of the libraries assume that agular_momentum = position_vector * momentum, but if you actually add an underlying type like (la_vector{1, 2, 3} * m) * (la_vector{3, 2, 1} * (kg * m / s)) how can it mathematically work? How would you obtain angular momentum as a result of those in AU?

I don't see how it can be "wrong", when the reason I gave this rating is based on our experience doing this in production for several years at Uber ATG. We used strong types with (homogeneous!) units for vectors and matrices, where the vector quantities were things like position, velocity, and acceleration.

This was an "algebra-on-units" solution, because that was all we had at the time. We hadn't yet learned about the "units-on-algebra" solution or why it is superior. That's why I'm rating it as "fair", not "good". It's also true that most or all linear algebra libraries would need some patching to get non-trivial use cases to work, but we know from experience that the patches aren't that onerous for most features. Since those patches would benefit each library equally, I'm rating them all as "fair", except for mp-units which has some exciting new ideas for how to go beyond.

By the way, now that I've clarified that I was talking about an "algebra-on-units" solution, note that your example was spelled in a "units-on-algebra" style. If we translate it to "algebra-on-units", it looks more like la_vector{1 * m, 2 * m, 3 * m} * la_vector{3 * (kg * m / s), 2 * (kg * m / s), 1 * (kg * m / s)}. Assuming the vector multiplication is the cross product --- an API choice to which I would have tremendous objections, for what it's worth 😁 --- then this should produce an angular momentum "vector" without issue.

I'm not sure when users would reach for this. We do support this as well in Au, but with our idioms, end users virtually never work with dimensions directly anyway.

Well, I didn't think about this as a really important feature as well, but some people from national labs asked me about it at ISO meetings some time ago, and also @bernedom asked for this explicitly during our last meeting.

Cool! I didn't know people needed this. I decided to fold it into the units-as-types section near the bottom. I explicitly listed the support from both mp-units and Au for units and dimensions.

Added a unit-aware I/O section near the top.

mp-units also supports "Unit labels available even without <iostream>". See:

It even works at compile-time wink

Thanks for calling it out! Added.

BTW, there are also a few points where I disagree with your assessment of AU (or maybe I just do not know enough about it).

Thanks! It's hard for me to see beyond my own perspective, so I'm grateful that you're sharing yours.

  • Single header is nice, assuming that it has the same content every time and if it compiles fast. Allowing customization of the contents of this header is, in my opinion, a huge mistake. Consider two vendors using Au with different sets of units and a third one that tries to use the products provided by the former. The same header file in dependencies with different content is asking for problems.

I don't understand how a customized single-header delivery is any worse than having the libraries depend on two different versions of the same library --- which is admittedly a very hard problem, but not one that has much to do with this delivery method. In fact, assuming the versions are the same, wouldn't it be strictly less bad? After all, the contents should be either identical or absent relative to the other file: there won't be any conflicting definitions.

(I will say that dependency management outside of a monorepo context is very much not my forte, so I could be missing something obvious.)

I'll also say that, given that we're offering a customizable single-file delivery, I'm really glad that we made a manifest comment part of it from the very beginning. This comment makes it clear at a glance which precise version was used to generate the file, whether it has <iostream> support included, and which specific units were included. If there does turn out to be some special problem caused by customizable single files, this should at least make it much easier to fix.

  • I do not think that extensibility can be marked as good when you need to write multiple lines of code to add one quantity or unit. It is a huge effort on a larger scale. And macros are not welcomed either ;-)

The reason I'm fine with the multi-line setup is that I don't expect new unit definition to be a major part of most users' workflow. Most missing units should be brought into Au itself via PR, so as time goes on, I expect the units will tend to already be present more and more. When users do need to define their own named units, they'll typically do so only once per project per unit: it's not part of the normal workflow. And of course, for unnamed units, they can simply define them inline in a single line: e.g., constexpr auto trinches = inches * mag<3>();.

So, sure, it may be a significant effort on a larger scale, but I don't think a use case for that "larger scale" really exists.

I also think readability matters more than writability for unit definitions. And I'm not a fan of the readability of a sequence of positional arguments, as one sees in most (all?) unit definition macros. In fact, come to think of it, I'd even feel more confident about writing a unit definition in Au's style than with a macro if I was forced not to look at the docs! I understand all the parts and I can reason about what they do. I can start with a single line definition, and then add the parts for whatever features I want, when I need them.

That said --- I definitely agree that a modern, minimum-C++20 implementation can give us the best of both worlds! You get more flexibility in your template parameters with NTTPs. Also, Concepts clarify constraints, cultivating callsite confidence. That's why I'm glad there's a library like mp-units that's willing to bite the bullet of that steep C++20 requirement, so it can show the way to the interfaces of the future.

  • Do you think that "No 'preferred' Rep" is a better solution than = double? I could remove the default in mp-units, but I am not so sure if users would be happy about it? Anyway, in V2 we promote 123 * m syntax so during the construction Rep is always explicitly provided by the user. = default is useful in the interfaces (i.e. void foo(quantity<si::metre, double> q) would be too verbose IMHO and double seems to be a good default based on the established practice in other libraries).
  • I am not sure if "sizeof()-friendly unit label representation" is a killer feature for embedded wink, but in mp-units you can easily get the size of any unit at compile time as well (https://github.com/mpusz/mp-units/blob/master/test/unit_test/static/unit_symbol_test.cpp).

I'll answer these together, because they came from a common source: our actual conversations with embedded developers, who were brought in as first-class clients from the library's inception.

Through working with them, I learned that <iostreams> is an unacceptably huge dependency. I also learned that const char[] is strongly preferable to const char* (to which the former decays if you but look at it sideways), in part because of the ability to do sizeof() on the unit label. Our const char[] compatibility through-and-through is one of the small details that I think makes Au the C++ units library with the best real-world track record for embedded support... at least, so far. 🙂 I expect that will change as we get more and more mature toolchains that support C++20.

As for no preferred Rep, yes, I think this is important. The explicit goal there was to avoid making our embedded users second-class citizens: we didn't want one set of APIs for "normal" use cases, and then a separate set for "embedded". Given that double is very often a notably poor choice in embedded applications, making it the default would make embedded users second-class citizens.

This goal forced us to make our APIs as Rep-agnostic as possible. I'm really pleased with where this led for QuantityMaker instances: you can call meters(x) on any arithmetic type x, and it'll work just fine! (Much as with the x * m which mp-units' quantity references permit.) The main downside is of course naming the types. I think we've worked around it pretty well in practice with the Rep-named aliases, which get it down to a single letter: QuantityD<Meters> instead of Quantity<Meters>. I can't say I love this solution as much as the quantity makers, but I think it does the job in practice --- and there's no privilege over the QuantityI32 that I see my embedded colleagues reach for routinely.

That said, I'm not sure that rep-named aliases would work well with the idioms either of mp-units, or of a future std::units library. I'm genuinely at a loss as to how I'd suggest to spell it. I think "default double" will win the day, but I feel a little sad about it.

Ohh, and according to my understanding, mp-units is probably the only one that provides a system of quantities where an angle is a strong dimension/quantity. The docs are TBD (they were provided for 0.8.0), but you can find more here:

Perhaps the only explicit system of quantities. I do get a little confused by the terms sometimes, but I think Au also has a system of quantities (i.e., our one, implicit system) with angle as a strong type: we have a base dimension called angle. Maybe we were the first? I haven't checked.

I think mp-units is the only one which simultaneously supports different systems of quantities with and without strong angles. This is really neat, and I'm excited to see what the community does with it!

(I guess Au kind of supports both? But mainly because users can neglect any dimension they're not interested in, which leads to a kind of "don't say radians if you don't mean radians" policy.)

I just thought of possible additional rows to the comparison table:

  • basic math on quantities (abs, floor, ceil, round, hypot, pow, sqrt, cbrt, exp)
  • trigonometric functions for angular quantities (could also extend already existing "Angles" row as an additional criteria for comparison)

I can't believe I didn't have a row for math functions --- how on earth did I miss that one? I've added it as na for now because assessing each individual library is a lot of work, and I want to finish this comment. 😅

  • one of my users contributed random generators for quantities claiming it is important for their domain as well

I'm pretty wary of that one: it strikes me as being scope creep. I don't think a units library should be in the business of defining how random numbers are generated. This is especially true given that mp-units, like Au, has made it so easy to apply units to arbitrary Rep! I think the right move is to advise a user on how to write a generic function if they need the help, but I expect the library itself is better off without this feature.

We have a similar use case at Aurora, with "fuzz helpers", where we need to generate random quantity values for fuzz testing. Au has no such concept. But our generic Aurora-internal implementation is 5 lines of code --- and only so many because of our clang-format settings! I think this is one feature best left to the end users.

@chiphogg chiphogg marked this pull request as ready for review July 17, 2023 23:51
@mpusz
Copy link

mpusz commented Jul 20, 2023

Thanks for the detailed answer. I understand your points, even if I might have other priorities 😉.

One thing that I am not convinced about is the double thing. I fully understand that you do not want to favor one group over the other, but one could argue that you already do. QuantityD is less to type than QuantityI32 😉. Said that any user can create any alias they want for their project. For example,

namespace my_project {

template<mp_units::Reference auto R>
using quantity = mp_units::quantity<R, std::int32_t>;

}

With the above, users have fixed type as needed for their project and they even do not have to prefix the identifier with the mp_units namespace anymore (so less to type). Having double as a default makes the library easy to use at least for some (majority?) of users. The rest may provide a simple alias like above and it will work great for them as well.

docs/alternatives/index.md Outdated Show resolved Hide resolved
1.82.0)
- One of the longest-standing C++ unit libraries, and the most prominent pre-C++14 option.
- [**nholthaus/units**](https://github.com/nholthaus/units) (version: 2.3.3)
- Kicked off the revolution in modern (that is, post-C++11 watershed) units libraries.
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What does the word "watershed" add here? It leads me to believe that C++11 was particularly revolutionary, but then the word is again used below to describe the C++20 era.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That was my intention. I consider both C++11 and C++20 to be revolutionary releases.

I'm fine keeping it, but am also open to wording suggestions, as I wasn't completely happy with this even before your comment.

docs/alternatives/index.md Outdated Show resolved Hide resolved
- [**mp-units**](https://github.com/mpusz/mp-units) (version: 2.0.0:testing)
- A library designed to take full advantage of ultra-modern (that is, post-C++20 watershed)
features, such as concepts and non-template type parameters (NTTPs).
- mp-units is leading the efforts towards a standard C++ units library, both by trialling new
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"trialling" might be the right word here -- it makes me think of "clinical trials." But it's kind of jargony and got a red squiggle underline when I typed it just now. Consider "trying", "prototyping", or "field testing"?

Copy link
Contributor

@johnzoppina johnzoppina Jul 20, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd cosign on that.

An aside: @tobin That red squiggle is likely because the double-L spelling is also British English; the US variant is trialing

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's go with "field testing".

@@ -225,11 +259,19 @@ At this point, you've assessed:
Now we're ready to compare the libraries "as units libraries" --- that is, in terms of their core
features.

!!! note
The features are listed, _very_ roughly, in order of importance. Counting up the colours in
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we use British spelling?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Chuffed though I'd be if we did, we don't. "Colors" it is.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Canadian habits! 😁

This probably isn't the last to be found among our docs.

@chiphogg chiphogg requested a review from tobin July 21, 2023 13:45
@chiphogg
Copy link
Contributor Author

Thanks for the detailed answer. I understand your points, even if I might have other priorities wink.

One thing that I am not convinced about is the double thing. I fully understand that you do not want to favor one group over the other, but one could argue that you already do. QuantityD is less to type than QuantityI32 wink. Said that any user can create any alias they want for their project. For example,

namespace my_project {

template<mp_units::Reference auto R>
using quantity = mp_units::quantity<R, std::int32_t>;

}

With the above, users have fixed type as needed for their project and they even do not have to prefix the identifier with the mp_units namespace anymore (so less to type). Having double as a default makes the library easy to use at least for some (majority?) of users. The rest may provide a simple alias like above and it will work great for them as well.

That's true, yes. I see both sides on this one, and have even held both positions at different times.

Ultimately, I think it's good for there to be a library that explores the region of design space that is radically committed to not favoring any Rep. Some of the consequences have been unambiguously great, like the quantity maker APIs which are equally usable with any Rep --- I think mp-units is now the only other library with interfaces that match this flexibility. On the other hand, the consequences for the type names are more ambiguous, although I'm happy that the Rep-named aliases have mitigated most of the pain.

That said, I can see the benefits for other libraries to use a default Rep --- especially if Rep-named aliases would be too hard to spell within the idioms of the library (as I think likely for mp-units and a possible future standard units library).

As for D vs. I32, while I'm definitely keen on minimizing unnecessary typing, I wouldn't call D privileged, any more than I'd say that int is privileged over double for that reason. Interestingly, the extra characters in I32 are actually a bonus for my target customers! One thing I've learned is that embedded developers really prefer to be conscious of how many bits they have at their disposal. Spending a couple extra characters to make this clear at the callsite is a price they're generally very happy to pay. 🙂

Copy link
Contributor

@johnzoppina johnzoppina left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks good to me. Thanks Chip!

@chiphogg chiphogg merged commit 5ba2262 into main Jul 21, 2023
7 checks passed
@chiphogg chiphogg deleted the update-matrix#108 branch July 21, 2023 18:49
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
release notes: 📝 documentation PR affecting library documentation
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Consider adding bernedom/SI to alternatives matrix
4 participants