File indexing completed on 2025-09-17 08:54:08
0001
0002
0003
0004
0005
0006
0007 #pragma once
0008
0009 #include <type_traits>
0010
0011 #include "corecel/Macros.hh"
0012 #include "corecel/Types.hh"
0013
0014 #include "detail/QuantityImpl.hh"
0015
0016 namespace celeritas
0017 {
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
0078 template<class UnitT, class ValueT>
0079 class Quantity
0080 {
0081 public:
0082
0083
0084 using value_type = ValueT;
0085 using unit_type = UnitT;
0086 using unit_value_type = decltype(UnitT::value());
0087 using common_type = decltype(std::declval<value_type>()
0088 * std::declval<unit_value_type>());
0089
0090
0091 public:
0092
0093 constexpr Quantity() = default;
0094
0095
0096 explicit CELER_CONSTEXPR_FUNCTION Quantity(value_type value) noexcept
0097 : value_(value)
0098 {
0099 }
0100
0101
0102 template<detail::QConstant QC>
0103 CELER_CONSTEXPR_FUNCTION Quantity(detail::UnitlessQuantity<QC>) noexcept
0104 : value_(detail::get_constant<ValueT>(QC))
0105 {
0106 }
0107
0108
0109
0110 CELER_CONSTEXPR_FUNCTION value_type& value() & noexcept { return value_; }
0111 CELER_CONSTEXPR_FUNCTION value_type const& value() const& noexcept
0112 {
0113 return value_;
0114 }
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 template<class UnitT>
0127 using RealQuantity = Quantity<UnitT, real_type>;
0128
0129
0130
0131 #define CELER_DEFINE_QUANTITY_CMP(TOKEN) \
0132 template<class U, class T, class T2> \
0133 CELER_CONSTEXPR_FUNCTION bool operator TOKEN( \
0134 Quantity<U, T> lhs, Quantity<U, T2> rhs) noexcept \
0135 { \
0136 return lhs.value() TOKEN rhs.value(); \
0137 } \
0138 template<class U, class T, detail::QConstant QC> \
0139 CELER_CONSTEXPR_FUNCTION bool operator TOKEN( \
0140 Quantity<U, T> lhs, detail::UnitlessQuantity<QC>) noexcept \
0141 { \
0142 return lhs.value() TOKEN detail::get_constant<T>(QC); \
0143 } \
0144 template<class U, class T, detail::QConstant QC> \
0145 CELER_CONSTEXPR_FUNCTION bool operator TOKEN( \
0146 detail::UnitlessQuantity<QC>, Quantity<U, T> rhs) noexcept \
0147 { \
0148 return detail::get_constant<T>(QC) TOKEN rhs.value(); \
0149 } \
0150 namespace detail \
0151 { \
0152 template<detail::QConstant C1, detail::QConstant C2> \
0153 CELER_CONSTEXPR_FUNCTION bool \
0154 operator TOKEN(detail::UnitlessQuantity<C1>, \
0155 detail::UnitlessQuantity<C2>) noexcept \
0156 { \
0157 return static_cast<int>(C1) TOKEN static_cast<int>(C2); \
0158 } \
0159 }
0160
0161
0162
0163 CELER_DEFINE_QUANTITY_CMP(==)
0164 CELER_DEFINE_QUANTITY_CMP(!=)
0165 CELER_DEFINE_QUANTITY_CMP(<)
0166 CELER_DEFINE_QUANTITY_CMP(>)
0167 CELER_DEFINE_QUANTITY_CMP(<=)
0168 CELER_DEFINE_QUANTITY_CMP(>=)
0169
0170
0171 #undef CELER_DEFINE_QUANTITY_CMP
0172
0173
0174
0175 template<class U, class T, class T2>
0176 CELER_CONSTEXPR_FUNCTION auto
0177 operator+(Quantity<U, T> lhs, Quantity<U, T2> rhs) noexcept
0178 {
0179 return Quantity<U, std::common_type_t<T, T2>>{lhs.value() + rhs.value()};
0180 }
0181
0182 template<class U, class T, class T2>
0183 CELER_CONSTEXPR_FUNCTION auto
0184 operator-(Quantity<U, T> lhs, Quantity<U, T2> rhs) noexcept
0185 {
0186 return Quantity<U, std::common_type_t<T, T2>>{lhs.value() - rhs.value()};
0187 }
0188
0189 template<class U, class T, class T2>
0190 CELER_CONSTEXPR_FUNCTION auto
0191 operator/(Quantity<U, T> lhs, Quantity<U, T2> rhs) noexcept
0192 {
0193 return lhs.value() / rhs.value();
0194 }
0195
0196 template<class U, class T>
0197 CELER_CONSTEXPR_FUNCTION auto operator-(Quantity<U, T> q) noexcept
0198 {
0199 return Quantity<U, T>{-q.value()};
0200 }
0201
0202 template<class U, class T, class T2>
0203 CELER_CONSTEXPR_FUNCTION auto operator*(Quantity<U, T> lhs, T2 rhs) noexcept
0204 {
0205 return Quantity<U, std::common_type_t<T, T2>>{lhs.value() * rhs};
0206 }
0207
0208 template<class T, class U, class T2>
0209 CELER_CONSTEXPR_FUNCTION auto operator*(T rhs, Quantity<U, T2> lhs) noexcept
0210 {
0211 return Quantity<U, std::common_type_t<T, T2>>{rhs * lhs.value()};
0212 }
0213
0214 template<class U, class T, class T2>
0215 CELER_CONSTEXPR_FUNCTION auto operator/(Quantity<U, T> lhs, T2 rhs) noexcept
0216 {
0217 return Quantity<U, std::common_type_t<T, T2>>{lhs.value() / rhs};
0218 }
0219
0220
0221
0222
0223
0224
0225
0226
0227
0228
0229
0230 CELER_CONSTEXPR_FUNCTION auto zero_quantity() noexcept
0231 {
0232 return detail::UnitlessQuantity<detail::QConstant::zero>{};
0233 }
0234
0235
0236
0237
0238
0239 CELER_CONSTEXPR_FUNCTION auto max_quantity() noexcept
0240 {
0241 return detail::UnitlessQuantity<detail::QConstant::max>{};
0242 }
0243
0244
0245
0246
0247
0248 CELER_CONSTEXPR_FUNCTION auto neg_max_quantity() noexcept
0249 {
0250 return detail::UnitlessQuantity<detail::QConstant::neg_max>{};
0251 }
0252
0253
0254
0255
0256
0257 template<class U, class V>
0258 CELER_CONSTEXPR_FUNCTION void
0259 swap(Quantity<U, V>& a, Quantity<U, V>& b) noexcept
0260 {
0261 Quantity<U, V> tmp{a};
0262 a = b;
0263 b = tmp;
0264 }
0265
0266
0267
0268
0269
0270
0271
0272
0273
0274
0275 template<class UnitT, class ValueT>
0276 CELER_CONSTEXPR_FUNCTION auto
0277 native_value_from(Quantity<UnitT, ValueT> quant) noexcept
0278 {
0279 using common_type = typename Quantity<UnitT, ValueT>::common_type;
0280 return static_cast<common_type>(quant.value())
0281 * static_cast<common_type>(UnitT::value());
0282 }
0283
0284
0285
0286
0287
0288
0289
0290
0291
0292
0293
0294 template<class Q, class T>
0295 CELER_CONSTEXPR_FUNCTION Q native_value_to(T value) noexcept
0296 {
0297 using common_type = typename Q::common_type;
0298 using value_type = typename Q::value_type;
0299 constexpr auto unit_value = Q::unit_type::value();
0300 return Q{
0301 static_cast<value_type>(value / static_cast<common_type>(unit_value))};
0302 }
0303
0304
0305
0306
0307
0308
0309
0310
0311
0312
0313
0314
0315 template<class Q, class SrcUnitT, class ValueT>
0316 CELER_CONSTEXPR_FUNCTION auto
0317 value_as(Quantity<SrcUnitT, ValueT> quant) noexcept -> ValueT
0318 {
0319 static_assert(std::is_same<Q, Quantity<SrcUnitT, ValueT>>::value,
0320 "quantity units do not match");
0321 return quant.value();
0322 }
0323
0324
0325
0326
0327
0328
0329
0330
0331
0332
0333 template<class T>
0334 inline char const* accessor_unit_label()
0335 {
0336 return detail::AccessorResultType<T>::unit_type::label();
0337 }
0338
0339
0340 }