mpusz / mp-units

The quantities and units library for C++
https://mpusz.github.io/mp-units/
MIT License
1.07k stars 85 forks source link

Provide support for non-negative quantities #468

Open mpusz opened 1 year ago

mpusz commented 1 year ago

ISO 80000 explicitly specifies quantities that have to be non-negative (width, thickness, diameter, radius).

Some of the quantities are implicitly defined as non-negative. For example, "path length" is defined as hypot(dx, dy, dz). Others are defined as the magnitude of a vector which also is always non-negative.

Some quantities are also explicitly defined as signed (i.e. height), so they should not be treated as a norm(position_vector).

mpusz commented 1 year ago

We should probably provide some exceptions from the rules for engineering purposes. For example, speed is defined as a magnitude of velocity which implies that it is non-negative.

For engineering purposes, speed probably should be defined as length / time which improves usability. For example, we can easily calculate height / length without mandating users to use a linear algebra library. In such a case a negative height can result in a negative speed.

JohelEGP commented 1 year ago

What does the library need to do, besides permitting user-defined representation types that can catch negative values?

mpusz commented 1 year ago

The check implementation part is easy. Just do the compile-time branch with gsl_Assert(). However, first, the logic (when and where) has to be figured out. Then we have to find out how to store the information about this in a derived quantity based on the quantity equation.

JohelEGP commented 1 year ago

I think I have an answer.

Either we do nothing, or provide a way to opt-into having a non-negative quantity type.

For example, I wrap a width and a height in a Cartesian vector. I should be able to add and subtract these values without triggering assertions. Sometimes, the Cartesian vector represents a size, in which case both of the components should be non-negative. In this case, the width and height components are equally constrained. So there isn't anything particularly special about width.

It seems to me that ISO/IEC 80000 sometimes calls out special cases like this. However, that shouldn't prevent us from applying the maths to manipulate these values. As for

or provide a way to mark a given value's type as non-negative

it seems to me that we actually want an interface that both applies abs when first converting the quantity and updates the quantity_spec to require the numerical value to be non-negative from there on. So I can do

Quantity_of<width> auto q = (entity1.pos.x - entity2.pos.x).non_negative();

when I require the result to be the width that is non-negative, and an equivalent interface to easily name such a constrained type.

It seems to me that ISO/IEC 80000 sometimes calls out special cases like this.

Others include quantity difference and quantity point pairs. So where we might use quantity<time[s]> and quantity_point<time[s]> as a difference and point, respectively, ISO/IEC 80000 might actually have different names for those. For example, I get the impression that these come in groups of points and corresponding difference:

There may be a few others, but I don't remember. I think I may have mentioned this before. I also don't remember if V2 does anything in particular with this information.

mpusz commented 1 year ago

For example, I wrap a width and a height in a Cartesian vector. I should be able to add and subtract these values without triggering assertions.

Sure, please note that subtracting width from height is a length that is not constrained by itself.

ISQ defines only width, thickness, diameter, and radius to be non-negative. Additionally, probably quantities that are defined as magnitudes of vectors could be non-negative as well.

However, subtracting width and width will give you width as a result, and we have to decide what to do with that... ๐Ÿ˜‰

So I can do

Quantity_of<width> auto q = (entity1.pos.x - entity2.pos.x).non_negative();

when I require the result to be the width that is non-negative, and an equivalent interface to easily name such a constrained type.

I actually never thought of that, but I am not sure if that is needed. The temporary result probably does not need constraints. The check has to be done in the width constructor if the value is non-negative anyway.

I also don't remember if V2 does anything in particular with this information.

I am not sure if we should constrain some ISQ types to be used only for either quantity or quantity_point. It could be too much, but maybe we should discuss this option in a dedicated issue? Another question is who would be able to properly identify those?

JohelEGP commented 1 year ago

For example, I wrap a width and a height in a Cartesian vector. I should be able to add and subtract these values without triggering assertions.

Sure, please note that subtracting width from height is a length that is not constrained by itself.

I meant the vector values, which does the component-wise operation (so no width plus height, but rather width plus width and height plus height).

JohelEGP commented 1 year ago

However, subtracting width and width will give you width as a result, and we have to decide what to do with that... ๐Ÿ˜‰

This is why I answered

Either we do nothing, or provide a way to opt-into having a non-negative quantity type.

I forgot that to mention that it might just be the case of a missing abstraction. Which is why I mentioned enhancing quantity_spec to recognize the constrained case. We still want to be able to have differences and points of "negative" quantities that aren't actually constrained. If we force the property for all uses of the quantity, it becomes engineering unfriendly.

mpusz commented 1 year ago

Please note that isq::height can be negative.

Probably, you are abusing isq::width for your coordinate needs. Width is something that you may measure with a caliper. There is no physical way for it to be negative. Maybe you should derive your own quantity_spec from isq::length to denote X axis?

JohelEGP commented 1 year ago

Yeah, I'm considering that. I need to do it for depth, anyways, which in ISQ is a synonym for height. However, I'm not convinced that my abuse of width means that my opinions on how it should be handled by the library are invalid. If it's constrained, the only reasonable way to change width values is to work on lengths before converting to widths.

mpusz commented 1 year ago

I would do something like:

QUANTITY_SPEC(pos_x, isq::length);
QUANTITY_SPEC(pos_y, isq::length);
QUANTITY_SPEC(pos_z, isq::length);
mpusz commented 1 year ago

If it's constrained, the only reasonable way to change width values is to work on lengths before converting to widths.

Yes, if we really want to subtract two widths measured by the caliper and we really need to subtract the bigger value from the smaller one we would probably need something like that:

QuantityOf<isq::length> auto q = isq::length(width1) - isq::length(width2);

which I think may have some sense in a "twisted" physical way ๐Ÿ˜œ

JohelEGP commented 1 year ago

I also don't remember if V2 does anything in particular with this information.

I am not sure if we should constrain some ISQ types to be used only for either quantity or quantity_point. It could be too much, but maybe we should discuss this option in a dedicated issue? Another question is who would be able to properly identify those?

I remember that we did discuss this before. I think it was something about how a quantity difference can have different associated points. The associated points could be different by definition, and thus not share an origin among themselves. And I think I concluded that a quantity difference doesn't necessarily have a default associated point. So it's the user who should opt-into using the correct quantity point for their use case.

JohelEGP commented 1 year ago

Probably, you are abusing isq::width for your coordinate needs.

The reason I haven't convinced myself of that is that the definition of width and height in ISO seem to match that of the components of a Cartesian vector.

JohelEGP commented 1 year ago

My Cartesian vectors, represented with cartesian_vector๐˜•d and cartesian_point๐˜•d in code, are more specific quantities of displacement and position vector, respectively. However, I believe it has an even more specific representation as a tuple of (width, height, depthโ‚’โ‚šโ‚œ). Only when a Cartesian vector represents a size, do all of its components need to be non-negative.

I think it's perfectly valid for a difference of widths to be negative. A quantity is supposed to represent a quantity difference. And quantity_point is just a more specific version representing a quantity offset from an origin. So I think it's fine for those to be negative.

So if a quantity of width is supposed to be non-negative, what is the missing abstraction? Is it that quantity doesn't always represent a quantity difference? What are the implications of making it so, and enhancing quantity_spec to represent this use case?

mpusz commented 1 year ago

I think it's perfectly valid for a difference of widths to be negative.

The ISQ defines width as:

minimum length of a straight line segment between two parallel straight lines (in two dimensions) or planes (in three dimensions) that enclose a given geometrical shape

How can a length between two parallel lines be negative? I do not think it has anything to do with points here. If we subtract two widths, we actually do not subtract the widths but their lengths. That is why I think that the cast I mentioned above makes a lot of sense from the physical point of view.

JohelEGP commented 1 year ago

That's why this time I'm referring to a difference of widths, which shouldn't be the same as a width (the non-negative quantity).

JohelEGP commented 1 year ago

Maybe it'd make more sense if quantity was named quantity_vector. Then we could add quantity_magnitude for the times we want the non-negative quantity that doesn't represent a vector. It could be implemented on top of quantity_vector (like quantity_point is), but without operations (other than an accessor for the vector), and possibly constrained to non-negative quantities.

JohelEGP commented 1 year ago

So yeah, as a generalization of std::chrono::duration, I was under the impression that mp_units::quantity was supposed to represent a vector space. But widths don't have inverse elements, so it doesn't form a vector space. It's still useful to have width vectors, and have their magnitude result in an actual width. So I think quantity_magnitude is the missing abstraction.

mpusz commented 1 year ago

But widths don't have inverse elements, so it doesn't form a vector space. It's still useful to have width vectors, and have their magnitude result in an actual width. So I think quantity_magnitude is the missing abstraction.

I do not think that we miss something here. We might just misuse what we have. Notice that isq::width is defined as a scalar quantity so trying to represent it with vectors or expect it to model a vector space is wrong.

As I wrote before, width is something that you can measure with the caliper, and physically you can't measure negative widths, right? ๐Ÿ˜‰ If we subtract a longer displacement from a shorter one and take a magnitude of it, it would not be a width in a physical sense.

Let's forget about vectors for now and see the following:

// measured with caliper
quantity<isq::diameter[mm]> outside_pipe_diameter = 20 * mm;
quantity<isq::diameter[mm]> inside_pipe_diameter = 16 * mm;

quantity<isq::thickness[mm]> pipe_wall = quantity_cast<isq::thickness>((outside_pipe_diameter - inside_pipe_diameter) / 2);
std::cout << "Thickness of the pipe wall: " << pipe_wall << "\n";

If I accidentally subtract the outside diameter from the inside one I will get a negative value which does not make sense and the entire purpose of this Issue is to help find such problems (unfortunately only at runtime).

mpusz commented 1 year ago

Now, let's come back to vectors.

If we deal with vectors, we should use isq::position_vector (if our vector originates from the center of the coordinate system and expresses a point/position) or isq::displacement otherwise. If isq::displacement is not expressive enough, we can derive more specific quantities from them if we need additional safety.

Having those, we can subtract them, take the magnitude of the result, and cast it to isq::width if that is what we actually deal with. But again, if we subtract a longer displacement from a shorter one and take a magnitude of the result (which will yield a positive value) we will still have an error in our calculations as this should not express a width. However, this time, the library will not find the issue at runtime because the magnitude(q) operation will hide the issue.

The above is probably not a correct approach as well. So what we should do is the following:

quantity<isq::displacement[mm], la_vector> outside_pipe_diameter = {2, 3, 4} * mm;
quantity<isq::displacement[mm], la_vector> inside_pipe_diameter = {1, 2, 3} * mm;

quantity<isq::thickness[mm]> pipe_wall =
    quantity_cast<isq::thickness>(isq::diameter(magnitude(outside_pipe_diameter)) -
                                  isq::diameter(magnitude(inside_pipe_diameter)) / 2);
std::cout << "Thickness of the pipe wall: " << pipe_wall << "\n";

We have #463 opened to discuss how to handle vector quantities in the library correctly.

JohelEGP commented 1 year ago

But widths don't have inverse elements, so it doesn't form a vector space. It's still useful to have width vectors, and have their magnitude result in an actual width. So I think quantity_magnitude is the missing abstraction.

I do not think that we miss something here. We might just misuse what we have. Notice that isq::width is defined as a scalar quantity so trying to represent it with vectors or expect it to model a vector space is wrong.

Rather than vector space, it seems like I meant more specifically affine space. This is the vector I'm talking about: https://mpusz.github.io/mp-units/2.0/users_guide/framework_basics/the_affine_space/#vector-is-modeled-by-quantity. And a width doesn't support this operation listed at https://mpusz.github.io/mp-units/2.0/users_guide/framework_basics/the_affine_space/#operations-in-the-affine-space:

  • -vector -> vector
mpusz commented 1 year ago

OK, I was confused because you mentioned taking the magnitude of a vector several times. What does the magnitude of such a vector/difference quantity mean?

mpusz commented 1 year ago

Also, I think I was wrong in claiming that a negative width has no physical sense. For example, let's assume that we measure the width of brake pads in my car with a caliper today and after half a year. The second measurement will be smaller, which should give me the answer that the pads shrunk by this amount. It is still a quantity of width and its value probably should be negative.

mpusz commented 1 year ago

Does it mean that in case we will add support for non-negative quantities they should actually apply only to the values in the quantity_point and not for quantity?

JohelEGP commented 1 year ago

If quantity represents a vector, then it can't represent negative quantities like width. But you can indeed represent changes in width. Like you mention with https://github.com/mpusz/mp-units/issues/468#issuecomment-1708157645. That's what vectors are for, after all.

I'm struggling more finding something that you can't measure with quantity or a vector. That's besides nominal properties and ordinal quantities. And of course, algebraic structures that don't form a vector space.

Does it mean that in case we will add support for non-negative quantities they should actually apply only to the values in the quantity_point and not for quantity?

I don't think so, since you can have negative points. I really think it's a new abstraction: Magnitude.

mpusz commented 1 year ago

If quantity represents a vector, then it can't represent negative quantities like width. But you can indeed represent changes in width. Like you mention with https://github.com/mpusz/mp-units/issues/468#issuecomment-1708157645. That's what vectors are for, after all.

I am not sure if I understand what you meant here. First, you say that a vector can't represent negative quantities and then you say that is obvious ๐Ÿ˜‰

I don't think so, since you can have negative points. I really think it's a new abstraction: Magnitude.

What does a negative point of width mean?

JohelEGP commented 1 year ago

Depends on your origin, I guess. With ideal_waist_size_of_adult_supermodel, it'd mean your waist size is less than that of the ideal for an adult supermodel.

mpusz commented 1 year ago

quantity always expresses the change of something, and quantity_point provides the actual point/position (https://mpusz.github.io/mp-units/2.0/users_guide/framework_basics/the_affine_space/#vector-is-modeled-by-quantity). We are just not using points often enough, thinking that they are mostly used for temperatures.

Think about std::duration and std::time_point.

JohelEGP commented 1 year ago

We are just not using points often enough thinking that they are mostly used for temperatures.

Well, I do use them a lot, and not for temperatures at all.

Here's a sample implementation of magnitude: https://cpp2.godbolt.org/z/xP9fhM9Mf. The lower pane has generated Cpp1. The only operations I permit are with other magnitudes, and only in the direction of addition.

JohelEGP commented 1 year ago

We are just not using points often enough, thinking that they are mostly used for temperatures.

I totally wouldn't want to mix positions and sizes/magnitudes in the type system. I once tried to merge quantity and quantity_point, disabling unwanted overloads with constraints. The result was unsightly compared to each being its own template, so I wouldn't want to do the same with quantity_point.

mpusz commented 1 year ago

Depends on your origin, I guess. With ideal_waist_size_of_adult_supermodel, it'd mean your waist size is less than that of the ideal for an adult supermodel.

Right ๐Ÿ˜œ Do you think such an origin should be defined as absolute or relative? Maybe then, absolute values should be non-negative?

JohelEGP commented 1 year ago

Maybe then, absolute values should be non-negative?

With something like mean_sea_level, you'd want negative points. And regardless of it being an absolute or relative origin, you should be able to have negative points (if you can do the same with any single other related origin).

mpusz commented 1 year ago

But height is not specified as non-negative. Only width and quantities derived from it are defined as non-negative. See the tree of quantities of kind length for reference: https://mpusz.github.io/mp-units/2.0/users_guide/framework_basics/systems_of_quantities/#system-of-quantities-is-not-only-about-kinds.

JohelEGP commented 1 year ago

Yeah, I said before that width is no different than height in respect to being negative or non-negative.

You can have an object with a width and a height. These are magnitudes, because a negative width or height for an object doesn't make sense. So both are equally non-negative in this case, even if ISQ defines both from different applications (as a magnitude for width, and as a vector for height).

You can also have the object change its width or height. A vector applied to one of the two parallel straight lines that define a width as a magnitude can represent this change in the width of the object. The same applies to the primitives that define the height of the object.

The object can also be in a space. Conveniently, I use the same space of the primitives used to define its width and height. So I use these primitives to the define points of the object in the space (e.g., it's center), and changes to the points of the object (in the type system using the same vectors that describe the width and height of the object).

mpusz commented 1 year ago

I said before that width is no different than height in respect to being negative or non-negative.

I am not so convinced here. It was hard for me to realize how to measure a negative width, there are plenty of negative heights/altitudes on a map. Height points are typically measured relative to MSL so it is easy to get a negative value. Widths are mostly measured against 0 (but your ideal_waist_size_of_adult_supermodel example is probably also valid).

chiphogg commented 1 year ago

Terminology is hard. "Height" can mean "height relative to a reference altitude" (which can be positive or negative), or "minimum clearance to pass over an object on the ground" (which must be non-negative). It's important to be clear about which we're discussing when we say "height"... although I have no good ideas for how to make this distinction in code.

JohelEGP commented 1 year ago

how to measure a negative width

I agree with ISQ; there are no negative widths. As currently defined, mp_units can't represent a width. mp_units::quantity is a vector. But a width isn't a vector because its negative is undefined. mp_units::quantity_point is a point. But a width has no origin. Or you could say it has the two parallel lines in its definition. But those are very dynamic in nature; they enclose an object in a space.

Then what do mp_units::quantity<width[m]> and mp_units::quantity_point<width[m]> measure? Is it something we want to prohibit? And instead allow only through a new abstraction mp_units::magnitude<width[m]>? My application has sizes, points, and vectors. I can define a size as the magnitude of a vector. And the vector can be the difference of two points. So if magnitude(point_a - point_b) can give me a size, then it makes sense that I can add a vector like point_a - point_b to any point of the same "quantity" to change an eventual magnitude.

Do note that ISO/IEC 80000 already defines "quantities" that are points. So it's no surprise that it also defines "quantites" that are magnitudes. Part 8 (Acoustics) also defines logarithmic quantities, which we haven't figured out yet (#35). It might be that they also are their own new abstraction. Knowing whether they make a vector space could be a starting point to figuring that out.

[ Note: Even though ISQ remarks that height "is usually signed", I can have non-negative heights (i.e., magnitudes, e.g., to describe the height of an object or space, which isn't a point or a vector). -- end note ]

[ Note: In reality, some of my objects are represented with a single point offset from some origin (e.g., the top-right of a GUI button offset from the window's top-right). Their representation also include a size (a pair of magnitudes of width and height). Those can be enough to manipulate all its points. Those primitives currently go by the name of vector<width, pixel>, magnitude<width, pixel>, and point<window, width, pixel>, which currently respectively correspond to mp_units's quantity<width[pixel]>, quantity<width[pixel]>, and quantity_point<window, width[pixel]>. -- end note ]

although I have no good ideas for how to make this distinction in code.

This is why I'm contemplating using a magnitude abstraction for this.

I'm still rewriting things to use magnitude. And mp_units also has some examples that use widths and heights. So looking at those with this new information in mind might help in figuring things out. I already have my own application, which is how I got here in the first place.

mpusz commented 1 year ago

I wouldn't like to use the term vector here, because I prefer to leave it to quantity character so saying that width might be a vector is really misleading as ISQ says that it is a scalar quantity. ISQ defines only two vector quantities of kind length (position_vector and displacement). Using the same term for two different things leads to confusion. Can we find a better name for it (i.e. difference, offset, shift, ...)?

Also, magnitude is already taken for the "factor" of a unit. We should rename either of those to avoid the confusion. For vector quantities, we plan to use norm() to calculate the magnitude of a vector as described in #463, but this may change as well.

mpusz commented 1 year ago

Terminology is hard. "Height" can mean "height relative to a reference altitude" (which can be positive or negative), or "minimum clearance to pass over an object on the ground" (which must be non-negative). It's important to be clear about which we're discussing when we say "height"... although I have no good ideas for how to make this distinction in code.

ISQ is not that specific, but if some life-critical aviation application needs to distinguish those, it can always derive its own quantity kinds from isq::height and make one of them non-negative if needed.

JohelEGP commented 1 year ago

This is what I've settled with for now: https://cpp2.godbolt.org/z/sWj1K5rc8.

With that, I specify arguments and members that are magnitudes. It's clear from context what's a magnitude, so I chose for vector to be implicitly convertible to magnitude.

I still need to use magnitudes as vectors. So I overloaded unary * on magnitude to return the vector. Using that, I avoid having to overload vector functions for magnitudes.

So far, I've been able to rely on the implicit conversion of vector to magnitude. But when implicit conversion doesn't happen, a named conversion might be need. If Cpp2 had conversion operators, I'd have used that, too.

JohelEGP commented 1 year ago

428, and https://github.com/mpusz/mp-units/issues/353#issuecomment-1084679393 in particular,

reminded me that we can just use a constrained number type. When it comes to saying whether such a type would be a vector space, I think it's the same as using an unsigned integer type. That means that the domains of some operations are more restricted.

JohelEGP commented 1 year ago

No, sorry, that not entirely right. A number type constrained to not be negative isn't the same as an unsigned integer type. Unsigned integer types have more defined operations (see the last sentence of the "Note 1 to entry" of IEV 102-01-11). Using an unsigned integer type for representing magnitudes is as problematic as using unsigned integer types for representing sizes (e.g., of C++ standard library containers).

JohelEGP commented 1 year ago

428, and https://github.com/mpusz/mp-units/issues/353#issuecomment-1084679393 in particular,

reminded me that we can just use a constrained number type. [...] That means that the domains of some operations are more restricted.

This is also doubtful. Elements of a vector space have an opposite. But with such a constrained number type, all elements are out the domain of unary -.

mpusz commented 1 year ago

I wouldn't recommend using unsigned type for that, but a custom wrapper for representation type could do the work. However, I do not see how it is different than adding proper checks to the constructor and assignment of quantity?

JohelEGP commented 11 months ago

IIUC, the consensus on yesterday's meeting was that, for non-negative quantities, contract-checking the number suffices and that anything else should prove the safety it brings.

I have been thinking that, indeed, that should suffice. But that doesn't answer how the library should handle non-negative quantities. Right now, we have to use a number type that is contract-checked to catch negative values. IIRC, @rothmichaels wanted to be able to specify a quantity_spec as non-negative to reduce boilerplate. In that case, mp_units::quantity could be contract-checked with .is_non_zero(). And a quantity_point with a non-negative quantity_spec would also be contract-checked for free.

We also talked about being able to subtract quantities specified as non-negative. That could result in a negative value depending on the order of the arguments. But that there are conceivable use cases where such manipulation is useful (or the lack thereof restrictive). @mpusz also mentioned having to specify speed not as the magnitude of velocity (as in ISO 80000), which would make it implicitly non-negative, but as something else because negative speeds are entirely reasonable.

I still view quantity as a vector for which we should be able to always subtract in any order. We also talked about the value of having non-negative quantities of quantities that aren't necessarily specified as being non-negative. Let's consider height, not specified by ISO 80000 as non-negative. Some amusement park rides requires have a minimum height requirement on its riders.

The convenience of generalized non-negative quantities is being able to catch math errors. Did the user get a sign wrong or arguments inverted, or simply forgot to call abs or magnitude? So even if amusement park goers never have 0 height, we can help catch logic errors. Based on all the feedback, I'm leaning towards this:

As an aside, I originally gave the example of frequency instead of height. But that might not be entirely right, as it's specified in terms of period (IEV 103-06-01). Although it being non-negative isn't clear from the ISO 80000 definition: "duration (item 3-9) of one cycle of a periodic event". @mpusz Here's an example of what you were wondering about other non-negative quantities in ISO/IEC 80000.

JohelEGP commented 11 months ago

Based on all the feedback, I'm leaning towards this:

  • Not allowing users to explicitly define their quantity_specs as non-negative.
  • Having a magnitude<Reference, Rep> template alias that "sets the non-negative bit in quantity_spec", that aliases quantity<Reference._non_negative_(), Rep> (I think a magnitude_point might also be useful).
  • I think magnitude is mainly useful in interfaces. So in order to allow using their values as vectors, they should drop the "non-negative bit" at the drop of a hat. For example, given a magnitude x:
    • x -= y works and checks that the resulting number of x is non-negative.
    • x - y results in a quantity with the "non-negative bit" unset.

More simply, magnitude<Reference, Rep> aliases quantity<Reference, non_negative<Rep>>. Where mp-units defines non_negative because it wants to support the good stuffs above. Accordingly, -= is checked, and - returns the Rep (i.e., not wrapped in non_negative).

JohelEGP commented 11 months ago

I think it was @mpusz who said that we wouldn't be having this discussion if std had something like non_negative.

I'm going to suggest that the non_negative I'm suggesting that mp-units needs should be named magnitude_rep to highlight its special behavior. Other constrained numbers keep their constrains when operating on them. I'm suggesting that magnitude_rep<Rep> should instead return Rep from those.

Now, a question of safety. Is it clear that quantity<width[m], int> can be negative? Today's mp-units could be a source of logic errors due to users who expect naively it to be contract-checked. I see two ways forward.

The first one is the very constraining choice of all non-negative quantities always being contract-checked.

The second one is to attempt to educate users. My suggestion of adding magnitude is one such attempt in this direction.

mpusz commented 11 months ago

because negative speeds are entirely reasonable.

The more I think of it, the more I am convinced that negative speeds should indeed be velocities. A negative value is to represent a vector in the "backward" direction, right? ๐Ÿ˜‰

However, I think that it should be perfectly fine to obtain speed by dividing i.e. height by time, and not always through a magnitude of position vector. Do we have any idea how to handle that?

mpusz commented 11 months ago

Let's consider height, not specified by ISO 80000 as non-negative.

Height and altitude are the same quantities in ISQ and negative altitudes are perfectly fine.

JohelEGP commented 11 months ago

Yeah. That's why I'm saying there's value in having it checked as non-negative when a negative altitudes would be a logic error.