Open mpusz opened 1 year ago
I'm not even sure there should be a one()
at all. What is it supposed to return? To me, the "one" of an algebra is the identity object of the multiplication group. The set of physical quantities representable by in a mp-units quantity of dimension meter doesn't form an algebra at all (it isn't closed under multiplication:length * (1 meter)
isn't a length anymore). Now that I think of it, maybe one()
should actually return the dimensionless quantity of 1, in the same representation type?
Now that I think of it, maybe
one()
should actually return the dimensionless quantity of 1, in the same representation type?
So maybe that should be part of something like a representation_traits
instead.
To me, the "one" of an algebra is the identity object of the multiplication group
Yes, this was the original intent suggested by one of the ISO members. But in practice it turns out that in entire code base we have for V1 one()
is being used only in the functions like ceil()
and floor()
:
So maybe that should be part of something like a representation_traits instead.
We have something similar already:
The question is do we want to keep it and if the numeric-like types should provide specializations of std::numeric_limits
as a general rule. I asked this question to the chair of SG6 Numerics group but got no specific answer for now. Probably I will have to write a paper about that and other similar questions I have in this domain.
Just to elaborate a bit more on what I have in mind here:
value_type
or element_type
member types, or min()
, max()
member functions, or if numeric_limits
should be specialized for them.quantity_values
, but a similar thing will need to be done for linear algebra library, type-safe numerics, fixed precision integers, and so on.... If there was a specific interface mandated by the standard (like, for example, all STD containers have), then it would be much easier to work with those types.quantity
is just yet another numerical type that can be used as an underlying representation type for some other library. So we also should obey the rules of such interfaces. Said that, I believe that, for example, quantity::rep
is a really bad name as probably no other numerical type will choose such a member type to expose the type of its underlying value. Maybe, we should use value_type
instead. Maybe we should provide specializations of numeric_limits
for quantity
and expect such specialization for our representation type as well.I agree with this desire. As always, we can only reason about a "good API" if we have a mental model of the concept that we want to implement. You ask for a "numeric-like representation type", but what does it mean? What should it even mean?
I really believe defining this API is outside of the scope of mp-units; we should be basing of concepts defined elsewhere.
As for acceptable types for the representation of a quantity, I believe std::is_arithmetic
does the job.
But is a quantity
even "just yet another numerical type" itself? What does that mean? It probably is arithmetic, so std::is_arithmetic
does the job. That just requires std::numeric_limits
to be specialised and the four arithmetic operators to be defined. If we want to model a stronger concept, then we should probably look at real use-cases, and then decide if a physical quantity actually models the concept expected by the use-case, and then we have a reference for the API.
On rep
/value_type
/member_type
: To me, this has nothing to do with a "numeric-like" concept (what does it mean for a "number" to ask for it's "value_type"?). Conceptually, it is the C++ representation that we use to represent the number, which, together with a unit provides a representation for a physical quantity. I would thus like to call it number_repr_type
. Having it named member_type
on it's own doesn't make it anymore interoperable with other libraries unless it also follows the expected semantics (quantity
is still not a container).
You may want to have a look at the compositional numbers library, which composes actual "number-like" types from various aspects. One important feature are fixed-point numbers: a signed 12.4 bit fixed-point number is an arithmetic object that is able to represent certain rational numbers, and shares the bit pattern of a 16 bit signed integer that is semantically interpreted as if counting in "units of 1/16". It also does support more general scaled numbers, i.e. scaling by powers of 10, similar to decimal prefixes in SI. However, contrary to quantity
, it still generally models the concept of (rational) numbers, where quantity
models "physical quantities".
As for acceptable types for the representation of a quantity, I believe std::is_arithmetic does the job.
No, it does not. It limits the type only to fundamental types. We already have plenty of examples using linear algebra, `measurement class, or ranged_representation
.
quantity
does not satisfy std::is_arithmetic
as well. Moreover, it is an Undefined Behavior to provide specialization of most type traits from the <type_traits>
header for user-defined types.
You may want to have a look at the compositional numbers library, which composes actual "number-like" types from various aspects.
Yes, I am aware of that and other projects (although I did not study them too much). Yesterday, I asked their authors and SG6 Numerics reflector for feedback, and I am getting the first answers already. We will see if we will be able to standardize some common look and feel here or if we just continue to do our local stuff.
Consider providing a partial specialization for
std::numeric_limits
to provide all the numeric properties of underlying representation types. Removemin()
andmax()
from quantity and also remove standaloneepsilon()
from math.h.The only problem is what to do with the remaining
zero()
andone()
as those are not provided viastd::numeric_limits
.