File indexing completed on 2025-01-18 09:54:49
0001
0002
0003
0004
0005
0006
0007
0008 #pragma once
0009
0010 #include <type_traits>
0011
0012 #include "corecel/Macros.hh"
0013 #include "corecel/Types.hh"
0014
0015 #include "detail/QuantityImpl.hh"
0016
0017 namespace celeritas
0018 {
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037
0038
0039
0040
0041
0042
0043
0044
0045
0046
0047
0048
0049
0050
0051
0052
0053
0054
0055
0056
0057
0058
0059
0060
0061
0062
0063
0064
0065
0066
0067
0068
0069
0070
0071
0072
0073
0074
0075
0076
0077 template<class UnitT, class ValueT = decltype(UnitT::value())>
0078 class Quantity
0079 {
0080 public:
0081
0082
0083 using value_type = ValueT;
0084 using unit_type = UnitT;
0085
0086
0087 public:
0088
0089 constexpr Quantity() = default;
0090
0091
0092 explicit CELER_CONSTEXPR_FUNCTION Quantity(value_type value) noexcept
0093 : value_(value)
0094 {
0095 }
0096
0097
0098 template<detail::QConstant QC>
0099 CELER_CONSTEXPR_FUNCTION Quantity(detail::UnitlessQuantity<QC>) noexcept
0100 : value_(detail::get_constant<ValueT>(QC))
0101 {
0102 }
0103
0104
0105
0106 #define CELER_DEFINE_QACCESS(FUNC, QUAL) \
0107 CELER_CONSTEXPR_FUNCTION value_type QUAL FUNC() QUAL noexcept \
0108 { \
0109 return value_; \
0110 }
0111
0112 CELER_DEFINE_QACCESS(value, &)
0113 CELER_DEFINE_QACCESS(value, const&)
0114 #undef CELER_DEFINE_QACCESS
0115
0116
0117
0118 CELER_CONSTEXPR_FUNCTION value_type const* data() const { return &value_; }
0119
0120 private:
0121 value_type value_{};
0122 };
0123
0124
0125
0126 #define CELER_DEFINE_QUANTITY_CMP(TOKEN) \
0127 template<class U, class T, class T2> \
0128 CELER_CONSTEXPR_FUNCTION bool operator TOKEN( \
0129 Quantity<U, T> lhs, Quantity<U, T2> rhs) noexcept \
0130 { \
0131 return lhs.value() TOKEN rhs.value(); \
0132 } \
0133 template<class U, class T, detail::QConstant QC> \
0134 CELER_CONSTEXPR_FUNCTION bool operator TOKEN( \
0135 Quantity<U, T> lhs, detail::UnitlessQuantity<QC>) noexcept \
0136 { \
0137 return lhs.value() TOKEN detail::get_constant<T>(QC); \
0138 } \
0139 template<class U, class T, detail::QConstant QC> \
0140 CELER_CONSTEXPR_FUNCTION bool operator TOKEN( \
0141 detail::UnitlessQuantity<QC>, Quantity<U, T> rhs) noexcept \
0142 { \
0143 return detail::get_constant<T>(QC) TOKEN rhs.value(); \
0144 } \
0145 namespace detail \
0146 { \
0147 template<detail::QConstant C1, detail::QConstant C2> \
0148 CELER_CONSTEXPR_FUNCTION bool \
0149 operator TOKEN(detail::UnitlessQuantity<C1>, \
0150 detail::UnitlessQuantity<C2>) noexcept \
0151 { \
0152 return static_cast<int>(C1) TOKEN static_cast<int>(C2); \
0153 } \
0154 }
0155
0156
0157
0158 CELER_DEFINE_QUANTITY_CMP(==)
0159 CELER_DEFINE_QUANTITY_CMP(!=)
0160 CELER_DEFINE_QUANTITY_CMP(<)
0161 CELER_DEFINE_QUANTITY_CMP(>)
0162 CELER_DEFINE_QUANTITY_CMP(<=)
0163 CELER_DEFINE_QUANTITY_CMP(>=)
0164
0165
0166 #undef CELER_DEFINE_QUANTITY_CMP
0167
0168
0169
0170 template<class U, class T, class T2>
0171 CELER_CONSTEXPR_FUNCTION auto
0172 operator+(Quantity<U, T> lhs, Quantity<U, T2> rhs) noexcept -> decltype(auto)
0173 {
0174 return Quantity<U, std::common_type_t<T, T2>>{lhs.value() + rhs.value()};
0175 }
0176
0177 template<class U, class T, class T2>
0178 CELER_CONSTEXPR_FUNCTION auto
0179 operator-(Quantity<U, T> lhs, Quantity<U, T2> rhs) noexcept -> decltype(auto)
0180 {
0181 return Quantity<U, std::common_type_t<T, T2>>{lhs.value() - rhs.value()};
0182 }
0183
0184 template<class U, class T>
0185 CELER_CONSTEXPR_FUNCTION auto
0186 operator-(Quantity<U, T> q) noexcept -> Quantity<U, T>
0187 {
0188 return Quantity<U, T>{-q.value()};
0189 }
0190
0191 template<class U, class T, class T2>
0192 CELER_CONSTEXPR_FUNCTION auto
0193 operator*(Quantity<U, T> lhs, T2 rhs) noexcept -> decltype(auto)
0194 {
0195 return Quantity<U, std::common_type_t<T, T2>>{lhs.value() * rhs};
0196 }
0197
0198 template<class T, class U, class T2>
0199 CELER_CONSTEXPR_FUNCTION auto
0200 operator*(T rhs, Quantity<U, T2> lhs) noexcept -> decltype(auto)
0201 {
0202 return Quantity<U, std::common_type_t<T, T2>>{rhs * lhs.value()};
0203 }
0204
0205 template<class U, class T, class T2>
0206 CELER_CONSTEXPR_FUNCTION auto
0207 operator/(Quantity<U, T> lhs, T2 rhs) noexcept -> decltype(auto)
0208 {
0209 return Quantity<U, std::common_type_t<T, T2>>{lhs.value() / rhs};
0210 }
0211
0212
0213
0214
0215
0216
0217
0218
0219
0220 CELER_CONSTEXPR_FUNCTION auto zero_quantity() noexcept
0221 {
0222 return detail::UnitlessQuantity<detail::QConstant::zero>{};
0223 }
0224
0225
0226
0227
0228
0229 CELER_CONSTEXPR_FUNCTION auto max_quantity() noexcept
0230 {
0231 return detail::UnitlessQuantity<detail::QConstant::max>{};
0232 }
0233
0234
0235
0236
0237
0238 CELER_CONSTEXPR_FUNCTION auto neg_max_quantity() noexcept
0239 {
0240 return detail::UnitlessQuantity<detail::QConstant::neg_max>{};
0241 }
0242
0243
0244
0245
0246
0247 template<class U, class V>
0248 CELER_CONSTEXPR_FUNCTION void
0249 swap(Quantity<U, V>& a, Quantity<U, V>& b) noexcept
0250 {
0251 Quantity<U, V> tmp{a};
0252 a = b;
0253 b = tmp;
0254 }
0255
0256
0257
0258
0259
0260
0261
0262
0263
0264
0265 template<class UnitT, class ValueT>
0266 CELER_CONSTEXPR_FUNCTION auto
0267 native_value_from(Quantity<UnitT, ValueT> quant) noexcept -> decltype(auto)
0268 {
0269 return quant.value() * UnitT::value();
0270 }
0271
0272
0273
0274
0275
0276
0277
0278
0279
0280
0281
0282
0283
0284 template<class Q>
0285 CELER_CONSTEXPR_FUNCTION Q native_value_to(typename Q::value_type value) noexcept
0286 {
0287 return Q{value / Q::unit_type::value()};
0288 }
0289
0290
0291
0292
0293
0294
0295
0296
0297
0298
0299
0300
0301 template<class Q, class SrcUnitT, class ValueT>
0302 CELER_CONSTEXPR_FUNCTION auto
0303 value_as(Quantity<SrcUnitT, ValueT> quant) noexcept -> ValueT
0304 {
0305 static_assert(std::is_same<Q, Quantity<SrcUnitT, ValueT>>::value,
0306 "quantity units do not match");
0307 return quant.value();
0308 }
0309
0310
0311
0312
0313
0314
0315
0316
0317
0318
0319 template<class T>
0320 inline char const* accessor_unit_label()
0321 {
0322 return detail::AccessorResultType<T>::unit_type::label();
0323 }
0324
0325
0326 }