Replies: 2 comments
-
@chiphogg, that is excellent feedback, and I must admit I had some similar doubts before. However, with time, I realized there was no other way to make it right. I will provide a few points below to "defend" the current approach. Please let me know your thoughts.
Many people naively assume that the only mistakes we make in our code are related to units, but that is not true. I initially got some pushback about quantity kinds from some people (including you 😉). Still, we already have plenty of feedback that proper modeling of quantity kinds increases safety in production code in many domains already. This is why many people chear for mp-units because no other library can help them make their project correct. I also get reports about other kinds of prevalent and often fatal mistakes that the library could prevent. For example, in power systems engineering, it is a common mistake to assign the result of modulus on a complex power to apparent power (instead of active power), incorrectly assign the real part of complex power to reactive power or form a complex power from wrong ingredients. Another simple mistake to avoid would be preventing conflating speed and velocity which is common in some cases. Even on the last CppCon, I was approached by some potential users who stated that if the library does not explicitly cover the above cases, it will be useless in their domains and that they will not be able to use it even if it gets standardized. It will simply not be safe enough, and potential mistakes may have fatal consequences. Please note that NO library on the market works with proper linear algebra or complex types used as a quantity representation type. As a result, the users have to work around this issue by putting the units-library type into the representation type. They create vectors of meters or complex numbers of quantity types (please note that In order to support those, a
No library on the market today can prevent the above mistakes. But those mistakes do happen a lot. We can help people write correct code with the abstractions that mp-units propose.
Sure, but even if the representation is a C++ fundamental type, those still express vector quantities (i.e., velocity/speed example), and this does not make them less quantity-safe.
No one wants to change that. The idea is that for many libraries, quantity characters should work right away with no changes needed. For others, users may need to provide some customization points (e.g.,
Are you aware of such use cases already? I reviewed all quantities from parts 3 - 6 in ISQ, and I could not see any controversies there. |
Beta Was this translation helpful? Give feedback.
-
Let's try to provide code examples for three cases. Maybe this will make what we want to achieve here more straightforward. Work vs moment of forceThe first case was already discussed in detail in my blog post about quantity safety: quantity force = get_force();
quantity displacement = get_displacement();
quantity position_vector = get_position_vector();
delta_quantity_of<isq::work> auto work = scalar_product(force, displacement).in[J];
delta_quantity_of<isq::moment_of_force> auto moment_of_force = vector_product(position_vector, force).in[N * m];
quantity axis = get_axis_unit_vector();
delta_quantity_of<isq::torque> auto torque = scalar_product(moment_of_force, axis);
// delta_quantity_of<isq::work> auto bad1 = vector_product(position_vector, force).in[N * m];
// delta_quantity_of<isq::moment_of_force> auto bad_2 = vector_product(force, position_vector).in[N * m];
// delta_quantity_of<isq::torque> auto bad_3 = scalar_product(position_vector, force).in[N * m]; Please note that the above code is quantity-safe, even though I did not mention any explicit representation type. Users can choose any type that satisfies the above concepts through our customization points (e.g., vectors, bivectors, ...). Of course, in a traditional "vector of quantities" use case, some of the above operations will also not compile if the users carefully match the correct representation types with the proper quantities. However, it will not be true for Using proper linear algebra types for vector quantities actually makes it easier to detect issues, even in the traditional approach. It may be much more challenging when a user uses the same type for scalar and vector quantities, as presented in the following example. Velocity vs speedquantity velocity = isq::velocity(-20. * km / h);
quantity<isq::speed[km / h]> speed = magnitude(velocity);
quantity mass = 1'540 * kg;
quantity<isq::momentum[kg * m / s]> momentum = mass * velocity;
// quantity<isq::speed[km / h]> bad_4 = velocity;
// quantity<isq::momentum[kg * m / s]> bad_5 = mass * speed;
// quantity bad_6 = isq::speed(vector{1, 2, 3} * m / s); Above, I used vector quantities with With Complex Powerquantity active_power = isq::active_power(42. * W);
quantity reactive_power = isq::reactive_power(42. * var);
quantity<isq::complex_power[V * A], std::complex<double>> complex_power = make_complex_quantity<std::complex>(active_power, reactive_power);
quantity<isq::active_power[W]> act = real(complex_power);
quantity<isq::reactive_power[var]> react = imag(complex_power);
quantity<isq::apparent_power[V * A]> app = modulus(complex_power);
// quantity<isq::complex_power[V * A], std::complex<double>> bad_7 = make_complex_quantity<std::complex>(reactive_power, active_power);
// quantity<isq::apparent_power[V * A]> bad_8 = real(complex_power);
// quantity<isq::active_power[W]> bad_9 = modulus(complex_power); I used an explicit @chiphogg or others, could you please explain how to model the above in other libraries (e.g., Au)? I am not even asking about preventing the bad cases (of course, it would be nice to learn if that is already possible), but at least present the code that allows the correct part to compile and have proper units (and quantities, if possible). I would love to see such code examples, as this could allow us to compare approaches and maybe limit the scope to what is really needed. |
Beta Was this translation helpful? Give feedback.
Uh oh!
There was an error while loading. Please reload this page.
-
I was thinking the other day about the principle of "same program, only safer", and I realized it might have implications for whether the "vector character" feature is within the proper scope of a quantities library.
That principle suggests that we should think about what programs a user would write in their ideal world, but without a units library. Then we should think about what kinds of (quantity-related) mistakes they're likely to make, and look for opportunities to help them move fast with confidence.
In that ideal world, users are already choosing the vector and matrix types that make the most sense for their application. They are already choosing scalar types for vector quantities that reduce to a single dimension when that's appropriate. If they care about avoiding the kludge of the cross product, they are already using bivector or multivector types from a geometric algebra. We certainly want to avoid changing any of that; all we want to do is wrap it and make it safer.
Now, suppose we do include vector character in our quantity specs. This has the following effects.
When a user encounters one of these forbidden combinations, I see two possibilities:
For this feature to be a net win, we need (1) to be overwhelmingly more common than (2). But I think that (2) will be more common in practice, and possibly overwhelmingly so. In order to achieve (1) users would have to choose a type with the wrong vector character. Do users do that, in the real world? I doubt it!
There's a good chance we can save ourselves (and our users) a lot of headache by leaving this feature out. We should just say that choosing the rep is the right way to handle the vector character. We have enough work to do to get a high quality quantities library into C++29; if we can avoid working on a feature that may cause more harm than good, then we should take that opportunity.
Beta Was this translation helpful? Give feedback.
All reactions