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

docs(ref): document mp_units.core #628

Draft
wants to merge 218 commits into
base: master
Choose a base branch
from
Draft

Conversation

JohelEGP
Copy link
Collaborator

@JohelEGP JohelEGP commented Oct 18, 2024

This is still a WIP:

This is also blocked on
a number of minor points which I'll review later.

There are some TBDs, mainly for algorithms which need wording.
These are:

  • The quantity specification conversion algorithms.
  • The collapse common unit algorithms.
  • The formatting functions for dimensions and units.
  • The semantic requirements on the QuantityCharacterRepresentation concepts.
  • sudo_cast.

Work left (besides the TBDs above):

  • Text output.
  • Less priority:
    • system_reference
    • math.h
    • random.h

@mpusz
Copy link
Owner

mpusz commented Oct 19, 2024

This is great! Thanks!

Regarding magnitudes, please note that they are meant to be implementation-defined. Only a few user-facing API things are public (construction helpers (mag, mag_ratio, and mag_power), concept, operators, magnitude<...> where ... is implementation-defined).

Copy link
Owner

@mpusz mpusz left a comment

Choose a reason for hiding this comment

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

This is huge!!! Lots of great work! Thank you!!!

docs/api_reference/src/quantities.tex Outdated Show resolved Hide resolved
docs/api_reference/src/quantities.tex Outdated Show resolved Hide resolved
docs/api_reference/src/quantities.tex Outdated Show resolved Hide resolved
docs/api_reference/src/quantities.tex Outdated Show resolved Hide resolved
docs/api_reference/src/quantities.tex Outdated Show resolved Hide resolved
Copy link
Owner

Choose a reason for hiding this comment

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

How can we specify that some public identifiers should not be exported from the std module?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Reading https://wg21.link/std.modules, it seems like there's no way.

Copy link
Owner

Choose a reason for hiding this comment

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

I will ask LWG members

Choose a reason for hiding this comment

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

Dropping in mid-stream here -- is there a problem with marking them as exposition only? That basically says -- we're going to act like this thing exists in the standard, but we might implement it differently or call it something different.

Copy link
Owner

Choose a reason for hiding this comment

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

exposition-only is not a solution, as I wrote in the LWG reflector.

\label{term.quantity.type}
A \defnadj{quantity}{type}
is a type \tcode{\placeholder{Q}}
that is a specialization of \tcode{quantity} or \tcode{quantity_point}.
Copy link
Owner

Choose a reason for hiding this comment

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

There are some users that derive from quantity already. We support this in mp-units with derived_from. Should we remove this support?

This comment was marked as resolved.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Should we remove this support?

I've always been against it.
Do you have the related issue/PR numbers?
I hope to convince you to do that with my TBD review here.

Copy link
Owner

Choose a reason for hiding this comment

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

Copy link
Owner

Choose a reason for hiding this comment

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

This is controversial for me as well. In C++ we typically discourage people from inheriting from std types. It would be great if we could find a better solution here.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

The most glaring issue is that for a parameter constrained with
std::derived_from<quantity> or std::derived_from<quantity_point>,
the implementation doesn't convert to the quantity base subobject.

For example, in operator+:

  template<std::derived_from<quantity> Q, auto R2, typename Rep2>
    requires detail::CommonlyInvocableQuantities<std::plus<>, quantity, quantity<R2, Rep2>>
  [[nodiscard]] friend constexpr Quantity auto operator+(const Q& lhs, const quantity<R2, Rep2>& rhs)
  {
    using ret = detail::common_quantity_for<std::plus<>, quantity, quantity<R2, Rep2>>;
    const ret ret_lhs(lhs);

We need this conversion from Q, type of lhs, to ret,
to be the same as ret(static_cast<const quantity&>(lhs)).
The implementation doesn't do that (like as-variant),
so we need wording to require those parameter types
to not hide members
and prevent conversions like the above to have a different meaning.
Perhaps by requiring Q to behave as-if the base template in the specified wording
(e.g., by borrowing https://eel.is/c++draft/namespace.std#2.2).

Copy link
Owner

Choose a reason for hiding this comment

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

I do not oppose removing the support for deriving from a quantity.

docs/api_reference/src/quantities.tex Outdated Show resolved Hide resolved
docs/api_reference/src/quantities.tex Outdated Show resolved Hide resolved
docs/api_reference/src/quantities.tex Outdated Show resolved Hide resolved
@JohelEGP JohelEGP force-pushed the ref_docs branch 5 times, most recently from 05ab0a8 to 8bf5db5 Compare October 23, 2024 16:15
@mpusz
Copy link
Owner

mpusz commented Oct 23, 2024

Could you please not squash or rebase the branch?

It is impossible to track what changes between commits this way. I need to start reviewing all 2500 lines from scratch as I do not know what has changed.

Maybe provide something for merge and open another PR with additional changes?

@JohelEGP

This comment was marked as outdated.

@mpusz
Copy link
Owner

mpusz commented Oct 24, 2024

I try to review in LatTeX as it is easier to provide comments that way, and I also need to learn the syntax.

docs/api_reference/src/quantities.tex Outdated Show resolved Hide resolved
docs/api_reference/src/quantities.tex Outdated Show resolved Hide resolved
docs/api_reference/src/quantities.tex Show resolved Hide resolved
docs/api_reference/src/quantities.tex Outdated Show resolved Hide resolved
docs/api_reference/src/quantities.tex Outdated Show resolved Hide resolved
docs/api_reference/src/quantities.tex Show resolved Hide resolved
docs/api_reference/src/quantities.tex Outdated Show resolved Hide resolved
docs/api_reference/src/quantities.tex Outdated Show resolved Hide resolved
docs/api_reference/src/quantities.tex Outdated Show resolved Hide resolved
docs/api_reference/src/quantities.tex Outdated Show resolved Hide resolved
docs/api_reference/src/quantities.tex Outdated Show resolved Hide resolved
docs/api_reference/src/quantities.tex Outdated Show resolved Hide resolved
docs/api_reference/src/quantities.tex Outdated Show resolved Hide resolved
docs/api_reference/src/quantities.tex Outdated Show resolved Hide resolved
docs/api_reference/src/quantities.tex Outdated Show resolved Hide resolved
mpusz
mpusz previously approved these changes Nov 28, 2024
Comment on lines +91 to +93
template<std::intmax_t Num, std::intmax_t Den = 1, @\libconcept{Dimension}@ D>
requires(Den != 0)
consteval @\libconcept{Dimension}@ auto pow(D d);
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

This kind of ratio in template parameters only require that Den != 0.
However, ratio{Num, Den} would fail when Abs or Den is INTMAX_MAX due to abs.
Is that a problem in any of these interfaces?

Copy link
Owner

Choose a reason for hiding this comment

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

I don't know. I did not think about it so far. We may need dedicated Issues to track things like that.

Copy link
Collaborator Author

@JohelEGP JohelEGP left a comment

Choose a reason for hiding this comment

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

1732851043
has_associated_quantity and all_are_kinds share the navigation algorithm.
They only differ in the returned expression when U::_quantity_spec_ is valid.
The former returns true and the latter QuantityKindSpec<MP_UNITS_NONCONST_TYPE(U::_quantity_spec_)>.
The former also returns false when nothing works, whereas the latter returns nothing (I suppose it's guarded by the former).
You can factor out the navigation algorithm parameterized on the predicate.
Then the former simply becomes navigation_algorithm(always_true_unary_predicate{})
and the latter navigation_algorithm(nonconst_type_is_model_of_quantity_kind_spec{}).

@mpusz
Copy link
Owner

mpusz commented Nov 29, 2024

Actually, it is even better (or worse). It turns out that all_are_kinds are not needed anymore. It was needed at the beginning when I allowed any quantity spec to be used for a unit. Now we only allow kinds, so they are always kinds for an AssociatedUnit.

Comment on lines 4185 to 4189
template<typename FromRep, typename ToRep, auto FromUnit = one, auto ToUnit = one>
concept @\defexposconceptnc{ValuePreservingTo}@ =
requires(FromRep&& from, ToRep to) {
{ to = std::forward<FromRep>(from) } -> std::@\stdconcept{same_as}@<ToRep&>;
} &&
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Why not std::assignable_from<ToRep&, FromRep>?

\begin{itemdescr}
\pnum
\effects
Equivalent to \tcode{\exposidnc{sudo-cast}<quantity>(q)}\iref{qty.non.mem.conv}.
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

In code, this is actually the mem-initializer-list

      numerical_value_is_an_implementation_detail_(
        detail::sudo_cast<quantity>(q).numerical_value_is_an_implementation_detail_)

This makes a quantity temporary, to just jank-out its numerical value.
There would be no such temporary if instead the mem-initializer-list was
quantity(detail::sudo_cast<quantity>(q)).

Comment on lines 4937 to 4943
\pnum
\expects
If \tcode{@} is \tcode{\%=} or \tcode{/=}, then
\begin{codeblock}
@\placeholdernc{TO-NUMERICAL-VALUE}@(rhs) != representation_values<RhsRep>::zero()
\end{codeblock}
is \tcode{true}.
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

In code, this is operator%:

  template<detail::Mutable<quantity> Q, auto R2, typename Rep2>
    requires detail::QuantityConvertibleTo<quantity<R2, Rep2>, quantity> && (!treat_as_floating_point<rep>) &&
             requires(rep a, Rep2 b) {
               { a %= b } -> std::same_as<rep&>;
             }
  friend constexpr decltype(auto) operator%=(Q&& lhs, const quantity<R2, Rep2>& rhs)

  {
    MP_UNITS_EXPECTS_DEBUG(rhs != zero());

This compares rhs to lhs.zero().
There's no requirement that rep and Rep2 be equality comparable.
I suggest instead: MP_UNITS_EXPECTS_DEBUG(is_neq_zero(rhs));.
Similarly for other $x \neq 0$ contracts.
Or perhaps just prepend rhs. to zero(), as done elsewhere.

This one is also missing the contract:

  template<typename Value, std::derived_from<quantity> Q>
    requires(!Quantity<Value>) &&
            (!Reference<Value>) && detail::InvokeResultOf<quantity_spec, std::divides<>, const Value&, Rep>
  [[nodiscard]] friend constexpr Quantity auto operator/(const Value& val, const Q& q)
  {
    return ::mp_units::quantity{val / q.numerical_value_ref_in(unit), ::mp_units::one / R};
  }

Comment on lines 4968 to 4972
The expression in the \fakegrammarterm{requires-clause} is equivalent to:
\begin{codeblock}
(@\placeholder{C}@) && @\exposconceptnc{ValuePreservingTo}@<RhsRep, Rep> && requires {
{ lhs.@\exposid{numerical-value}@ @\atsign@ @\placeholdernc{TO-NUMERICAL-VALUE}@(rhs) } -> std::@\stdconcept{same_as}@<rep&>;
}
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

You can remove some of these requirements thanks to the new representation concepts.
For example, +'s

requires(rep a, Rep2 b) {
      { a += b } -> std::same_as<rep&>;
    }

When do you plan to do that?
Otherwise, those parameters also need to be made const for the implicit expression variations.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants