Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-08-06 09:38:20

0001 // -*- C++ -*-
0002 //
0003 // PhysicalQty.h is a part of ThePEG - Toolkit for HEP Event Generation
0004 // Copyright (C) 2006-2019 David Grellscheid, Leif Lonnblad
0005 //
0006 // ThePEG is licenced under version 3 of the GPL, see COPYING for details.
0007 // Please respect the MCnet academic guidelines, see GUIDELINES for details.
0008 //
0009 #ifndef Physical_Qty_H
0010 #define Physical_Qty_H
0011 #include "TemplateTools.h"
0012 #include <sstream>
0013 #include <ratio>
0014 #include <type_traits>
0015 
0016 /** @file 
0017  *
0018  * The PhysicalQty class allows compile-time checking of dimensional
0019  * correctness. Mathematical operations that are inconsistent are
0020  * flagged as type errors.
0021  *
0022  * Do not use the classes directly in ThePEG, use the wrappers defined
0023  * in Units.h or Phys_Qty.h instead.
0024  */
0025 
0026 namespace ThePEG {
0027 
0028 /// Helper class to construct zero unitful quantities.
0029 struct ZeroUnit {
0030   /** Automatic conversion to double. */
0031   constexpr operator double() const { return 0.0; }
0032 };
0033 
0034 /// ZERO can be used as zero for any unitful quantity.
0035 constexpr ZeroUnit ZERO = ZeroUnit();
0036 
0037 /**
0038  * This template class allows the compiler to check calculations with
0039  * physical quantities for dimensional correctness. A quantity can be
0040  * composed of arbitrary fractional powers of length L, energy E and
0041  * charge Q. Commonly used quantities should be typedef'ed (see Units.h).
0042  *
0043  * Some member functions can break dimensional consistency if the user
0044  * is not careful; these are marked explicitly.
0045  *
0046  * Do not use this class directly in ThePEG, use the pre-defined quantities
0047  * from Units.h or the wrapper in Phys_Qty.h instead.
0048  */
0049 
0050 // only specialization is with std::ratio below
0051 template <typename L, typename E, typename T>
0052 class Qty;
0053 
0054 template <typename T, typename U>
0055 struct qty_equal {
0056   static constexpr bool value = false;
0057 };
0058 
0059 template<typename L1, typename L2, typename E1, typename E2, typename Q1, typename Q2>
0060 struct qty_equal<Qty<L1,E1,Q1>, Qty<L2,E2,Q2>> {
0061   static constexpr bool value
0062     =  std::ratio_equal<L1,L2>::value 
0063     && std::ratio_equal<E1,E2>::value
0064     && std::ratio_equal<Q1,Q2>::value;
0065 };
0066 
0067 template <typename T>
0068 struct is_qty {
0069   static constexpr bool value = qty_equal<T,T>::value;
0070 };
0071 
0072 template <typename ResultT, typename T, typename U = T>
0073 using enable_if_same_qty = typename std::enable_if<qty_equal<T,U>::value, ResultT>::type;
0074 
0075 template<long int L, long int E, long int Q, long int DL, long int DE, long int DQ>
0076 class Qty<std::ratio<L,DL>, std::ratio<E,DE>, std::ratio<Q,DQ>>
0077 {
0078 private:
0079   /// Constructor from raw values. Breaks consistency.
0080   constexpr Qty(double val) : rawValue_(val) {}
0081 
0082 public:
0083 
0084   /// The name of the class for persistent IO
0085   static std::string className() {
0086     std::ostringstream os;
0087     os << "Qty<" 
0088        <<  L << ','
0089        <<  E << ','
0090        <<  Q << ','
0091        << DL << ','
0092        << DE << ','
0093        << DQ << '>';
0094       
0095     return os.str();
0096   }
0097 
0098   /// General power type
0099   template <long int Num, long int Den>
0100   using Power = Qty<typename std::ratio<Num*L,Den*DL>::type, 
0101                     typename std::ratio<Num*E,Den*DE>::type, 
0102                     typename std::ratio<Num*Q,Den*DQ>::type>;
0103   /// Our type
0104   using Type    = Power<1,1>;
0105   /// The squared type.
0106   using Squared = Power<2,1>;
0107   /// The inverse type.
0108   using Inverse = Power<-1,1>;
0109   /// The sqrt type.
0110   using Sqrt    = Power<1,2>;
0111 
0112   /// Basic unit of this quantity.
0113   static constexpr Type baseunit() 
0114   {
0115     return Type(1.0);
0116   }
0117 
0118   /// Default constructor to 0.
0119   constexpr Qty() : rawValue_(0.0) {}
0120 
0121   /// Default constructor to 0.
0122   constexpr Qty(ZeroUnit) : rawValue_(0.0) {}
0123 
0124   /// Constructor from a compatible quantity
0125   template <typename U>
0126   constexpr Qty(const U & q, double factor = 1.0, 
0127                 enable_if_same_qty<void,Type,U> * = nullptr)
0128     : rawValue_(q.rawValue() * factor) {}
0129 
0130   /// Access to the raw value. Breaks consistency.
0131   constexpr double rawValue() const { return rawValue_; }
0132 
0133   /// Assignment multiplication by dimensionless number.
0134   Type & operator*=(double x) { rawValue_ *= x; return *this; }
0135 
0136   /// Assignment division by dimensionless number.
0137   Type & operator/=(double x) { rawValue_ /= x; return *this; }
0138 
0139   /// Assignment addition with compatible quantity.
0140   Type & operator+=(const Type & x) 
0141   { 
0142     rawValue_ += x.rawValue(); 
0143     return *this; 
0144   }
0145 
0146   /// Assignment subtraction with compatible quantity.
0147   Type & operator-=(const Type & x) 
0148   { 
0149     rawValue_ -= x.rawValue(); 
0150     return *this; 
0151   }
0152 
0153 private:
0154   /// The raw value in units of Qty::baseunit().
0155   double rawValue_;
0156 };
0157 
0158 /// Specialization of Qty for <0,0,0> with conversions to double.
0159 template<>
0160 class Qty<std::ratio<0>,std::ratio<0>,std::ratio<0>>
0161 {
0162 public:
0163   /// Our type
0164   using Type    = Qty<std::ratio<0>,std::ratio<0>,std::ratio<0>>;
0165   /// General power type
0166   template <long int Num, long int Den>
0167   using Power   = Type;
0168   /// The squared type.
0169   using Squared = Type;
0170   /// The inverse type.
0171   using Inverse = Type;
0172   /// The sqrt type.
0173   using Sqrt    = Type;
0174 
0175 
0176   /// Basic unit of this quantity.
0177   static constexpr Type baseunit() {
0178     return 1.0;
0179   }
0180 
0181   /// Default constructor to 0.
0182   constexpr Qty(ZeroUnit) : rawValue_(0.0) {}
0183 
0184   /// Default constructor from a double.
0185   constexpr Qty(double x = 0.0, double factor=1.0) 
0186     : rawValue_(x * factor) {}
0187 
0188   /// Constructor from a compatible quantity
0189   template <typename U>
0190   constexpr Qty(const U & q, double factor=1.0, 
0191                 enable_if_same_qty<void,Type,U> * = nullptr)
0192    : rawValue_(q.rawValue() * factor) {}
0193 
0194   /// Access to the raw value.
0195   constexpr double rawValue() const { return rawValue_; }
0196 
0197   /// Cast to double.
0198   constexpr operator double() const { return rawValue_; }
0199 
0200   /// Assignment multiplication by dimensionless number.
0201   Type & operator*=(double x) { rawValue_ *= x; return *this; }
0202 
0203   /// Assignment division by dimensionless number.
0204   Type & operator/=(double x) { rawValue_ /= x; return *this; }
0205 
0206   /// Assignment addition with compatible quantity.
0207   Type & operator+=(const Type & x) { 
0208     rawValue_ += x.rawValue(); 
0209     return *this; 
0210   }
0211 
0212   /// Assignment subtraction with compatible quantity.
0213   Type & operator-=(const Type & x) { 
0214     rawValue_ -= x.rawValue(); 
0215     return *this; 
0216   }
0217 
0218   /// Assignment addition with double.
0219   Type & operator+=(double x) { 
0220     rawValue_ += x; 
0221     return *this; 
0222   }
0223 
0224   /// Assignment subtraction with double.
0225   Type & operator-=(double x) { 
0226     rawValue_ -= x; 
0227     return *this; 
0228   }
0229 
0230 private:
0231   /// The raw value.
0232   double rawValue_;
0233 };
0234 
0235 using QtyDouble = Qty<std::ratio<0>,std::ratio<0>,std::ratio<0>>;
0236 
0237 /// @name Result types for binary operations.
0238 //@{
0239 /**
0240  * BinaryOpTraits should be specialized with typdefs called MulT and
0241  * DivT which gives the type resulting when multiplying and dividing
0242  * the template argument types respectively.
0243  */
0244 template <typename T, typename U> 
0245 struct BinaryOpTraits;
0246 
0247 /** @cond TRAITSPECIALIZATIONS */
0248 
0249 template<typename L1, typename L2, 
0250          typename E1, typename E2, 
0251          typename Q1, typename Q2>
0252 struct BinaryOpTraits<Qty<L1,E1,Q1>, Qty<L2,E2,Q2>> {
0253   /** The type resulting from multiplication of the template type with
0254       itself. */
0255   typedef Qty<std::ratio_add<L1,L2>,
0256               std::ratio_add<E1,E2>,
0257               std::ratio_add<Q1,Q2>> MulT;
0258   /** The type resulting from division of one template type with
0259       another. */
0260   typedef Qty<std::ratio_subtract<L1,L2>,
0261               std::ratio_subtract<E1,E2>,
0262               std::ratio_subtract<Q1,Q2>> DivT;
0263 };
0264 
0265 /**
0266  *  Multiplication template
0267  */
0268 template<typename L, typename E, typename Q>
0269 struct BinaryOpTraits<double, Qty<L,E,Q>> {
0270   /** The type resulting from multiplication of the template type */
0271   typedef Qty<L,E,Q> MulT;
0272   /** The type resulting from division of the template type */
0273   typedef typename BinaryOpTraits<QtyDouble, Qty<L,E,Q>>::DivT DivT;
0274 };
0275 
0276 /**
0277  *  Multiplication template
0278  */
0279 template<typename L, typename E, typename Q>
0280 struct BinaryOpTraits<Qty<L,E,Q>, double> {
0281   /** The type resulting from multiplication of the template type */
0282   typedef Qty<L,E,Q> MulT;
0283   /** The type resulting from division of the template type */
0284   typedef Qty<L,E,Q> DivT;
0285 };
0286 //@}
0287 
0288 /// @name Type traits for alternative code generation.
0289 //@{
0290 /** Type traits for alternative code generation*/
0291 template <typename L, typename E, typename Q>
0292 struct TypeTraits<Qty<L,E,Q>>
0293 {
0294   /** Enum for dimensions*/
0295   enum { hasDimension = true };
0296   /// Type switch set to dimensioned type.
0297   typedef DimensionT DimType;
0298   /// Base unit
0299   static constexpr Qty<L,E,Q> baseunit() 
0300     { return Qty<L,E,Q>::baseunit(); }
0301 };
0302 
0303 /** Type traits for alternative code generation*/
0304 template <> 
0305 struct TypeTraits<QtyDouble>
0306 {
0307   /** Enum for dimensions*/
0308   enum { hasDimension = false };
0309   /// Type switch set to standard type.
0310   typedef StandardT DimType;
0311   /// Base unit
0312   static constexpr QtyDouble baseunit() { return 1.0; }
0313 };
0314 
0315 //@}
0316 
0317 /** @endcond */
0318 
0319 }
0320 
0321 #endif