Line data Source code
1 : // SPDX-License-Identifier: BSD-3-Clause 2 : // Copyright (c) 2023 Scipp contributors (https://github.com/scipp) 3 : /// @file 4 : /// @author Simon Heybrock 5 : /// @author Neil Vaytet 6 : #pragma once 7 : 8 : #include <functional> 9 : #include <optional> 10 : #include <string> 11 : 12 : #include <units/unit_definitions.hpp> 13 : 14 : #include "scipp-units_export.h" 15 : 16 : namespace scipp::units { 17 : 18 : class SCIPP_UNITS_EXPORT Unit { 19 : public: 20 : constexpr Unit() = default; 21 182339 : constexpr explicit Unit(const llnl::units::precise_unit &u) noexcept 22 182339 : : m_unit(u) {} 23 : explicit Unit(const std::string &unit); 24 : 25 310661 : [[nodiscard]] constexpr bool has_value() const noexcept { 26 310661 : return m_unit.has_value(); 27 : } 28 645970 : [[nodiscard]] constexpr auto underlying() const { return m_unit.value(); } 29 : 30 : [[nodiscard]] std::string name() const; 31 : 32 : [[nodiscard]] bool isCounts() const; 33 : [[nodiscard]] bool isCountDensity() const; 34 : 35 : [[nodiscard]] bool has_same_base(const Unit &other) const; 36 : 37 : bool operator==(const Unit &other) const; 38 : bool operator!=(const Unit &other) const; 39 : 40 : Unit &operator+=(const Unit &other); 41 : Unit &operator-=(const Unit &other); 42 : Unit &operator*=(const Unit &other); 43 : Unit &operator/=(const Unit &other); 44 : Unit &operator%=(const Unit &other); 45 : 46 282 : template <class F> void map_over_bases(F &&f) const { 47 282 : const auto base_units = underlying().base_units(); 48 282 : f("m", base_units.meter()); 49 282 : f("kg", base_units.kg()); 50 282 : f("s", base_units.second()); 51 282 : f("A", base_units.ampere()); 52 282 : f("K", base_units.kelvin()); 53 282 : f("mol", base_units.mole()); 54 282 : f("cd", base_units.candela()); 55 282 : f("$", base_units.currency()); 56 282 : f("counts", base_units.count()); 57 282 : f("rad", base_units.radian()); 58 282 : } 59 : 60 282 : template <class F> void map_over_flags(F &&f) const { 61 282 : const auto base_units = underlying().base_units(); 62 282 : f("per_unit", base_units.is_per_unit()); 63 282 : f("i_flag", base_units.has_i_flag()); 64 282 : f("e_flag", base_units.has_e_flag()); 65 282 : f("equation", base_units.is_equation()); 66 282 : } 67 : 68 : private: 69 : std::optional<llnl::units::precise_unit> m_unit; 70 : }; 71 : 72 : SCIPP_UNITS_EXPORT Unit operator+(const Unit &a, const Unit &b); 73 : SCIPP_UNITS_EXPORT Unit operator-(const Unit &a, const Unit &b); 74 : SCIPP_UNITS_EXPORT Unit operator*(const Unit &a, const Unit &b); 75 : SCIPP_UNITS_EXPORT Unit operator/(const Unit &a, const Unit &b); 76 : SCIPP_UNITS_EXPORT Unit operator%(const Unit &a, const Unit &b); 77 : SCIPP_UNITS_EXPORT Unit operator-(const Unit &a); 78 : SCIPP_UNITS_EXPORT Unit abs(const Unit &a); 79 : SCIPP_UNITS_EXPORT Unit sqrt(const Unit &a); 80 : SCIPP_UNITS_EXPORT Unit pow(const Unit &a, int64_t power); 81 : SCIPP_UNITS_EXPORT Unit sin(const Unit &a); 82 : SCIPP_UNITS_EXPORT Unit cos(const Unit &a); 83 : SCIPP_UNITS_EXPORT Unit tan(const Unit &a); 84 : SCIPP_UNITS_EXPORT Unit asin(const Unit &a); 85 : SCIPP_UNITS_EXPORT Unit acos(const Unit &a); 86 : SCIPP_UNITS_EXPORT Unit atan(const Unit &a); 87 : SCIPP_UNITS_EXPORT Unit atan2(const Unit &y, const Unit &x); 88 : SCIPP_UNITS_EXPORT Unit sinh(const Unit &a); 89 : SCIPP_UNITS_EXPORT Unit cosh(const Unit &a); 90 : SCIPP_UNITS_EXPORT Unit tanh(const Unit &a); 91 : SCIPP_UNITS_EXPORT Unit asinh(const Unit &a); 92 : SCIPP_UNITS_EXPORT Unit acosh(const Unit &a); 93 : SCIPP_UNITS_EXPORT Unit atanh(const Unit &a); 94 : SCIPP_UNITS_EXPORT Unit floor(const Unit &a); 95 : SCIPP_UNITS_EXPORT Unit ceil(const Unit &a); 96 : SCIPP_UNITS_EXPORT Unit rint(const Unit &a); 97 : 98 : SCIPP_UNITS_EXPORT bool identical(const Unit &a, const Unit &b); 99 : 100 : SCIPP_UNITS_EXPORT void add_unit_alias(const std::string &name, 101 : const Unit &unit); 102 : SCIPP_UNITS_EXPORT void clear_unit_aliases(); 103 : 104 : constexpr Unit none{}; 105 : constexpr Unit dimensionless{llnl::units::precise::one}; 106 : constexpr Unit one{llnl::units::precise::one}; /// alias for dimensionless 107 : constexpr Unit m{llnl::units::precise::meter}; 108 : constexpr Unit s{llnl::units::precise::second}; 109 : constexpr Unit kg{llnl::units::precise::kg}; 110 : constexpr Unit K{llnl::units::precise::K}; 111 : constexpr Unit rad{llnl::units::precise::rad}; 112 : constexpr Unit deg{llnl::units::precise::deg}; 113 : constexpr Unit us{llnl::units::precise::micro * llnl::units::precise::second}; 114 : constexpr Unit ns{llnl::units::precise::ns}; 115 : constexpr Unit mm{llnl::units::precise::mm}; 116 : constexpr Unit counts{llnl::units::precise::count}; 117 : constexpr Unit angstrom{llnl::units::precise::distance::angstrom}; 118 : constexpr Unit meV{llnl::units::precise::milli * 119 : llnl::units::precise::energy::eV}; 120 : constexpr Unit c{ 121 : {llnl::units::precise::m / llnl::units::precise::s, 299792458}}; 122 : 123 : } // namespace scipp::units 124 : 125 : namespace std { 126 : template <> struct hash<scipp::units::Unit> { 127 10538 : std::size_t operator()(const scipp::units::Unit &u) const { 128 10538 : return hash<llnl::units::precise_unit>()(u.underlying()); 129 : } 130 : }; 131 : } // namespace std