News for hackers. Stuff that matters.
Re:Improving our safety with a physical quantities and units... by majorexception on Sunday December 24, 2023 @12:39PM (#38755073)
I have a project for which I wrote a simple units library. I don't think I'd be able to write any physics-related project now without using it (or a similar library). My Quantity class has a set of 8 parameters (7 SI base units and a hack that allows conversion between Hz and radians) + additional Scale and Offset parameters. Scale allows representing units other than SI (like Nautical Miles), Offset is for units like Celsius, for which 0°C == 273.15 K.

I can do things like:

    si::Length length = 15_m + 12_nm; // _nm for Nautical Miles
    si::Area area = 1_m * 1_km; // Equals to 1000_m2
    si::Power power = 1_m / 1_sec / 1_sec; // Compilation error, 1_m/s² is not a si::Power
I don't have every possible User-Defined Literal, of course, so I end up doing this for less common units:

    using SomeLocalTypeName = decltype(1_rpm / 1_V);
Something to thing about, when designing such library:

* What is 0_degC + 1_degC? 1_degC or… 273.15_K + 274.15_K = 547.3_K = 274.15_degC? I forbid operations between units if any of them has Offset parameter different than 0. I'm not sure if this is the good solution, though.

* Nm (Newton-meters) is the same unit as Joules. ;-)

Re:Improving our safety with a physical quantities and units... by pests on Sunday December 24, 2023 @01:21PM (#38755382)
For your first point about temp, the proper way would be to convert to Kelvin, do the addition, and back to Celsius.
Re:Improving our safety with a physical quantities and units... by majorexception on Sunday December 24, 2023 @02:15PM (#38755859)
Yup. So I explicitly deleted operators for °C, so things like 5_degC + 10_degC won't compile.
Re:Improving our safety with a physical quantities and units... by pests on Monday December 25, 2023 @01:50AM (#38760425)
But cant you just implement operator+(celcius, celcius) that will do the conversion to kelvin and back, since you know for certain the conversion math?
Re:Improving our safety with a physical quantities and units... by majorexception on Monday December 25, 2023 @04:36AM (#38761169)
I did that, but then adding 0_degC + 0_degC gave 273.15_degC. I think that would be surprising to many people. In reality I don't remember ever having to deal with physics formulas that used °C instead of Kelvins, so the only time I need to use °C is when presenting the temperature in the UI:

    temperature.in<si::Celsius>()
Re:Improving our safety with a physical quantities and units... by pests on Friday December 29, 2023 @04:54PM (#38810687)
Duh. I was thinking too much on the syntax side and not thinking about the physical world; which is ironic considering the discussion topic.
Re:Improving our safety with a physical quantities and units... by phanimahesh on Monday December 25, 2023 @06:44AM (#38761816)
Adding temperatures is not done usually. Mixing substances adds thermal energy. There's no reason I can hink of why allowing plus operator on temperatures is a good idea. You can add temperature differentials, but it is plain addition so long as units are in agreement. And 0C differential is 0F differential, no offsets in conversions.
Re:Improving our safety with a physical quantities and units... by Negitivefrags on Sunday December 24, 2023 @01:20PM (#38755365)
I’m not really a fan of the syntax in the article where you multiply the unit with the value.

I much prefer your user defined literal approach.

But is there any way to make it so you can introduce a new user defined literal for a new composed unit with reasonable syntax?

Re:Improving our safety with a physical quantities and units... by majorexception on Sunday December 24, 2023 @02:17PM (#38755877)
Something like this:

    auto
    operator"" _rpmPerVolt (long double x) {
        return decltype (1_rpm / 1_V)(x);
    }
I have a macro for that:

    #define SI_DEFINE_LITERAL(xUnit, xliteral) \
     [[nodiscard]] \
     constexpr Quantity<units::xUnit> \
     operator"" xliteral (long double value) \
     {  \
         return Quantity<units::xUnit> (value); \
     } \
     \
     [[nodiscard]] \
     constexpr Quantity<units::xUnit> \
     operator"" xliteral (unsigned long long value) \
     { \
         return Quantity<units::xUnit> (value); \
     }

    // Base SI units:
    SI_DEFINE_LITERAL (Meter, _m)
    SI_DEFINE_LITERAL (Kilogram, _kg)
    SI_DEFINE_LITERAL (Second, _s)
    SI_DEFINE_LITERAL (Ampere, _A)
    SI_DEFINE_LITERAL (Kelvin, _K)
    SI_DEFINE_LITERAL (Mole, _mol)
    SI_DEFINE_LITERAL (Candela, _cd)
    SI_DEFINE_LITERAL (Radian, _rad)
...and a loong list of other common units here.

The additional types are defined like this, in another file:

    using Foot          = ScaledUnit<Meter, std::ratio<1'200, 3'937>>;
    using Mile          = ScaledUnit<Meter, std::ratio<1'609'344, 1'000>>;
    using NauticalMile  = ScaledUnit<Meter, std::ratio<1'852, 1>>;
    using Inch          = ScaledUnit<Meter, std::ratio<254, 10'000>>;
And then I use SI_DEFINE_LITERAL (NauticalMile, _nm); etc.
Re:Improving our safety with a physical quantities and units... by thfuran on Tuesday December 26, 2023 @04:55AM (#38770328)
Yeah, Celsius is awkward because it's basically used as both an actual temperature and as an interval depending on context, and mixing them is bad news. A similar sort of distinction often shows up in datetime libraries between an instant and a duration/timespan, but I'm not sure it's worth doing in a unit library. Just forcing kelvin for intervals probably isn't too onerous for most uses, and I can't think of any unit it would really apply to other than °C/F, whosoever dares mix units of measure with time zones notwithstanding.