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

Does a base_dimension belong to particular quantity_system(s)? #44

Closed
kwikius opened this issue Dec 13, 2019 · 7 comments
Closed

Does a base_dimension belong to particular quantity_system(s)? #44

kwikius opened this issue Dec 13, 2019 · 7 comments
Labels
question Further information is requested

Comments

@kwikius
Copy link
Contributor

kwikius commented Dec 13, 2019

Mpusz units on new_design branch splits into quantity_systems { physical.si, physical.cgs, data }

Does a base_dimension belong to particular quantity_system(s) or is a base_dimension allowed in any quantity_system? Or alternatively do quantity systems themselves belong to a particular quantity "universe"? (The base_dimension then exists in that universe rather than a particular quantity system.

Is there a dependency of base_dimension on the particular system(s) in use as suggested here?
https://github.com/mpusz/units/blob/new_design/src/include/units/base_dimension.h#L39

One dependency, for example might be if base-dimensions are ordered differently in different systems, or maybe two base_dimensions from different systems compare the same for ordering. Then what happens if various systems are used simultaneously?

If there is a dependency then instead of

is_base_dimension
one might have to do
is_base_dimension_of<QuantityUniverse,T>

Now the next issue. It is necessary to know what universe the computation applies to at compile time, so how one finds and applies the quantity_system a computation is in during compilation? .
(Maybe by choosing a custom header eg, as for example (std::cout availability is dependent on iostream header for example)

@mpusz mpusz added the question Further information is requested label Dec 14, 2019
@mpusz mpusz added this to To do in Issues Kanban Board via automation Dec 14, 2019
@kwikius
Copy link
Contributor Author

kwikius commented Dec 14, 2019

Here is where I am at as regards base_dimension

A base_dimension is a globally unique entity within an application.

exponents of base_dimensions can be combined in a set known as a dimension.

For convenience c++ classes representing unique base_dimensions must be totally ordered at compile time.

Alternatively you have to restrict a base_dimension to a particular system e.g Newtonian Physics or Quantum Physics etc

Ideally you can plug in a set of base dimensions ( which meets the necessary requirements) to the units 'engine' and it will just work.

For myself I would hope there would be a standard <units/si_base_dimensions> header included.
In previous discussions, there used to be requests for options where e.g apple,oranges, pears are base dimensions ( money is another frequent request, though arguably far from being a compile time constant).

Ideally it should be possible to unplug (say) physical base_dimensions and plug in apples and pears base_dimensions or even append apples and pears to physical base dimensions. Even though apples and pears base_dimensions might seem ridiculous, yet it helps to use as a test case to verify separation of concerns in the library. For example The SI system can then be verified as a plug in to the basic units engine rather than being a dependency

@mpusz mpusz moved this from To do to In progress in Issues Kanban Board Dec 14, 2019
@mpusz
Copy link
Owner

mpusz commented Dec 14, 2019

Hi, thanks for the review of a new design :-) You raised a few interesting questions here and well, even though I designed and implemented all of this I am not sure if I know how to answer them ;-)

We always had base_dimension in the design but for now, it was fixed to one bae unit (i.e. physical length was always measured in metres even when we simulated CGS dimensions). This metre symbol was hardcoded in the base_dimension implementation and independent from metre unit defined for a derived dimension. It bothered me a lot. Also up to now, every base_dimension was repeated as a derived one (i.e. length = <exp<base_dim_length, 1>> and only this one was later used to composed real derived dimensions like area or velocity. New design solves all of those problems.

Right now a physical dimension is still identified by a unique text identifier (i.e. "length") that is the most important part of the ordering (BTW, I fixed a potential bug there based on your comment, thanks! :-) ), but additionally gets a base unit that is adopted in a specific system of units. So:

namespace units::si {

struct dim_length : base_dimension<"length", metre> {};
struct dim_mass : base_dimension<"mass", kilogram> {};
struct dim_time : base_dimension<"time", second> {};
struct dim_current : base_dimension<"current", ampere> {};
struct dim_temperature : base_dimension<"temperature", kelvin> {};
struct dim_substance : base_dimension<"substance", mole> {};
struct dim_luminous_intensity : base_dimension<"luminous intensity", candela> {};

}
namespace units::cgs {

using si::centimetre;
using si::gram;
using si::second;

struct dim_length : base_dimension<"length", centimetre> {};
struct dim_mass : base_dimension<"mass", gram> {};
using si::dim_time;

}

You ask "Is there a dependency of base_dimension on the particular system(s) in use as suggested here?". I think that the answer is no. Base dimensions do not depend on a system. They define one. A set of base dimensions for all system's base quantities yields a system of those base quantities.

They are not closed to this system. You can freely mix base dimensions from different systems to form one derived dimension (if one wishes so).

One more use case for this feature is not strictly connected to define a system of units but opens the doors to provide units that have the same dimensions but different units in the numerator and denominator like the Hubble parameter mentioned by Vincent Reverdy in https://wg21.link/p1930.

BTW, if you would like to discuss some stuff more interactively please reach me on Cpplang Slack. I really value your feedback. Thanks!

@kwikius
Copy link
Contributor Author

kwikius commented Dec 15, 2019

@mpusz That is very helpful. Thankyou.

@kwikius
Copy link
Contributor Author

kwikius commented Dec 15, 2019

I am wondering about the uses of template strings to uniquely identify base_dimension. 2 issues.

  1. If I am writing a pre c++2a library ( as I am), then I can't use them easily
  2. You cant reuse the name returned by the base_dimension in different quantity systems.

For uniquely identifying base_dimension, an alternative to string is a UUID
https://en.wikipedia.org/wiki/Universally_unique_identifier

No need to re-invent the wheel here either, since there are already some UUIDs assigned for(nearly) the purpose in the bluetooth specification, which are at least a standardised useful starting point to work from.
https://www.bluetooth.com/specifications/assigned-numbers/units/
The numbers used there are so called 'short form' UUIDs which stand in for the full length UUIDs where the number there is added to a reserved value.
One could reserve 'short form' UUIDs and require custom base_dimensions to use the full length UUID

@mpusz
Copy link
Owner

mpusz commented Dec 15, 2019

This is a library using c++20 features. Strings as NTTP is only one of many C++20 features used there and all of them will be the reason for your code to not compile on a pre C++20 compiler. Also, I do not care much about other strange quantity systems. If it is a physical "length" than just reuse it with the same name and a unit that is a base unit for length for this system of units (this exactly why base_dimension was refactored in a new design). If the length base dimension is really strange and does not conform to a physical system meaning of it than just it what it is a "strange length" as its identifier ;-)

With the above, I do not think that introducing UUID to the C++ Standard Library is a good idea here.

@kwikius
Copy link
Contributor Author

kwikius commented Dec 15, 2019

OK.

I have one other issue. I think this thing we are calling base_dimension, should be called base_quantity
See here in middle of the page. https://physics.nist.gov/cuu/Units/units.html

I renamed things in one branch of my library and I think it is much easier to read.

https://github.com/kwikius/pqs/blob/exposition_physical_base_unit/src/include/pqs/bits/dimension.hpp#L97

@mpusz
Copy link
Owner

mpusz commented Dec 16, 2019

I am really open to bikeshedding of names if needed, but in this particular case, I have a really strong opinion.

First of all, please note that I am fully aware of the official terms and definitions. If you do not have access to ISO 80000, you can find most of them in chapter 4.1 of my paper: https://wg21.link/p1935.

It is true that officially the SI specs define quantity (divided to a base and derived quantity) and "just" a dimension (no base or derived) that is a list of exponents. If I would like to follow exactly this nomenclature than:

  1. Length and all other SI base quantities would be handled by base_quantity class template
  2. All derived quantities would be handled by derived_quantity class template
  3. Both derived_quantity and base_quantity class templates would have nearly the same interface (and this is the biggest and the most complicated class of the library)
  4. Users would need to be aware when to instantiate a derived_quantity and when to instantiate a base_quantity (also in a generic code)

However, please note that ISO 80000, even in the official definitions chapter, often mentions dimensions of base quantities which clearly states that base quantities also have their own dimensions ;-). For example, the definition of dimension looks as follows:

expression of the dependence of a quantity on the base quantities of a system of quantities as a product of powers of factors corresponding to the base quantities, omitting any numerical factor. A power of a factor is the factor raised to an exponent. Each factor is the dimension of a base quantity.

Above clearly states that base quantities have their own dimensions that then are used to form exponents of a "dimension" (in our case derived_dimension). Also in the same derived dimension definition, there is a table that iterates all "symbols for dimensions" of "base quantities" (i.e. L for length). which clearly states that dimensions of base quantities have unique identifiers.

This is why I believe that in this particular case we are really OK with our design. From the implementation point of view I have to know which factor of a derived dimension definition is a base quantity and which is a derived one because if I get a derived one from the user than I have to unpack it to a list of base quantities. This is why we need to have two strong types in the design:

  • base_dimension
  • derived_dimension

As you know both have also different properties (i.e. base_dimension need a unique and sortable identifiers which is an implementation detail that ISO 80000 does not bother much about ;-) ).

I also believe that it is much easier for the user to have only one quantity abstraction that handles both base and derived quantities. Splitting this would complicate writing generic code a lot.

@mpusz mpusz closed this as completed Dec 29, 2019
Issues Kanban Board automation moved this from In progress to Done Dec 29, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
question Further information is requested
Projects
Development

No branches or pull requests

2 participants