mpusz / mp-units

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

Measurement in IAU #464

Open mpusz opened 1 year ago

mpusz commented 1 year ago

Improve and productize a measurement class and use it in the definition of the IAU system based on https://web.archive.org/web/20131110215339/http://asa.usno.navy.mil/static/files/2014/Astronomical_Constants_2014.pdf.

mpusz commented 8 months ago

It seems that the IAU is not the only library customer for such a utility. #510 mentioned plenty of constants that are also specified with some uncertainty that might change over the years if we get a better way to measure them.

mpusz commented 8 months ago

We should also study what Python did for a similar feature: https://pythonhosted.org/uncertainties.

mpusz commented 8 months ago

https://en.wikipedia.org/wiki/Propagation_of_uncertainty

RalphSteinhagen commented 8 months ago

Some additional resources of interest might be:

RalphSteinhagen commented 7 months ago

image xkcd.com CC BY-NC 2.5 DEED

Hi @mpusz and @mattkretz, I have been working a bit on the concept of propagation of uncertainties. The implementation is showcased in this compiler-explorer example. The core of this implementation is based on the UncertainValue struct, handling both uncorrelated and correlated uncertainties.

enum class Correlation { UnCorrelated, Correlated };

template <is_arithmetic_or_complex_v T, Correlation correlation>
struct UncertainValue;

template <is_arithmetic_or_complex_v T>
struct UncertainValue<T, Correlation::UnCorrelated> {
    using value_type = T;

    T value;                            /// stores the mean value
    T uncertainty = static_cast<T>(0);  /// stores the standard deviation of the value

   UncertainValue(T val, T uncert) : value(val), uncertainty(uncert) {}
};
template <typename T>
UncertainValue(T, T) -> UncertainValue<T, Correlation::UnCorrelated>;

template <is_arithmetic_or_complex_v T>
struct UncertainValue<T, Correlation::Correlated> {
    using value_type = T;

    T value;                            /// stores the mean value
    T uncertainty = static_cast<T>(0);  /// stores the standard deviation of the value
    std::uint64_t correlationID = 0UZ;  /// correlation ID - fully correlated if ID1==ID2 - issue: redundant 8bytes for each samples

   UncertainValue(T val, T uncert, std::uint64_t correlationID_ = get_unique_id()) : value(val), uncertainty(uncert), correlationID(correlationID_) {}
};
template <typename T>
UncertainValue(T, T, std::uint64_t) -> UncertainValue<T, Correlation::Correlated>;

Notably, I'd would like your input on:

I appreciate any insights, comments, or suggestions you can provide to improve this implementation. Your expertise in this area is invaluable.

mpusz commented 7 months ago

Hi @RalphSteinhagen, thanks for sharing this nice code! I am on vacation now, so I did not have much time for this review. I will probably come back to you with more details when I will learn more about handling uncertainties.

For now, a really short feedback:

RalphSteinhagen commented 7 months ago
  • Your types definitely need constexpr and [[nodiscard]]

Absolutely ... :see_no_evil: ... was a bit q-n-d for this concept.

  • UncertainValueType concept could do is_specialization_of check instead

I'd prefer to test w.r.t. the functionality rather than the actual implementation. This should help composition and help users to have parallel functionally equivalent implementation of the struct.

  • The members should not be publically exposed ...

This is IMO a longer discussion to be had. There are pros/cons for both sides that need to be evaluated.