Page Menu
Home
HEPForge
Search
Configure Global Search
Log In
Files
F8309980
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Flag For Later
Size
177 KB
Subscribers
None
View Options
diff --git a/Config/Complex.h b/Config/Complex.h
--- a/Config/Complex.h
+++ b/Config/Complex.h
@@ -1,82 +1,28 @@
// -*- C++ -*-
//
// Complex.h is a part of ThePEG - Toolkit for HEP Event Generation
// Copyright (C) 1999-2017 Leif Lonnblad
//
// ThePEG is licenced under version 3 of the GPL, see COPYING for details.
// Please respect the MCnet academic guidelines, see GUIDELINES for details.
//
#ifndef ThePEG_Complex_H
#define ThePEG_Complex_H
//
// This is file wraps the standard complex header and makes some
// convenient typedefs in the ThePEG namespace.
//
#include <complex>
namespace ThePEG {
using std::complex;
-/** ThePEG code should use Complex for all complex scalars */
-typedef std::complex<double> Complex;
-
-/** @cond TRAITSPECIALIZATIONS */
-
-template <typename T, typename U>
-struct BinaryOpTraits;
-
-
-template <typename T, typename U>
-struct BinaryOpTraits<complex<T>, U> {
- /** The type resulting from multiplication of the template type with
- itself. */
- typedef complex<typename BinaryOpTraits<T,U>::MulT> MulT;
- /** The type resulting from division of one template type with
- another. */
- typedef complex<typename BinaryOpTraits<T,U>::DivT> DivT;
-
-};
-
-template <typename T, typename U>
-struct BinaryOpTraits<T, complex<U> > {
- /** The type resulting from multiplication of the template type with
- itself. */
- typedef complex<typename BinaryOpTraits<T,U>::MulT> MulT;
- /** The type resulting from division of one template type with
- another. */
- typedef complex<typename BinaryOpTraits<T,U>::DivT> DivT;
-
-};
-
-template <typename T, typename U>
-struct BinaryOpTraits<complex<T>, complex<U> > {
- /** The type resulting from multiplication of the template type with
- itself. */
- typedef complex<typename BinaryOpTraits<T,U>::MulT> MulT;
- /** The type resulting from division of one template type with
- another. */
- typedef complex<typename BinaryOpTraits<T,U>::DivT> DivT;
-
-};
-
-template <typename T>
-struct BinaryOpTraits<complex<T>, complex<T> > {
- /** The type resulting from multiplication of the template type with
- itself. */
- typedef complex<typename BinaryOpTraits<T,T>::MulT> MulT;
- /** The type resulting from division of one template type with
- another. */
- typedef complex<typename BinaryOpTraits<T,T>::DivT> DivT;
-
- /** @endcond */
-
-};
-
-
+/// ThePEG code should use Complex for all complex scalars
+using Complex = std::complex<double>;
}
#endif /* ThePEG_Complex_H */
diff --git a/Config/PhysicalQty.h b/Config/PhysicalQty.h
--- a/Config/PhysicalQty.h
+++ b/Config/PhysicalQty.h
@@ -1,337 +1,321 @@
// -*- C++ -*-
//
// PhysicalQty.h is a part of ThePEG - Toolkit for HEP Event Generation
// Copyright (C) 2006-2017 David Grellscheid, Leif Lonnblad
//
// ThePEG is licenced under version 3 of the GPL, see COPYING for details.
// Please respect the MCnet academic guidelines, see GUIDELINES for details.
//
#ifndef Physical_Qty_H
#define Physical_Qty_H
#include "TemplateTools.h"
#include <sstream>
+#include <ratio>
+#include <type_traits>
/** @file
*
* The PhysicalQty class allows compile-time checking of dimensional
* correctness. Mathematical operations that are inconsistent are
* flagged as type errors.
*
* Do not use the classes directly in ThePEG, use the wrappers defined
* in Units.h or Phys_Qty.h instead.
*/
namespace ThePEG {
/// Helper class to construct zero unitful quantities.
struct ZeroUnit {
/** Automatic conversion to double. */
constexpr operator double() const { return 0.0; }
};
/// ZERO can be used as zero for any unitful quantity.
constexpr ZeroUnit ZERO = ZeroUnit();
-/// Helper classes to extend or shorten fractions
-//@{
-/**
- * Template to help with fractional powers of dimensions
- */
-template <int M, int II>
-struct QtyHelper
-{
- /// The numerator, indicating failure.
- static constexpr int I = -999999;
-};
-
-/**
- * Template to help with fractional powers of dimensions
- */
-template <int II>
-struct QtyHelper<0,II>
-{
- /// The new numerator.
- static constexpr int I = II;
-};
-
-/**
- * Template to help with fractional powers of dimensions
- */
-template <int II, int DI, int DI2>
-struct QtyInt
-{
- /// The new numerator.
- static constexpr int I = QtyHelper<(DI2*II)%DI,(DI2*II)/DI>::I;
-};
-//@}
-
/**
* This template class allows the compiler to check calculations with
* physical quantities for dimensional correctness. A quantity can be
* composed of arbitrary fractional powers of length L, energy E and
* charge Q. Commonly used quantities should be typedef'ed (see Units.h).
*
* Some member functions can break dimensional consistency if the user
* is not careful; these are marked explicitly.
*
* Do not use this class directly in ThePEG, use the pre-defined quantities
* from Units.h or the wrapper in Phys_Qty.h instead.
*/
-template<int L, int E, int Q, int DL = 1, int DE = 1, int DQ = 1>
-class Qty
+
+// only specialization is with std::ratio below
+template <typename L, typename E, typename T>
+class Qty;
+
+template <typename T, typename U>
+struct qty_equal {
+ static constexpr bool value = false;
+};
+
+template<typename L1, typename L2, typename E1, typename E2, typename Q1, typename Q2>
+struct qty_equal<Qty<L1,E1,Q1>, Qty<L2,E2,Q2>> {
+ static constexpr bool value
+ = std::ratio_equal<L1,L2>::value
+ && std::ratio_equal<E1,E2>::value
+ && std::ratio_equal<Q1,Q2>::value;
+};
+
+template <typename T>
+struct is_qty {
+ static constexpr bool value = qty_equal<T,T>::value;
+};
+
+template <typename ResultT, typename T, typename U = T>
+using enable_if_same_qty = typename std::enable_if<qty_equal<T,U>::value, ResultT>::type;
+
+template<int L, int E, int Q, int DL, int DE, int DQ>
+class Qty<std::ratio<L,DL>, std::ratio<E,DE>, std::ratio<Q,DQ>>
{
private:
/// Constructor from raw values. Breaks consistency.
constexpr Qty(double val) : rawValue_(val) {}
public:
/// The name of the class for persistent IO
static std::string className() {
std::ostringstream os;
os << "Qty<"
<< L << ','
<< E << ','
<< Q << ','
<< DL << ','
<< DE << ','
<< DQ << '>';
return os.str();
}
-
+ /// General power type
+ template <int Num, int Den>
+ using Power = Qty<typename std::ratio<Num*L,Den*DL>::type,
+ typename std::ratio<Num*E,Den*DE>::type,
+ typename std::ratio<Num*Q,Den*DQ>::type>;
+ /// Our type
+ using Type = Power<1,1>;
/// The squared type.
- typedef Qty<2*L,2*E,2*Q,DL,DE,DQ> Squared;
+ using Squared = Power<2,1>;
+ /// The inverse type.
+ using Inverse = Power<-1,1>;
+ /// The sqrt type.
+ using Sqrt = Power<1,2>;
/// Basic unit of this quantity.
- static constexpr Qty<L,E,Q,DL,DE,DQ> baseunit()
+ static constexpr Type baseunit()
{
- return Qty<L,E,Q,DL,DE,DQ>(1.0);
+ return Type(1.0);
}
/// Default constructor to 0.
constexpr Qty() : rawValue_(0.0) {}
/// Default constructor to 0.
constexpr Qty(ZeroUnit) : rawValue_(0.0) {}
/// Constructor from a compatible quantity
- template <int DL2, int DE2, int DQ2>
- constexpr
- Qty(const Qty<QtyInt<L,DL,DL2>::I,
- QtyInt<E,DE,DE2>::I,
- QtyInt<Q,DQ,DQ2>::I,
- DL2,DE2,DQ2> & q,
- double factor = 1.0)
+ template <typename U>
+ constexpr Qty(const U & q, double factor = 1.0,
+ enable_if_same_qty<void,Type,U> * = nullptr)
: rawValue_(q.rawValue() * factor) {}
/// Access to the raw value. Breaks consistency.
constexpr double rawValue() const { return rawValue_; }
/// Assignment multiplication by dimensionless number.
- Qty<L,E,Q,DL,DE,DQ> & operator*=(double x) { rawValue_ *= x; return *this; }
+ Type & operator*=(double x) { rawValue_ *= x; return *this; }
/// Assignment division by dimensionless number.
- Qty<L,E,Q,DL,DE,DQ> & operator/=(double x) { rawValue_ /= x; return *this; }
+ Type & operator/=(double x) { rawValue_ /= x; return *this; }
/// Assignment addition with compatible quantity.
- template <int DL2, int DE2, int DQ2>
- Qty<L,E,Q,DL,DE,DQ> &
- operator+=(const Qty<QtyInt<L,DL,DL2>::I,
- QtyInt<E,DE,DE2>::I,
- QtyInt<Q,DQ,DQ2>::I,
- DL2,DE2,DQ2> x)
+ Type & operator+=(const Type & x)
{
rawValue_ += x.rawValue();
return *this;
}
/// Assignment subtraction with compatible quantity.
- template <int DL2, int DE2, int DQ2>
- Qty<L,E,Q,DL,DE,DQ> &
- operator-=(const Qty<QtyInt<L,DL,DL2>::I,
- QtyInt<E,DE,DE2>::I,
- QtyInt<Q,DQ,DQ2>::I,
- DL2,DE2,DQ2> x)
+ Type & operator-=(const Type & x)
{
rawValue_ -= x.rawValue();
return *this;
}
private:
/// The raw value in units of Qty::baseunit().
double rawValue_;
};
/// Specialization of Qty for <0,0,0> with conversions to double.
-template<int DL, int DE, int DQ>
-class Qty<0,0,0,DL,DE,DQ>
+template<>
+class Qty<std::ratio<0>,std::ratio<0>,std::ratio<0>>
{
public:
+ /// Our type
+ using Type = Qty<std::ratio<0>,std::ratio<0>,std::ratio<0>>;
+ /// General power type
+ template <int Num, int Den>
+ using Power = Type;
/// The squared type.
- typedef double Squared;
+ using Squared = Type;
+ /// The inverse type.
+ using Inverse = Type;
+ /// The sqrt type.
+ using Sqrt = Type;
+
/// Basic unit of this quantity.
- static constexpr double baseunit() {
+ static constexpr Type baseunit() {
return 1.0;
}
/// Default constructor to 0.
constexpr Qty(ZeroUnit) : rawValue_(0.0) {}
/// Default constructor from a double.
constexpr Qty(double x = 0.0, double factor=1.0)
: rawValue_(x * factor) {}
/// Constructor from a compatible quantity
- template <int DL2, int DE2, int DQ2>
- constexpr
- Qty(const Qty<0,0,0,DL2,DE2,DQ2> & q, double factor=1.0)
+ template <typename U>
+ constexpr Qty(const U & q, double factor=1.0,
+ enable_if_same_qty<void,Type,U> * = nullptr)
: rawValue_(q.rawValue() * factor) {}
/// Access to the raw value.
constexpr double rawValue() const { return rawValue_; }
/// Cast to double.
constexpr operator double() const { return rawValue_; }
/// Assignment multiplication by dimensionless number.
- Qty<0,0,0,DL,DE,DQ> & operator*=(double x) { rawValue_ *= x; return *this; }
+ Type & operator*=(double x) { rawValue_ *= x; return *this; }
/// Assignment division by dimensionless number.
- Qty<0,0,0,DL,DE,DQ> & operator/=(double x) { rawValue_ /= x; return *this; }
+ Type & operator/=(double x) { rawValue_ /= x; return *this; }
/// Assignment addition with compatible quantity.
- template <int DL2, int DE2, int DQ2>
- Qty<0,0,0,DL,DE,DQ> & operator+=(const Qty<0,0,0,DL2,DE2,DQ2> x) {
+ Type & operator+=(const Type & x) {
rawValue_ += x.rawValue();
return *this;
}
/// Assignment subtraction with compatible quantity.
- template <int DL2, int DE2, int DQ2>
- Qty<0,0,0,DL,DE,DQ> & operator-=(const Qty<0,0,0,DL2,DE2,DQ2> x) {
+ Type & operator-=(const Type & x) {
rawValue_ -= x.rawValue();
return *this;
}
/// Assignment addition with double.
- Qty<0,0,0,DL,DE,DQ> & operator+=(double x) {
+ Type & operator+=(double x) {
rawValue_ += x;
return *this;
}
/// Assignment subtraction with double.
- Qty<0,0,0,DL,DE,DQ> & operator-=(double x) {
+ Type & operator-=(double x) {
rawValue_ -= x;
return *this;
}
private:
/// The raw value.
double rawValue_;
};
+using QtyDouble = Qty<std::ratio<0>,std::ratio<0>,std::ratio<0>>;
+
/// @name Result types for binary operations.
//@{
/**
* BinaryOpTraits should be specialized with typdefs called MulT and
* DivT which gives the type resulting when multiplying and dividing
* the template argument types respectively.
*/
template <typename T, typename U>
struct BinaryOpTraits;
/** @cond TRAITSPECIALIZATIONS */
-template<int L1, int L2, int E1, int E2, int Q1, int Q2,
- int DL1, int DL2, int DE1, int DE2, int DQ1, int DQ2>
-struct BinaryOpTraits<Qty<L1,E1,Q1,DL1,DE1,DQ1>,
- Qty<L2,E2,Q2,DL2,DE2,DQ2> > {
+template<typename L1, typename L2,
+ typename E1, typename E2,
+ typename Q1, typename Q2>
+struct BinaryOpTraits<Qty<L1,E1,Q1>, Qty<L2,E2,Q2>> {
/** The type resulting from multiplication of the template type with
itself. */
- typedef Qty<L1*DL2+L2*DL1,E1*DE2+E2*DE1,Q1*DQ2+Q2*DQ1,
- DL1*DL2,DE1*DE2,DQ1*DQ2> MulT;
+ typedef Qty<std::ratio_add<L1,L2>,
+ std::ratio_add<E1,E2>,
+ std::ratio_add<Q1,Q2>> MulT;
/** The type resulting from division of one template type with
another. */
- typedef Qty<L1*DL2-L2*DL1,E1*DE2-E2*DE1,Q1*DQ2-Q2*DQ1,
- DL1*DL2,DE1*DE2,DQ1*DQ2> DivT;
-};
-
-
-template<int L1, int E1, int Q1, int DL1, int DE1, int DQ1>
-struct BinaryOpTraits<Qty<L1,E1,Q1,DL1,DE1,DQ1>,
- Qty<L1,E1,Q1,DL1,DE1,DQ1> > {
- /** The type resulting from multiplication of the template type with
- itself. */
- typedef Qty<2*L1,2*E1,2*Q1,
- DL1,DE1,DQ1> MulT;
- /** The type resulting from division of one template type with
- another. */
- typedef double DivT;
+ typedef Qty<std::ratio_subtract<L1,L2>,
+ std::ratio_subtract<E1,E2>,
+ std::ratio_subtract<Q1,Q2>> DivT;
};
/**
* Multiplication template
*/
-template<int L1, int E1, int Q1, int DL1, int DE1, int DQ1>
-struct BinaryOpTraits<double,
- Qty<L1,E1,Q1,DL1,DE1,DQ1> > {
+template<typename L, typename E, typename Q>
+struct BinaryOpTraits<double, Qty<L,E,Q>> {
/** The type resulting from multiplication of the template type */
- typedef Qty<L1,E1,Q1,
- DL1,DE1,DQ1> MulT;
+ typedef Qty<L,E,Q> MulT;
/** The type resulting from division of the template type */
- typedef Qty<-L1,-E1,-Q1,
- DL1,DE1,DQ1> DivT;
+ typedef typename BinaryOpTraits<QtyDouble, Qty<L,E,Q>>::DivT DivT;
};
/**
* Multiplication template
*/
-template<int L1, int E1, int Q1, int DL1, int DE1, int DQ1>
-struct BinaryOpTraits<Qty<L1,E1,Q1,DL1,DE1,DQ1>,
- double> {
+template<typename L, typename E, typename Q>
+struct BinaryOpTraits<Qty<L,E,Q>, double> {
/** The type resulting from multiplication of the template type */
- typedef Qty<L1,E1,Q1,
- DL1,DE1,DQ1> MulT;
+ typedef Qty<L,E,Q> MulT;
/** The type resulting from division of the template type */
- typedef Qty<L1,E1,Q1,
- DL1,DE1,DQ1> DivT;
+ typedef Qty<L,E,Q> DivT;
};
//@}
/// @name Type traits for alternative code generation.
//@{
/** Type traits for alternative code generation*/
-template <int L, int E, int Q, int DL, int DE, int DQ>
-struct TypeTraits<Qty<L,E,Q,DL,DE,DQ> >
+template <typename L, typename E, typename Q>
+struct TypeTraits<Qty<L,E,Q>>
{
/** Enum for dimensions*/
enum { hasDimension = true };
/// Type switch set to dimensioned type.
typedef DimensionT DimType;
/// Base unit
- static constexpr Qty<L,E,Q,DL,DE,DQ> baseunit()
- { return Qty<L,E,Q,DL,DE,DQ>::baseunit(); }
+ static constexpr Qty<L,E,Q> baseunit()
+ { return Qty<L,E,Q>::baseunit(); }
};
/** Type traits for alternative code generation*/
-template <int DL, int DE, int DQ>
-struct TypeTraits<Qty<0,0,0,DL,DE,DQ> >
+template <>
+struct TypeTraits<QtyDouble>
{
/** Enum for dimensions*/
enum { hasDimension = false };
/// Type switch set to standard type.
typedef StandardT DimType;
/// Base unit
- static constexpr double baseunit() { return 1.0; }
+ static constexpr QtyDouble baseunit() { return 1.0; }
};
//@}
/** @endcond */
}
#endif
diff --git a/Config/PhysicalQtyComplex.h b/Config/PhysicalQtyComplex.h
--- a/Config/PhysicalQtyComplex.h
+++ b/Config/PhysicalQtyComplex.h
@@ -1,330 +1,284 @@
// -*- C++ -*-
//
// PhysicalQtyComplex.h is a part of ThePEG - Toolkit for HEP Event Generation
// Copyright (C) 2006-2017 David Grellscheid, Leif Lonnblad
//
// ThePEG is licenced under version 3 of the GPL, see COPYING for details.
// Please respect the MCnet academic guidelines, see GUIDELINES for details.
//
#ifndef Physical_Qty_Complex_H
#define Physical_Qty_Complex_H
+#include "PhysicalQty.h"
+#include "PhysicalQtyOps.h"
#include <complex>
/** @file PhysicalQtyComplex.h
* Overloads for operations on complex physical quantities.
*/
namespace std {
/**
* Template specialization for std::complex<Qty<0,0,0> >
* with conversions to complex<double>
*/
- template<int DL, int DE, int DQ>
- class complex<ThePEG::Qty<0,0,0,DL,DE,DQ> >
+ template<>
+ class complex<ThePEG::QtyDouble>
{
public:
/// Default constructor
constexpr complex(double r=0.0, double i=0.0)
: rawValue_(r,i) {}
/// Constructor from complex<double>
constexpr complex(complex<double> C)
: rawValue_(C) {}
/**
* The internal representation of the dimensionful quantity.
* Using this will break dimension-consistency.
*/
constexpr complex<double> rawValue() const { return rawValue_; }
/// Real part
constexpr double real() const { return rawValue_.real(); }
/// Imaginary part
constexpr double imag() const { return rawValue_.imag(); }
/// Cast to complex<double>
constexpr operator complex<double>() const {
return rawValue_;
}
/// Addition-assignment
- complex<ThePEG::Qty<0,0,0,DL,DE,DQ> > &
- operator+=(const complex<ThePEG::Qty<0,0,0,DL,DE,DQ> > x) {
+ complex<ThePEG::QtyDouble> &
+ operator+=(const complex<ThePEG::QtyDouble> x) {
rawValue_ += x.rawValue();
return *this;
}
/// Subtraction-assignment
- complex<ThePEG::Qty<0,0,0,DL,DE,DQ> > &
- operator-=(const complex<ThePEG::Qty<0,0,0,DL,DE,DQ> > x) {
+ complex<ThePEG::QtyDouble> &
+ operator-=(const complex<ThePEG::QtyDouble> x) {
rawValue_ -= x.rawValue();
return *this;
}
private:
/// Internal value of the dimensioned quantity
complex<double> rawValue_;
};
}
// =========================================
namespace ThePEG {
/// @name Overloads for mathematical operations
//@{
// complex qty = complex qty * complex qty
-template<int L1, int L2, int E1, int E2, int Q1, int Q2,
- int DL1, int DL2, int DE1, int DE2, int DQ1, int DQ2>
-inline constexpr std::complex<Qty<L1*DL2+L2*DL1,E1*DE2+E2*DE1,Q1*DQ2+Q2*DQ1,
- DL1*DL2,DE1*DE2,DQ1*DQ2> >
-operator*(std::complex<Qty<L1,E1,Q1,DL1,DE1,DQ1> > q1,
- std::complex<Qty<L2,E2,Q2,DL2,DE2,DQ2> > q2) {
- typedef std::complex<Qty<L1*DL2+L2*DL1,E1*DE2+E2*DE1,Q1*DQ2+Q2*DQ1,
- DL1*DL2,DE1*DE2,DQ1*DQ2> > RetT;
- return RetT(q1.real()*q2.real() - q1.imag()*q2.imag(),
- q1.real()*q2.imag() + q1.imag()*q2.real());
+template<typename L1, typename E1, typename Q1,
+ typename L2, typename E2, typename Q2>
+inline constexpr auto
+operator*(std::complex<Qty<L1,E1,Q1>> q1,
+ std::complex<Qty<L2,E2,Q2>> q2)
+-> std::complex<decltype(q1.real()*q2.real())>
+{
+ return {q1.real()*q2.real() - q1.imag()*q2.imag(),
+ q1.real()*q2.imag() + q1.imag()*q2.real()};
}
// complex qty = complex qty * complex qty
-template<int L, int E, int Q, int DL, int DE, int DQ>
-inline constexpr std::complex<Qty<2*L,2*E,2*Q,DL,DE,DQ> >
-operator*(std::complex<Qty<L,E,Q,DL,DE,DQ> > q1,
- std::complex<Qty<L,E,Q,DL,DE,DQ> > q2) {
- typedef std::complex<Qty<2*L,2*E,2*Q,DL,DE,DQ> > RetT;
- return RetT(q1.real()*q2.real() - q1.imag()*q2.imag(),
- q1.real()*q2.imag() + q1.imag()*q2.real());
+template<typename L, typename E, typename Q>
+inline constexpr std::complex<typename Qty<L,E,Q>::Squared>
+operator*(std::complex<Qty<L,E,Q>> q1,
+ std::complex<Qty<L,E,Q>> q2)
+{
+ return {q1.real()*q2.real() - q1.imag()*q2.imag(),
+ q1.real()*q2.imag() + q1.imag()*q2.real()};
}
// complex qty = complex double - complex qty
-template<int DL, int DE, int DQ>
inline constexpr std::complex<double>
-operator-(std::complex<double> q1,
- std::complex<Qty<0,0,0,DL,DE,DQ> > q2) {
- typedef std::complex<double> RetT;
- return RetT(q1.real()-q2.real(),q1.imag()-q2.imag());
+operator-(std::complex<double> q1, std::complex<QtyDouble> q2) {
+ return {q1.real()-q2.real(), q1.imag()-q2.imag()};
}
// complex qty = complex double * complex qty
-template<int L, int E, int Q, int DL, int DE, int DQ>
-inline constexpr std::complex<Qty<L,E,Q,DL,DE,DQ> >
-operator*(std::complex<double> q1,
- std::complex<Qty<L,E,Q,DL,DE,DQ> > q2) {
- typedef std::complex<Qty<L,E,Q,DL,DE,DQ> > RetT;
- return RetT(q1.real()*q2.real() - q1.imag()*q2.imag(),
- q1.real()*q2.imag() + q1.imag()*q2.real());
+template<typename L, typename E, typename Q>
+inline constexpr std::complex<Qty<L,E,Q>>
+operator*(std::complex<double> q1, std::complex<Qty<L,E,Q>> q2) {
+ return {q1.real()*q2.real() - q1.imag()*q2.imag(),
+ q1.real()*q2.imag() + q1.imag()*q2.real()};
}
// complex qty = complex double / complex qty
-template<int L, int E, int Q, int DL, int DE, int DQ>
-inline std::complex<Qty<-L,-E,-Q,DL,DE,DQ> >
-operator/(std::complex<double> q1,
- std::complex<Qty<L,E,Q,DL,DE,DQ> > q2) {
- typedef std::complex<Qty<-L,-E,-Q,DL,DE,DQ> > RetT;
- std::complex<Qty<L,E,Q,DL,DE,DQ> > tmp = q1*conj(q2);
- Qty<2*L,2*E,2*Q,DL,DE,DQ> norm = (q2*conj(q2)).real();
- return RetT(tmp.real()/norm,tmp.imag()/norm);
+template<typename L, typename E, typename Q>
+inline std::complex<typename Qty<L,E,Q>::Inverse>
+operator/(std::complex<double> q1, std::complex<Qty<L,E,Q>> q2) {
+ auto tmp = q1*conj(q2);
+ auto norm = (q2*conj(q2)).real();
+ return {tmp.real()/norm, tmp.imag()/norm};
}
// complex qty = complex double / qty
-template<int L, int E, int Q, int DL, int DE, int DQ>
-inline constexpr std::complex<Qty<-L,-E,-Q,DL,DE,DQ> >
-operator/(std::complex<double> q1,
- Qty<L,E,Q,DL,DE,DQ> q2) {
- typedef std::complex<Qty<-L,-E,-Q,DL,DE,DQ> > RetT;
- return RetT(q1.real()/q2,q1.imag()/q2);
+template<typename L, typename E, typename Q>
+inline constexpr std::complex<typename Qty<L,E,Q>::Inverse>
+operator/(std::complex<double> q1, Qty<L,E,Q> q2) {
+ return {q1.real()/q2, q1.imag()/q2};
}
// complex qty = complex qty / complex double
-template<int L, int E, int Q, int DL, int DE, int DQ>
-inline std::complex<Qty<L,E,Q,DL,DE,DQ> >
-operator/(std::complex<Qty<L,E,Q,DL,DE,DQ> > q1,
- std::complex<double> q2) {
- std::complex<Qty<L,E,Q,DL,DE,DQ> > tmp = q1*conj(q2);
- double norm = (q2*conj(q2)).real();
- return std::complex<Qty<L,E,Q,DL,DE,DQ> >(tmp.real()/norm,tmp.imag()/norm);
+template<typename L, typename E, typename Q>
+inline std::complex<Qty<L,E,Q>>
+operator/(std::complex<Qty<L,E,Q>> q1, std::complex<double> q2) {
+ auto tmp = q1*conj(q2);
+ auto norm = (q2*conj(q2)).real();
+ return {tmp.real()/norm, tmp.imag()/norm};
}
// complex qty = qty / complex double
-template<int L, int E, int Q, int DL, int DE, int DQ>
-inline std::complex<Qty<L,E,Q,DL,DE,DQ> >
-operator/(Qty<L,E,Q,DL,DE,DQ> q1,
- std::complex<double> q2) {
- std::complex<Qty<L,E,Q,DL,DE,DQ> > tmp = q1*conj(q2);
- double norm = (q2*conj(q2)).real();
- return std::complex<Qty<L,E,Q,DL,DE,DQ> >(tmp.real()/norm,tmp.imag()/norm);
+template<typename L, typename E, typename Q>
+inline std::complex<Qty<L,E,Q>>
+operator/(Qty<L,E,Q> q1, std::complex<double> q2) {
+ auto tmp = q1*conj(q2);
+ auto norm = (q2*conj(q2)).real();
+ return {tmp.real()/norm, tmp.imag()/norm};
}
// complex double = complex qty / complex qty
-template<int L, int E, int Q, int DL, int DE, int DQ>
+template<typename L, typename E, typename Q>
inline std::complex<double>
-operator/(std::complex<Qty<L,E,Q,DL,DE,DQ> > q1,
- std::complex<Qty<L,E,Q,DL,DE,DQ> > q2) {
- std::complex<Qty<2*L,2*E,2*Q,DL,DE,DQ> > tmp = q1*conj(q2);
- Qty<2*L,2*E,2*Q,DL,DE,DQ> norm = (q2*conj(q2)).real();
- return std::complex<double>(tmp.real()/norm,tmp.imag()/norm);
+operator/(std::complex<Qty<L,E,Q>> q1,
+ std::complex<Qty<L,E,Q>> q2) {
+ auto tmp = q1*conj(q2);
+ auto norm = (q2*conj(q2)).real();
+ return {tmp.real()/norm, tmp.imag()/norm};
}
// complex double = qty / complex qty
-template<int L, int E, int Q, int DL, int DE, int DQ>
+template<typename L, typename E, typename Q>
inline std::complex<double>
-operator/(Qty<L,E,Q,DL,DE,DQ> q1,
- std::complex<Qty<L,E,Q,DL,DE,DQ> > q2) {
- std::complex<Qty<2*L,2*E,2*Q,DL,DE,DQ> > tmp = q1*conj(q2);
- Qty<2*L,2*E,2*Q,DL,DE,DQ> norm = (q2*conj(q2)).real();
- return std::complex<double>(tmp.real()/norm,tmp.imag()/norm);
+operator/(Qty<L,E,Q> q1, std::complex<Qty<L,E,Q>> q2) {
+ auto tmp = q1*conj(q2);
+ auto norm = (q2*conj(q2)).real();
+ return {tmp.real()/norm, tmp.imag()/norm};
}
// complex double = complex qty / qty
-template<int L, int E, int Q, int DL, int DE, int DQ>
+template<typename L, typename E, typename Q>
inline constexpr std::complex<double>
-operator/(std::complex<Qty<L,E,Q,DL,DE,DQ> > q1,
- Qty<L,E,Q,DL,DE,DQ> q2) {
- return std::complex<double>(q1.real()/q2,q1.imag()/q2);
+operator/(std::complex<Qty<L,E,Q>> q1, Qty<L,E,Q> q2) {
+ return {q1.real()/q2, q1.imag()/q2};
}
// complex qty = complex qty / complex qty
-template<int L1, int L2, int E1, int E2, int Q1, int Q2,
- int DL1, int DL2, int DE1, int DE2, int DQ1, int DQ2>
-inline std::complex<Qty<L1*DL2-L2*DL1,E1*DE2-E2*DE1,Q1*DQ2-Q2*DQ1,DL1*DL2,DE1*DE2,DQ1*DQ2> >
-operator/(std::complex<Qty<L1,E1,Q1,DL1,DE1,DQ1> > q1,
- std::complex<Qty<L2,E2,Q2,DL2,DE2,DQ2> > q2) {
- typedef std::complex<Qty<L1*DL2-L2*DL1,E1*DE2-E2*DE1,Q1*DQ2-Q2*DQ1,
- DL1*DL2,DE1*DE2,DQ1*DQ2> > RetT;
- std::complex<Qty<L1*DL2+L2*DL1,E1*DE2+E2*DE1,Q1*DQ2+Q2*DQ1,
- DL1*DL2,DE1*DE2,DQ1*DQ2> > tmp = q1*conj(q2);
- Qty<2*L2,2*E2,2*Q2,DL2,DE2,DQ2> norm = (q2*conj(q2)).real();
- return RetT(tmp.real()/norm,tmp.imag()/norm);
+template<typename L1, typename E1, typename Q1,
+ typename L2, typename E2, typename Q2>
+inline auto
+operator/(std::complex<Qty<L1,E1,Q1>> q1,
+ std::complex<Qty<L2,E2,Q2>> q2)
+-> std::complex<decltype(q1.real()/q2.real())>
+{
+ auto tmp = q1*conj(q2);
+ auto norm = (q2*conj(q2)).real();
+ return {tmp.real()/norm, tmp.imag()/norm};
}
// complex qty = qty / complex qty
-template<int L1, int L2, int E1, int E2, int Q1, int Q2,
- int DL1, int DL2, int DE1, int DE2, int DQ1, int DQ2>
-inline std::complex<Qty<L1*DL2-L2*DL1,E1*DE2-E2*DE1,Q1*DQ2-Q2*DQ1,DL1*DL2,DE1*DE2,DQ1*DQ2> >
-operator/(Qty<L1,E1,Q1,DL1,DE1,DQ1> q1,
- std::complex<Qty<L2,E2,Q2,DL2,DE2,DQ2> > q2) {
- typedef std::complex<Qty<L1*DL2-L2*DL1,E1*DE2-E2*DE1,Q1*DQ2-Q2*DQ1,
- DL1*DL2,DE1*DE2,DQ1*DQ2> > RetT;
- std::complex<Qty<L1*DL2+L2*DL1,E1*DE2+E2*DE1,Q1*DQ2+Q2*DQ1,
- DL1*DL2,DE1*DE2,DQ1*DQ2> > tmp = q1*conj(q2);
- Qty<2*L2,2*E2,2*Q2,DL2,DE2,DQ2> norm = (q2*conj(q2)).real();
- return RetT(tmp.real()/norm,tmp.imag()/norm);
+template<typename L1, typename E1, typename Q1,
+ typename L2, typename E2, typename Q2>
+inline auto
+operator/(Qty<L1,E1,Q1> q1,
+ std::complex<Qty<L2,E2,Q2>> q2)
+-> std::complex<decltype(q1/q2.real())>
+{
+ auto tmp = q1*conj(q2);
+ auto norm = (q2*conj(q2)).real();
+ return {tmp.real()/norm, tmp.imag()/norm};
}
// complex qty = complex qty / qty
-template<int L1, int L2, int E1, int E2, int Q1, int Q2,
- int DL1, int DL2, int DE1, int DE2, int DQ1, int DQ2>
-inline constexpr std::complex<Qty<L1*DL2-L2*DL1,E1*DE2-E2*DE1,Q1*DQ2-Q2*DQ1,DL1*DL2,DE1*DE2,DQ1*DQ2> >
-operator/(std::complex<Qty<L1,E1,Q1,DL1,DE1,DQ1> > q1,
- Qty<L2,E2,Q2,DL2,DE2,DQ2> q2) {
- typedef std::complex<Qty<L1*DL2-L2*DL1,E1*DE2-E2*DE1,Q1*DQ2-Q2*DQ1,
- DL1*DL2,DE1*DE2,DQ1*DQ2> > RetT;
- return RetT(q1.real()/q2,q1.imag()/q2);
+template<typename L1, typename E1, typename Q1,
+ typename L2, typename E2, typename Q2>
+inline constexpr auto
+operator/(std::complex<Qty<L1,E1,Q1>> q1, Qty<L2,E2,Q2> q2)
+-> std::complex<decltype(q1.real()/q2)>
+{
+ return {q1.real()/q2, q1.imag()/q2};
}
// complex qty = complex qty * complex double
-template<int L, int E, int Q, int DL, int DE, int DQ>
-inline constexpr std::complex<Qty<L,E,Q,DL,DE,DQ> >
-operator*(std::complex<Qty<L,E,Q,DL,DE,DQ> > q1,
- std::complex<double> q2) {
+template<typename L, typename E, typename Q>
+inline constexpr std::complex<Qty<L,E,Q>>
+operator*(std::complex<Qty<L,E,Q>> q1, std::complex<double> q2) {
return q2 * q1;
}
// complex qty = qty * complex qty
-template<int L1, int L2, int E1, int E2, int Q1, int Q2,
- int DL1, int DL2, int DE1, int DE2, int DQ1, int DQ2>
-inline constexpr std::complex<Qty<L1*DL2+L2*DL1,E1*DE2+E2*DE1,Q1*DQ2+Q2*DQ1,
- DL1*DL2,DE1*DE2,DQ1*DQ2> >
-operator*(Qty<L1,E1,Q1,DL1,DE1,DQ1> q1,
- std::complex<Qty<L2,E2,Q2,DL2,DE2,DQ2> > q2) {
- typedef std::complex<Qty<L1*DL2+L2*DL1,E1*DE2+E2*DE1,Q1*DQ2+Q2*DQ1,
- DL1*DL2,DE1*DE2,DQ1*DQ2> > RetT;
- return RetT(q1*q2.real(), q1*q2.imag());
+template<typename L1, typename E1, typename Q1,
+ typename L2, typename E2, typename Q2>
+inline constexpr auto
+operator*(Qty<L1,E1,Q1> q1, std::complex<Qty<L2,E2,Q2>> q2)
+-> std::complex<decltype(q1*q2.real())>
+{
+ return {q1*q2.real(), q1*q2.imag()};
}
// complex qty = qty * complex qty
-template<int L, int E, int Q, int DL, int DE, int DQ>
-inline constexpr std::complex<Qty<2*L,2*E,2*Q,DL,DE,DQ> >
-operator*(Qty<L,E,Q,DL,DE,DQ> q1,
- std::complex<Qty<L,E,Q,DL,DE,DQ> > q2) {
- typedef std::complex<Qty<2*L,2*E,2*Q,DL,DE,DQ> > RetT;
- return RetT(q1*q2.real(), q1*q2.imag());
+template<typename L, typename E, typename Q>
+inline constexpr std::complex<typename Qty<L,E,Q>::Squared>
+operator*(Qty<L,E,Q> q1, std::complex<Qty<L,E,Q>> q2) {
+ return {q1*q2.real(), q1*q2.imag()};
}
// complex qty = qty * complex double
-template<int L, int E, int Q, int DL, int DE, int DQ>
-inline constexpr std::complex<Qty<L,E,Q,DL,DE,DQ> >
-operator*(Qty<L,E,Q,DL,DE,DQ> q1,
- std::complex<double> q2) {
- typedef std::complex<Qty<L,E,Q,DL,DE,DQ> > RetT;
- return RetT(q1*q2.real(), q1*q2.imag());
+template<typename L, typename E, typename Q>
+inline constexpr std::complex<Qty<L,E,Q>>
+operator*(Qty<L,E,Q> q1, std::complex<double> q2) {
+ return {q1*q2.real(), q1*q2.imag()};
}
// complex qty = complex double * qty
-template<int L, int E, int Q, int DL, int DE, int DQ>
-inline constexpr std::complex<Qty<L,E,Q,DL,DE,DQ> >
-operator*(std::complex<double> q1,
- Qty<L,E,Q,DL,DE,DQ> q2) {
+template<typename L, typename E, typename Q>
+inline constexpr std::complex<Qty<L,E,Q>>
+operator*(std::complex<double> q1, Qty<L,E,Q> q2) {
return q2 * q1;
}
// complex qty = complex qty * qty
-template<int L1, int L2, int E1, int E2, int Q1, int Q2,
- int DL1, int DL2, int DE1, int DE2, int DQ1, int DQ2>
-inline constexpr std::complex<Qty<L1*DL2+L2*DL1,E1*DE2+E2*DE1,Q1*DQ2+Q2*DQ1,
- DL1*DL2,DE1*DE2,DQ1*DQ2> >
-operator*(std::complex<Qty<L1,E1,Q1,DL1,DE1,DQ1> > q1,
- Qty<L2,E2,Q2,DL2,DE2,DQ2> q2) {
+template<typename L1, typename E1, typename Q1,
+ typename L2, typename E2, typename Q2>
+inline constexpr auto
+operator*(std::complex<Qty<L1,E1,Q1>> q1, Qty<L2,E2,Q2> q2)
+-> decltype(q2*q1)
+{
return q2 * q1;
}
// complex qty = complex qty * qty
-template<int L, int E, int Q, int DL, int DE, int DQ>
-inline constexpr std::complex<Qty<2*L,2*E,2*Q,DL,DE,DQ> >
-operator*(std::complex<Qty<L,E,Q,DL,DE,DQ> > q1,
- Qty<L,E,Q,DL,DE,DQ> q2) {
+template<typename L, typename E, typename Q>
+inline constexpr std::complex<typename Qty<L,E,Q>::Squared>
+operator*(std::complex<Qty<L,E,Q>> q1, Qty<L,E,Q> q2) {
return q2 * q1;
}
-// // complex qty *= complex double
-// template<int L, int E, int Q, int DL, int DE, int DQ>
-// inline std::complex<Qty<L,E,Q,DL,DE,DQ> > &
-// operator*=(std::complex<Qty<L,E,Q,DL,DE,DQ> > & q1,
-// std::complex<double> q2) {
-// q1 = q1 * q2;
-// return q1;
-// }
-
// complex qty *= double
-template<int L, int E, int Q, int DL, int DE, int DQ>
-inline std::complex<Qty<L,E,Q,DL,DE,DQ> > &
-operator*=(std::complex<Qty<L,E,Q,DL,DE,DQ> > & q1,
- double q2) {
- q1 = q1 * q2;
- return q1;
+template<typename L, typename E, typename Q>
+inline constexpr std::complex<Qty<L,E,Q>> &
+operator*=(std::complex<Qty<L,E,Q>> & q1, double q2) {
+ return (q1 = q1 * q2);
}
-// // complex qty /= complex double
-// template<int L, int E, int Q, int DL, int DE, int DQ>
-// inline std::complex<Qty<L,E,Q,DL,DE,DQ> > &
-// operator/=(std::complex<Qty<L,E,Q,DL,DE,DQ> > & q1,
-// std::complex<double> q2) {
-// q1 = q1 / q2;
-// return q1;
-// }
-
// complex qty /= double
-template<int L, int E, int Q, int DL, int DE, int DQ>
-inline std::complex<Qty<L,E,Q,DL,DE,DQ> > &
-operator/=(std::complex<Qty<L,E,Q,DL,DE,DQ> > & q1,
- double q2) {
- q1 = q1 / q2;
- return q1;
+template<typename L, typename E, typename Q>
+inline constexpr std::complex<Qty<L,E,Q>> &
+operator/=(std::complex<Qty<L,E,Q>> & q1, double q2) {
+ return (q1 = q1 / q2);
}
//@}
}
#endif
diff --git a/Config/PhysicalQtyOps.h b/Config/PhysicalQtyOps.h
--- a/Config/PhysicalQtyOps.h
+++ b/Config/PhysicalQtyOps.h
@@ -1,276 +1,226 @@
// -*- C++ -*-
//
// PhysicalQtyOps.h is a part of ThePEG - Toolkit for HEP Event Generation
// Copyright (C) 2006-2017 David Grellscheid, Leif Lonnblad
//
// ThePEG is licenced under version 3 of the GPL, see COPYING for details.
// Please respect the MCnet academic guidelines, see GUIDELINES for details.
//
#ifndef Physical_Qty_Ops_H
#define Physical_Qty_Ops_H
+#include "PhysicalQty.h"
#include <cmath>
/** @file PhysicalQtyOps.h
* Overloads for mathematical operations on physical quantities.
*/
namespace ThePEG {
/// @name Overloads for mathematical operations on physical quantities.
//@{
// qty = qty * qty
-template<int L1, int L2, int E1, int E2, int Q1, int Q2,
- int DL1, int DL2, int DE1, int DE2, int DQ1, int DQ2>
-inline constexpr Qty<L1*DL2+L2*DL1,E1*DE2+E2*DE1,Q1*DQ2+Q2*DQ1,DL1*DL2,DE1*DE2,DQ1*DQ2>
-operator*(Qty<L1,E1,Q1,DL1,DE1,DQ1> q1, Qty<L2,E2,Q2,DL2,DE2,DQ2> q2) {
- typedef
- Qty<L1*DL2+L2*DL1,E1*DE2+E2*DE1,Q1*DQ2+Q2*DQ1,DL1*DL2,DE1*DE2,DQ1*DQ2> RetT;
+template<typename T, typename U>
+inline constexpr typename BinaryOpTraits<T,U>::MulT
+operator*(T q1, U q2) {
+ typedef typename BinaryOpTraits<T,U>::MulT RetT;
return RetT{RetT::baseunit(), q1.rawValue()*q2.rawValue()};
}
-
// qty = qty / qty
-template<int L1, int L2, int E1, int E2, int Q1, int Q2,
- int DL1, int DL2, int DE1, int DE2, int DQ1, int DQ2>
-inline constexpr Qty<L1*DL2-L2*DL1,E1*DE2-E2*DE1,Q1*DQ2-Q2*DQ1,DL1*DL2,DE1*DE2,DQ1*DQ2>
-operator/(Qty<L1,E1,Q1,DL1,DE1,DQ1> q1, Qty<L2,E2,Q2,DL2,DE2,DQ2> q2) {
- typedef
- Qty<L1*DL2-L2*DL1,E1*DE2-E2*DE1,Q1*DQ2-Q2*DQ1,DL1*DL2,DE1*DE2,DQ1*DQ2> RetT;
+template<typename T, typename U>
+inline constexpr typename BinaryOpTraits<T,U>::DivT
+operator/(T q1, U q2) {
+ typedef typename BinaryOpTraits<T,U>::DivT RetT;
return RetT{RetT::baseunit(), q1.rawValue()/q2.rawValue()};
}
// qty = qty + qty
-template<int L, int E, int Q, int DL, int DE, int DQ, int DL2, int DE2, int DQ2>
-inline Qty<L,E,Q,DL,DE,DQ>
-operator+(Qty<L,E,Q,DL,DE,DQ> q1,
- Qty<QtyInt<L,DL,DL2>::I,
- QtyInt<E,DE,DE2>::I,
- QtyInt<Q,DQ,DQ2>::I,
- DL2,DE2,DQ2> q2) {
- Qty<L,E,Q,DL,DE,DQ> q = q1;
- q += q2;
- return q;
+template<typename T, typename U>
+inline enable_if_same_qty<T,T,U>
+operator+(T q1, U q2) {
+ q1 += q2;
+ return q1;
}
// qty = qty - qty
-template<int L, int E, int Q, int DL, int DE, int DQ, int DL2, int DE2, int DQ2>
-inline Qty<L,E,Q,DL,DE,DQ>
-operator-(Qty<L,E,Q,DL,DE,DQ> q1,
- Qty<QtyInt<L,DL,DL2>::I,
- QtyInt<E,DE,DE2>::I,
- QtyInt<Q,DQ,DQ2>::I,
- DL2,DE2,DQ2> q2) {
- Qty<L,E,Q,DL,DE,DQ> q = q1;
- q -= q2;
- return q;
+template<typename T, typename U>
+inline enable_if_same_qty<T,T,U>
+operator-(T q1, U q2) {
+ q1 -= q2;
+ return q1;
}
// qty == qty
-template<int L, int E, int Q, int DL, int DE, int DQ, int DL2, int DE2, int DQ2>
-inline constexpr bool
-operator==(Qty<L,E,Q,DL,DE,DQ> q1,
- Qty<QtyInt<L,DL,DL2>::I,
- QtyInt<E,DE,DE2>::I,
- QtyInt<Q,DQ,DQ2>::I,
- DL2,DE2,DQ2> q2) {
+template<typename T, typename U>
+inline constexpr enable_if_same_qty<bool,T,U>
+operator==(T q1, U q2) {
return q1.rawValue()==q2.rawValue();
}
// qty != qty
-template<int L, int E, int Q, int DL, int DE, int DQ, int DL2, int DE2, int DQ2>
-inline constexpr bool
-operator!=(Qty<L,E,Q,DL,DE,DQ> q1,
- Qty<QtyInt<L,DL,DL2>::I,
- QtyInt<E,DE,DE2>::I,
- QtyInt<Q,DQ,DQ2>::I,
- DL2,DE2,DQ2> q2) {
+template<typename T, typename U>
+inline constexpr enable_if_same_qty<bool,T,U>
+operator!=(T q1, U q2) {
return q1.rawValue()!=q2.rawValue();
}
// qty < qty
-template<int L, int E, int Q, int DL, int DE, int DQ, int DL2, int DE2, int DQ2>
-inline constexpr bool
-operator<(Qty<L,E,Q,DL,DE,DQ> q1,
- Qty<QtyInt<L,DL,DL2>::I,
- QtyInt<E,DE,DE2>::I,
- QtyInt<Q,DQ,DQ2>::I,
- DL2,DE2,DQ2> q2) {
+template<typename T, typename U>
+inline constexpr enable_if_same_qty<bool,T,U>
+operator<(T q1, U q2) {
return q1.rawValue()<q2.rawValue();
}
// qty <= qty
-template<int L, int E, int Q, int DL, int DE, int DQ, int DL2, int DE2, int DQ2>
-inline constexpr bool
-operator<=(Qty<L,E,Q,DL,DE,DQ> q1,
- Qty<QtyInt<L,DL,DL2>::I,
- QtyInt<E,DE,DE2>::I,
- QtyInt<Q,DQ,DQ2>::I,
- DL2,DE2,DQ2> q2) {
+template<typename T, typename U>
+inline constexpr enable_if_same_qty<bool,T,U>
+operator<=(T q1, U q2) {
return q1.rawValue()<=q2.rawValue();
}
// qty > qty
-template<int L, int E, int Q, int DL, int DE, int DQ, int DL2, int DE2, int DQ2>
-inline constexpr bool
-operator>(Qty<L,E,Q,DL,DE,DQ> q1,
- Qty<QtyInt<L,DL,DL2>::I,
- QtyInt<E,DE,DE2>::I,
- QtyInt<Q,DQ,DQ2>::I,
- DL2,DE2,DQ2> q2) {
+template<typename T, typename U>
+inline constexpr enable_if_same_qty<bool,T,U>
+operator>(T q1, U q2) {
return q1.rawValue()>q2.rawValue();
}
// qty >= qty
-template<int L, int E, int Q, int DL, int DE, int DQ, int DL2, int DE2, int DQ2>
-inline constexpr bool
-operator>=(Qty<L,E,Q,DL,DE,DQ> q1,
- Qty<QtyInt<L,DL,DL2>::I,
- QtyInt<E,DE,DE2>::I,
- QtyInt<Q,DQ,DQ2>::I,
- DL2,DE2,DQ2> q2) {
+template<typename T, typename U>
+inline constexpr enable_if_same_qty<bool,T,U>
+operator>=(T q1, U q2) {
return q1.rawValue()>=q2.rawValue();
}
// comparisons with ZERO
-template<int L, int E, int Q, int DL, int DE, int DQ>
-inline constexpr bool
-operator==(Qty<L,E,Q,DL,DE,DQ> q1, ZeroUnit) {
+template<typename T>
+inline constexpr enable_if_same_qty<bool, T>
+operator==(T q1, ZeroUnit) {
return q1.rawValue() == 0.0;
}
-template<int L, int E, int Q, int DL, int DE, int DQ>
-inline constexpr bool
-operator!=(Qty<L,E,Q,DL,DE,DQ> q1, ZeroUnit) {
+template<typename T>
+inline constexpr enable_if_same_qty<bool, T>
+operator!=(T q1, ZeroUnit) {
return q1.rawValue() != 0.0;
}
-template<int L, int E, int Q, int DL, int DE, int DQ>
-inline constexpr bool
-operator<(Qty<L,E,Q,DL,DE,DQ> q1, ZeroUnit) {
+template<typename T>
+inline constexpr enable_if_same_qty<bool, T>
+operator<(T q1, ZeroUnit) {
return q1.rawValue() < 0.0;
}
-template<int L, int E, int Q, int DL, int DE, int DQ>
-inline constexpr bool
-operator>(Qty<L,E,Q,DL,DE,DQ> q1, ZeroUnit) {
+template<typename T>
+inline constexpr enable_if_same_qty<bool, T>
+operator>(T q1, ZeroUnit) {
return q1.rawValue() > 0.0;
}
-template<int L, int E, int Q, int DL, int DE, int DQ>
-inline constexpr bool
-operator<=(Qty<L,E,Q,DL,DE,DQ> q1, ZeroUnit) {
+template<typename T>
+inline constexpr enable_if_same_qty<bool, T>
+operator<=(T q1, ZeroUnit) {
return q1.rawValue() <= 0.0;
}
-template<int L, int E, int Q, int DL, int DE, int DQ>
-inline constexpr bool
-operator>=(Qty<L,E,Q,DL,DE,DQ> q1, ZeroUnit) {
+template<typename T>
+inline constexpr enable_if_same_qty<bool, T>
+operator>=(T q1, ZeroUnit) {
return q1.rawValue() >= 0.0;
}
// qty = qty * double
-template<int L, int E, int Q, int DL, int DE, int DQ>
-inline constexpr Qty<L,E,Q,DL,DE,DQ>
-operator*(Qty<L,E,Q,DL,DE,DQ> q,double x) {
- return Qty<L,E,Q,DL,DE,DQ>{q,x};
+template<typename T>
+inline constexpr enable_if_same_qty<T, T>
+operator*(T q,double x) {
+ return T{q,x};
}
// qty = double * qty
-template<int L, int E, int Q, int DL, int DE, int DQ>
-inline constexpr Qty<L,E,Q,DL,DE,DQ>
-operator*(double x,Qty<L,E,Q,DL,DE,DQ> q) {
- return Qty<L,E,Q,DL,DE,DQ>{q,x};
+template<typename T>
+inline constexpr enable_if_same_qty<T, T>
+operator*(double x,T q) {
+ return T{q,x};
}
// qty = qty / double
-template<int L, int E, int Q, int DL, int DE, int DQ>
-inline constexpr Qty<L,E,Q,DL,DE,DQ>
-operator/(Qty<L,E,Q,DL,DE,DQ> q,double x) {
- return Qty<L,E,Q,DL,DE,DQ>{q, 1./x};
+template<typename T>
+inline constexpr enable_if_same_qty<T, T>
+operator/(T q,double x) {
+ return T{q, 1./x};
}
// qty = double / qty
-template<int L, int E, int Q, int DL, int DE, int DQ>
-inline constexpr Qty<-L,-E,-Q,DL,DE,DQ>
-operator/(double x, Qty<L,E,Q,DL,DE,DQ> q) {
- typedef Qty<-L,-E,-Q,DL,DE,DQ> RetT;
+template<typename T>
+inline constexpr enable_if_same_qty<typename T::Inverse, T>
+operator/(double x, T q) {
+ typedef typename T::Inverse RetT;
return RetT{RetT::baseunit(), x/q.rawValue()};
}
// qty = -qty
-template<int L, int E, int Q, int DL, int DE, int DQ>
-inline constexpr Qty<L,E,Q,DL,DE,DQ>
-operator-(Qty<L,E,Q,DL,DE,DQ> q) {
- typedef Qty<L,E,Q,DL,DE,DQ> RetT;
- return RetT{RetT::baseunit(), -q.rawValue()};
-}
-
-// qty = sqr(qty)
-template<int L, int E, int Q, int DL, int DE, int DQ>
-inline constexpr Qty<2*L,2*E,2*Q,DL,DE,DQ>
-sqr(Qty<L,E,Q,DL,DE,DQ> q) {
- return q*q;
+template<typename T>
+inline constexpr enable_if_same_qty<T, T>
+operator-(T q) {
+ typedef T RetT;
+ return RetT{q, -1.0};
}
// qty = sqrt(qty) // std::sqrt is not constexpr
-template<int L, int E, int Q, int DL, int DE, int DQ>
-inline Qty<L,E,Q,DL*2,DE*2,DQ*2>
-sqrt(Qty<L,E,Q,DL,DE,DQ> q) {
- typedef Qty<L,E,Q,DL*2,DE*2,DQ*2> RetT;
- return RetT(std::sqrt(q.rawValue())*RetT::baseunit());
+template<typename T>
+inline enable_if_same_qty<typename T::Sqrt, T>
+sqrt(T q) {
+ typedef typename T::Sqrt RetT;
+ return RetT{RetT::baseunit(), std::sqrt(q.rawValue())};
}
// double = atan2(y,x)
-template<int L, int E, int Q, int DL, int DE, int DQ>
-inline constexpr double
-atan2(Qty<L,E,Q,DL,DE,DQ> y, Qty<L,E,Q,DL,DE,DQ> x) {
+template<typename T, typename U>
+inline constexpr enable_if_same_qty<double,T,U>
+atan2(T y, U x) {
return std::atan2(y.rawValue(), x.rawValue());
}
// qty = abs(qty)
-template<int L, int E, int Q, int DL, int DE, int DQ>
-inline constexpr Qty<L,E,Q,DL,DE,DQ>
-abs(Qty<L,E,Q,DL,DE,DQ> q) {
- typedef Qty<L,E,Q,DL,DE,DQ> RetT;
- return RetT(std::abs(q.rawValue())*RetT::baseunit());
+template<typename T>
+inline constexpr enable_if_same_qty<T, T>
+abs(T q) {
+ return T{T::baseunit(), std::abs(q.rawValue())};
}
// qty = pow<P,R>(qty)
-template<int P, int R, int L, int E, int Q, int DL, int DE, int DQ>
-inline constexpr Qty<P*L,P*E,P*Q,R*DL,R*DE,R*DQ>
-pow(Qty<L,E,Q,DL,DE,DQ> q) {
- typedef Qty<P*L,P*E,P*Q,R*DL,R*DE,R*DQ> RetT;
- return RetT(std::pow(q.rawValue(),double(P)/double(R))*RetT::baseunit());
+template<int Num, int Den, typename T>
+inline constexpr enable_if_same_qty<typename T::template Power<Num,Den>, T>
+pow(T q) {
+ typedef typename T::template Power<Num,Den> RetT;
+ return RetT{RetT::baseunit(), std::pow(q.rawValue(),double(Num)/double(Den))};
}
// max for T,U types
template<typename T, typename U>
-inline
-T max(const T & t, const U & u) {
+inline T max(const T & t, const U & u) {
const T & utmp = u;
return std::max(t, utmp);
}
// ZeroUnit in front should take U type
template<typename U>
-inline
-U max(const ZeroUnit & t, const U & u) {
+inline U max(const ZeroUnit & t, const U & u) {
const U & ttmp = t;
return std::max(ttmp, u);
}
// min for T,U types
template<typename T, typename U>
-inline
-T min(const T & t, const U & u) {
+inline T min(const T & t, const U & u) {
const T & utmp = u;
return std::min(t, utmp);
}
// ZeroUnit in front should take U type
template<typename U>
-inline
-U min(const ZeroUnit & t, const U & u) {
+inline U min(const ZeroUnit & t, const U & u) {
const U & ttmp = t;
return std::min(ttmp, u);
}
//@}
}
#endif
diff --git a/Config/TemplateTools.h b/Config/TemplateTools.h
--- a/Config/TemplateTools.h
+++ b/Config/TemplateTools.h
@@ -1,97 +1,64 @@
// -*- C++ -*-
//
// TemplateTools.h is a part of ThePEG - Toolkit for HEP Event Generation
// Copyright (C) 2006-2017 David Grellscheid, Leif Lonnblad
//
// ThePEG is licenced under version 3 of the GPL, see COPYING for details.
// Please respect the MCnet academic guidelines, see GUIDELINES for details.
//
#ifndef Template_Tools_H
#define Template_Tools_H
#include <type_traits>
/**
* @file TemplateTools.h
* Useful template machinery. Based on Alexandrescu, "Modern C++ Design".
*/
namespace ThePEG {
/// Conversion between integers and types.
template <int v>
struct Int2Type
{
enum { value = v };
};
/// Dummy type for ambiguous function signatures.
struct DummyType {};
-/// Result type calculations for binary operators.
-template <typename T, typename U>
-struct BinaryOpTraits;
-
-/** @cond TRAITSPECIALIZATIONS */
-
-template <>
-struct BinaryOpTraits<double,double> {
- /** The type resulting from multiplication of the template types. */
- typedef double MulT;
- /** The type resulting from division of the first template type by
- the second. */
- typedef double DivT;
-};
-
-template <>
-struct BinaryOpTraits<long double, long double> {
- /** The type resulting from multiplication of the template types. */
- typedef long double MulT;
- /** The type resulting from division of the first template type by
- the second. */
- typedef long double DivT;
-};
-
-template <>
-struct BinaryOpTraits<int,int> {
- /** The type resulting from multiplication of the template types. */
- typedef int MulT;
- /** The type resulting from division of the first template type by
- the second. */
- typedef int DivT;
-};
-
/** @endcond */
/// Selection mechanism for type-dependent implementations.
enum ImplSelector { Dimensioned, Standard };
/// Typedef for dimensioned types.
typedef Int2Type<Dimensioned> DimensionT;
/// Typedef for non-dimensioned types.
typedef Int2Type<Standard> StandardT;
/// Type traits for built-in types
template <typename T>
struct TypeTraits
{
/// Boolean flag. Is true for physical quantities.
enum { hasDimension = false };
/// Implementation selector
typedef StandardT DimType;
/// Base unit for arithmetic types
// construction with extra U type is necessary to make
// enable_if work before concepts are supported properly
template <typename U = T>
static constexpr typename
std::enable_if< (std::is_arithmetic<U>::value &&
std::is_same<U, T>::value), U>::type
baseunit()
{ return static_cast<U>(1); }
};
}
#endif
diff --git a/Config/ThePEG.h b/Config/ThePEG.h
--- a/Config/ThePEG.h
+++ b/Config/ThePEG.h
@@ -1,149 +1,148 @@
// -*- C++ -*-
//
// ThePEG.h is a part of ThePEG - Toolkit for HEP Event Generation
// Copyright (C) 1999-2017 Leif Lonnblad
//
// ThePEG is licenced under version 3 of the GPL, see COPYING for details.
// Please respect the MCnet academic guidelines, see GUIDELINES for details.
//
#ifndef ThePEG_H
#define ThePEG_H
/** \file ThePEG.h
* This is the main config header file for ThePEG. Do not make
* changes in this file. If you need to modify anything, edit a copy
* of the file which can be included instead of this file using the
* macro <code>ThePEG_ALTERNATE_CONFIG</code>.
*/
#ifndef ThePEG_ALTERNATE_CONFIG
#include "ThePEG/Pointer/Ptr.h"
#include "ThePEG/Pointer/PtrTraits.h"
#include "ThePEG/Pointer/RCPtr.h"
#include "ThePEG/Utilities/Rebinder.fh"
#include "ThePEG/Utilities/Interval.fh"
#include "ThePEG/Utilities/ClassDescription.fh"
#include "ThePEG/Interface/InterfaceBase.fh"
#include "ThePEG/Persistency/PersistentOStream.fh"
#include "ThePEG/Persistency/PersistentIStream.fh"
#include "TemplateTools.h"
#include "Complex.h"
#include "Unitsystem.h"
#include "Constants.h"
#include "std.h"
/**
* This is the main namespace within which all identifiers in ThePEG
* are declared. External packages based on ThePEG should not
* introduce identifiers in the ThePEG namespace, but in a separate
* namespace which need not be nested within the ThePEG namespace.
*/
namespace ThePEG {
// Introduce some identifiers in the ThePEG namespace/
using namespace ThePEG::Pointer;
using ThePEG::Pointer::Ptr;
using namespace ThePEG::Units;
/**
* Define the base class from which all (polymorphic) classes in
* ThePEG are derived.
*/
struct Base: public ReferenceCounted {
/** The virtual destructor */
virtual ~Base() {}
/**
* The standard Init function used to initialize the interfaces.
* Called exactly once for each class by the class description system
* before the main function starts or
* when this class is dynamically loaded.
*/
static void Init() {}
/**
* Print out debugging information for this object on std::cerr. To
* be called from within a debugger. Simply calls the virtual
* debugme() function.
*/
void debug() const;
/**
* Print out debugging information for this object on std::cerr. To
* be called from within a debugger via the debug() function.
*/
virtual void debugme() const;
};
/**
* Define the base class from which all persistent classes in
* ThePEG are derived.
*/
typedef Base PersistentBase;
/**
* TraitsType is an empty, non-polymorphic, base class. It is used as
* a base class of all traits classes in ThePEG in order to group them
* together in the documentation. It currently serves no other
* purpose.
*/
struct TraitsType {};
/**
* A standard exception class to be used for vetoing a whole event.
*/
struct Veto {
/** the default constructor. */
Veto();
};
/**
* A standard exception class to be used to temporarily stop the
* generation of an event.
*/
struct Stop {};
/**
* The square function should really have been included in the
* standard C++ library.
*/
template <typename T>
-inline constexpr
-typename BinaryOpTraits<T,T>::MulT
-sqr(const T& x) {
+inline constexpr
+auto sqr(const T& x) -> decltype(x*x) {
return x*x;
}
// Debugging in ThePEG may be swithced off completely by this
// compilation swithc, eliminating possible overhead in error
// checking.
#ifndef ThePEG_NO_DEBUG
/** Macro for accessing debug functions to enable compile-time disabling. */
#define ThePEG_DEBUG_LEVEL Debug::level
/** Macro for accessing debug functions to enable compile-time disabling. */
#define ThePEG_DEBUG_ITEM(item) Debug::debugItem(item)
#else
/** Macro for accessing debug functions to enable compile-time disabling. */
#define ThePEG_DEBUG_LEVEL 0
/** Macro for accessing debug functions to enable compile-time disabling. */
#define ThePEG_DEBUG_ITEM(item) false
#endif
}
#include "Pointers.h"
#include "Containers.h"
#else
#include ThePEG_ALTERNATIVE_CONFIG
#endif
#endif /* ThePEG_H */
diff --git a/Config/Unitsystem.h b/Config/Unitsystem.h
--- a/Config/Unitsystem.h
+++ b/Config/Unitsystem.h
@@ -1,264 +1,268 @@
// -*- C++ -*-
//
// Unitsystem.h is a part of ThePEG - Toolkit for HEP Event Generation
// Copyright (C) 1999-2017 Leif Lonnblad, David Grellscheid
//
// ThePEG is licenced under version 3 of the GPL, see COPYING for details.
// Please respect the MCnet academic guidelines, see GUIDELINES for details.
//
#ifndef ThePEG_Units_H
#define ThePEG_Units_H
#include "ThePEG/Vectors/Lorentz5Vector.fh"
#include "ThePEG/Vectors/LorentzVector.fh"
#include "ThePEG/Vectors/ThreeVector.fh"
#include "ThePEG/Vectors/Transverse.fh"
#include "PhysicalQty.h"
#include "PhysicalQtyOps.h"
#include "PhysicalQtyComplex.h"
namespace ThePEG {
/**
* The Units namespace contains the declaration of a number of classes
* for variables with dimension. Currently they are all typedefs of
* double, but in the future the SIUnits package will be used.
*
* The file Utilities/UnitIO.h defines helper-classes and helper
* functions to read and write variables with dimensions. As an
* example, to read and write an energy variable <code>e</code> in
* units of GeV, use: <code>os << ounit(e, GeV)</code> and <code>is >>
* iunit(e, GeV)</code>
*/
namespace Units {
+/// adapter for the old style of naming quantities
+template<int L, int E, int Q, int DL=1, int DE=1, int DQ=1>
+using Qty = ThePEG::Qty<std::ratio<L,DL>, std::ratio<E,DE>, std::ratio<Q,DQ>>;
+
/** Energy. */
typedef Qty<0,1,0> Energy;
/** Mass has the same unit as Energy <=> c == 1. */
typedef Energy Mass;
/** Length. */
typedef Qty<1,0,0> Length;
/** Time has the same unit as Length. <=> c == 1. */
typedef Length Time;
/** Inverse Length. */
typedef Qty<-1,0,0> InvLength;
/** Velocities are dimensionless fractions of c. */
typedef double Velocity;
/** Charge. */
typedef Qty<0,0,1> Charge;
/** Angular momentum. */
typedef Qty<1,1,0> AngularMomentum;
/** Tension. */
typedef Qty<-1,1,0> Tension;
/** Area will be assumed to be Length\f$^2\f$. */
typedef Qty<2,0,0> Area;
/** Inverse Area. */
typedef Qty<-2,0,0> InvArea;
/** Cross section is an area. */
typedef Area CrossSection;
/**
* @name Higher powers of energy.
* Even higher powers can be created with similar typedefs.
*/
//@{
typedef Qty<0, 2, 0> Energy2;
typedef Qty<0, 3, 0> Energy3;
typedef Qty<0, 4, 0> Energy4;
typedef Qty<0, 5, 0> Energy5;
typedef Qty<0, 6, 0> Energy6;
typedef Qty<0, 7, 0> Energy7;
typedef Qty<0, 8, 0> Energy8;
typedef Qty<0, 9, 0> Energy9;
typedef Qty<0,10, 0> Energy10;
typedef Qty<0,11, 0> Energy11;
typedef Qty<0,12, 0> Energy12;
typedef Qty<0, 1,0, 1,2,1> SqrtEnergy;
typedef Qty<0,-1,0, 1,2,1> InvSqrtEnergy;
typedef Qty<0, -1, 0> InvEnergy;
typedef Qty<0, -2, 0> InvEnergy2;
typedef Qty<0, -3, 0> InvEnergy3;
typedef Qty<0, -4, 0> InvEnergy4;
typedef Qty<0, -5, 0> InvEnergy5;
typedef Qty<0, -6, 0> InvEnergy6;
typedef Qty<0, -7, 0> InvEnergy7;
typedef Qty<0, -8, 0> InvEnergy8;
typedef Qty<0, -9, 0> InvEnergy9;
typedef Qty<0,-10, 0> InvEnergy10;
typedef Qty<0,-11, 0> InvEnergy11;
typedef Qty<0,-12, 0> InvEnergy12;
//@}
/** CrossSection*Energy2. */
typedef Qty<2,2,0> Energy2XSec;
/** CrossSection/Energy2. */
typedef Qty<2,-2,0> DiffXSec;
/** CrossSection/Energy4. */
typedef Qty<2,-4,0> Diff2XSec;
/** CrossSection/Energy6 */
typedef Qty<2,-6,0> Diff3XSec;
/** Scale is the same as a squared energy. */
typedef Energy2 Scale;
/** A point in three-dimensional euclidean space. */
typedef ThreeVector<Length> Point;
/** A distance in three-dimensional euclidean space. */
typedef ThreeVector<Length> Distance;
/** A direction in three-dimensional euclidean space. */
typedef ThreeVector<double> Axis;
/** A momentum in three-dimensional euclidean space. */
typedef ThreeVector<Energy> Momentum3;
/** A three-dimensional boost vector. */
typedef ThreeVector<double> Boost;
/** A distance in four-dimensional space-time. */
typedef LorentzVector<Length> LorentzDistance;
/** A distance in four-dimensional space-time with an explicit
* invariant time component. */
typedef Lorentz5Vector<Length> Lorentz5Distance;
/** A point in four-dimensional space-time. */
typedef LorentzVector<Length> LorentzPoint;
/** A momentum in four-dimensional space-time. */
typedef LorentzVector<Energy> LorentzMomentum;
/** A momentum in four-dimensional space-time with an explicit
* invariant mass component. */
typedef Lorentz5Vector<Energy> Lorentz5Momentum;
/** Transverse components of a momentum. */
typedef Transverse<Energy> TransverseMomentum;
/// @name Pre-defined basic units.
//@{
constexpr Length operator "" _mm( long double x ) {
return Length{Length::baseunit(), static_cast<double>(x)};
}
constexpr Length operator "" _mm( unsigned long long x ) {
return Length{Length::baseunit(), static_cast<double>(x)};
}
constexpr Length meter = 1.0e+3_mm;
constexpr Length millimeter = 1_mm;
constexpr Length mm = 1_mm;
constexpr Length centimeter = 10_mm;
constexpr Length micrometer = 1.0e-3_mm;
constexpr Length nanometer = 1.0e-6_mm;
constexpr Length picometer = 1.0e-9_mm;
constexpr Length femtometer = 1.0e-12_mm;
constexpr Energy operator "" _MeV( long double x ) {
return Energy{Energy::baseunit(), static_cast<double>(x)};
}
constexpr Energy operator "" _MeV( unsigned long long x ) {
return Energy{Energy::baseunit(), static_cast<double>(x)};
}
constexpr Energy operator "" _GeV( long double x ) {
return Energy{1000_MeV, static_cast<double>(x)};
}
constexpr Energy operator "" _GeV( unsigned long long x ) {
return Energy{1000_MeV, static_cast<double>(x)};
}
constexpr Energy keV = 1.0e-3_MeV;
constexpr Energy MeV = 1_MeV;
constexpr Energy GeV = 1_GeV;
constexpr Energy TeV = 1.0e+6_MeV;
constexpr Energy2 operator "" _MeV2( long double x ) {
return Energy2{Energy2::baseunit(), static_cast<double>(x)};
}
constexpr Energy2 operator "" _MeV2( unsigned long long x ) {
return Energy2{Energy2::baseunit(), static_cast<double>(x)};
}
constexpr Energy2 operator "" _GeV2( long double x ) {
return Energy2{1.0e+6_MeV2, static_cast<double>(x)};
}
constexpr Energy2 operator "" _GeV2( unsigned long long x ) {
return Energy2{1.0e+6_MeV2, static_cast<double>(x)};
}
constexpr Energy2 MeV2 = 1_MeV2;
constexpr Energy2 GeV2 = 1_GeV2;
constexpr InvEnergy InvGeV = 1/GeV;
constexpr Area operator "" _pb( long double x ) {
return Area{1.0e-34 * Area::baseunit(), static_cast<double>(x)};
}
constexpr Area operator "" _pb( unsigned long long x ) {
return Area{1.0e-34 * Area::baseunit(), static_cast<double>(x)};
}
constexpr Area femtobarn = 1.0e-03_pb;
constexpr Area picobarn = 1_pb;
constexpr Area nanobarn = 1.0e+03_pb;
constexpr Area microbarn = 1.0e+06_pb;
constexpr Area millibarn = 1.0e+09_pb;
constexpr Area barn = 1.0e+12_pb;
constexpr Charge eplus = Charge::baseunit();
//@}
/// Planck's constant times c (PDG 2006 value 197.326968(17) MeV fm)
constexpr Qty<1,1,0> hbarc = 197.326968e-15 * MeV * meter;
/// Planck's constant (PDG 2006 value 197.326968(17) MeV fm)
constexpr Qty<1,1,0> hbar_Planck = hbarc / 1.0; // c is one
}
/**
* Use symbols from this namespace to make forced breaks of unit
* consistency explicit.
*/
namespace UnitRemoval {
/// @name Helper units to make breaks of unit consistency explicit.
//@{
constexpr Units::Energy E = Units::Energy::baseunit();
constexpr Units::Energy2 E2 = E*E;
constexpr Units::Energy3 E3 = E*E2;
constexpr Units::Energy4 E4 = E2*E2;
constexpr Units::InvEnergy InvE = 1.0/E;
constexpr Units::InvEnergy2 InvE2 = 1.0/E2;
constexpr Units::InvEnergy3 InvE3 = 1.0/E3;
constexpr Units::InvEnergy4 InvE4 = 1.0/E4;
constexpr Units::SqrtEnergy SqrtE = Units::SqrtEnergy::baseunit();
constexpr Units::InvSqrtEnergy InvSqrtE = Units::InvSqrtEnergy::baseunit();
//@}
}
}
#endif /* ThePEG_Units_H */
diff --git a/Helicity/LorentzRSSpinor.h b/Helicity/LorentzRSSpinor.h
--- a/Helicity/LorentzRSSpinor.h
+++ b/Helicity/LorentzRSSpinor.h
@@ -1,409 +1,413 @@
// -*- C++ -*-
//
// LorentzRSSpinor.h is a part of ThePEG - Toolkit for HEP Event Generation
// Copyright (C) 2003-2017 Peter Richardson, Leif Lonnblad
//
// ThePEG is licenced under version 3 of the GPL, see COPYING for details.
// Please respect the MCnet academic guidelines, see GUIDELINES for details.
//
#ifndef ThePEG_LorentzRSSpinor_H
#define ThePEG_LorentzRSSpinor_H
#include "ThePEG/Config/ThePEG.h"
#include "ThePEG/Vectors/ThreeVector.h"
#include "HelicityDefinitions.h"
#include "LorentzRSSpinor.fh"
#include "LorentzRSSpinorBar.h"
#include "LorentzSpinorBar.h"
#include "LorentzSpinor.h"
#include "LorentzPolarizationVector.h"
namespace ThePEG{
namespace Helicity{
/**
* The LorentzRSSpinor class is designed to store a Rarita-Schwinger
* spinor for a spin-3/2 particle. In addition to storing the
* components of the spinor information is stored on the type of
* spinor, for example u or v type.
*
* At the moment only one choice of the Dirac matrix representation
* is supported. For high-energy calculations the choice made by the
* HELAS collaboration is more efficient for numerical
* calculations. In this representation
*
* \f[
* \gamma_{i=1,2,3}=\left(\begin{array}{cc}
* 0 & \sigma_i \\
* -\sigma_i & 0
* \end{array}\right)
* \quad
* \gamma_0=\left(\begin{array}{cc}
* 0 & 1 \\
* 1 & 0
* \end{array}\right)
* \quad
* \gamma_5=\left(\begin{array}{cc}
* -1 & 0 \\
* 0 & 1
* \end{array}\right)
* \f]
*
* The type of the spinor is also stored using the SpinorType
* enumeration. There are three types supported SpinorType::u,
* SpinorType::v, SpinorType::unknown. This information is intended
* mainly for use in the case of Majorana particles where matrix
* elements can be calculated with either u or v type spinors and
* knowledge of which was used will be needed in order to give the
* correct correlations. The SpinorType::unknowne is intended for
* cases where either the spinor for an off-shell line in a matrix
* element calculation or the information is genuinely unknown.
*
* The LorentzRSSpinorBar class is also provided to store the barred
* spinor.
*
*
* @see HelicityDefinitions
* @see LorentzRSSpinorBar
*
* \author Peter Richardson
*
*/
template<typename Value>
class LorentzRSSpinor {
public:
/** @name Standard constructors. */
//@{
/**
* Default zero constructor, optionally specifying \a t, the type.
*/
LorentzRSSpinor(SpinorType t = SpinorType::unknown) : _type(t), _spin() {}
/**
* Constructor with complex numbers specifying the components,
* optionally specifying \a t, the type.
*/
LorentzRSSpinor(complex<Value> a1, complex<Value> b1,
complex<Value> c1, complex<Value> d1,
complex<Value> a2, complex<Value> b2,
complex<Value> c2, complex<Value> d2,
complex<Value> a3, complex<Value> b3,
complex<Value> c3, complex<Value> d3,
complex<Value> a4, complex<Value> b4,
complex<Value> c4, complex<Value> d4,
SpinorType t=SpinorType::unknown)
: _type(t), _spin{{ {{a1,b1,c1,d1}},
{{a2,b2,c2,d2}},
{{a3,b3,c3,d3}},
{{a4,b4,c4,d4}}
}} {}
//@}
/** @name Access the components. */
//@{
/**
* Subscript operator to return spinor components
*/
complex<Value> operator()(int i, int j) const {
assert( i >= 0 && i <= 3 && j>=0 && j<=3);
return _spin[i][j];
}
/**
* Set components by index
*/
complex<Value> & operator () (int i, int j) {
assert( i >= 0 && i <= 3 && j>=0 && j<=3);
return _spin[i][j];
}
/**
* Get first spinor component for the x vector
*/
complex<Value> xs1() const {return _spin[0][0];}
/**
* Get second spinor component for the x vector
*/
complex<Value> xs2() const {return _spin[0][1];}
/**
* Get third spinor component for the x vector
*/
complex<Value> xs3() const {return _spin[0][2];}
/**
* Get fourth spinor component for the x vector
*/
complex<Value> xs4() const {return _spin[0][3];}
/**
* Get first spinor component for the y vector
*/
complex<Value> ys1() const {return _spin[1][0];}
/**
* Get second spinor component for the y vector
*/
complex<Value> ys2() const {return _spin[1][1];}
/**
* Get third spinor component for the y vector
*/
complex<Value> ys3() const {return _spin[1][2];}
/**
* Get fourth spinor component for the y vector
*/
complex<Value> ys4() const {return _spin[1][3];}
/**
* Get first spinor component for the z vector
*/
complex<Value> zs1() const {return _spin[2][0];}
/**
* Get second spinor component for the z vector
*/
complex<Value> zs2() const {return _spin[2][1];}
/**
* Get third spinor component for the z vector
*/
complex<Value> zs3() const {return _spin[2][2];}
/**
* Get fourth spinor component for the z vector
*/
complex<Value> zs4() const {return _spin[2][3];}
/**
* Get first spinor component for the t vector
*/
complex<Value> ts1() const {return _spin[3][0];}
/**
* Get second spinor component for the t vector
*/
complex<Value> ts2() const {return _spin[3][1];}
/**
* Get third spinor component for the t vector
*/
complex<Value> ts3() const {return _spin[3][2];}
/**
* Get fourth spinor component for the t vector
*/
complex<Value> ts4() const {return _spin[3][3];}
/**
* Set first spinor component for the x vector
*/
void setXS1(complex<Value> in) {_spin[0][0]=in;}
/**
* Set second spinor component for the x vector
*/
void setXS2(complex<Value> in) {_spin[0][1]=in;}
/**
* Set third spinor component for the x vector
*/
void setXS3(complex<Value> in) {_spin[0][2]=in;}
/**
* Set fourth spinor component for the x vector
*/
void setXS4(complex<Value> in) {_spin[0][3]=in;}
/**
* Set first spinor component for the y vector
*/
void setYS1(complex<Value> in) {_spin[1][0]=in;}
/**
* Set second spinor component for the y vector
*/
void setYS2(complex<Value> in) {_spin[1][1]=in;}
/**
* Set third spinor component for the y vector
*/
void setYS3(complex<Value> in) {_spin[1][2]=in;}
/**
* Set fourth spinor component for the y vector
*/
void setYS4(complex<Value> in) {_spin[1][3]=in;}
/**
* Set first spinor component for the z vector
*/
void setZS1(complex<Value> in) {_spin[2][0]=in;}
/**
* Set second spinor component for the z vector
*/
void setZS2(complex<Value> in) {_spin[2][1]=in;}
/**
* Set third spinor component for the z vector
*/
void setZS3(complex<Value> in) {_spin[2][2]=in;}
/**
* Set fourth spinor component for the z vector
*/
void setZS4(complex<Value> in) {_spin[2][3]=in;}
/**
* Set first spinor component for the t vector
*/
void setTS1(complex<Value> in) {_spin[3][0]=in;}
/**
* Set second spinor component for the t vector
*/
void setTS2(complex<Value> in) {_spin[3][1]=in;}
/**
* Set third spinor component for the t vector
*/
void setTS3(complex<Value> in) {_spin[3][2]=in;}
/**
* Set fourth spinor component for the t vector
*/
void setTS4(complex<Value> in) {_spin[3][3]=in;}
//@}
/** @name Arithmetic operators. */
//@{
/**
* dot product with a polarization vector
*/
LorentzSpinor<Value> dot(const LorentzPolarizationVector & vec) const {
LorentzSpinor<Value> output(_type);
complex<Value> temp;
unsigned int ix;
for(ix=0;ix<4;++ix) {
temp = _spin[3][ix]*vec.t();
temp -= _spin[0][ix]*vec.x();
temp -= _spin[1][ix]*vec.y();
temp -= _spin[2][ix]*vec.z();
output[ix]=temp;
}
return output;
}
/**
* dot product with a 4-vector
*/
LorentzSpinor<Value> dot(const LorentzMomentum & invec) const {
LorentzSpinor<Value> output(_type);
complex<Value> temp;
LorentzVector<double> vec = UnitRemoval::InvE * invec;
unsigned int ix;
for(ix=0;ix<4;++ix) {
temp = - ( _spin[0][ix]*vec.x() + _spin[1][ix]*vec.y()+
_spin[2][ix]*vec.z() ) + _spin[3][ix]*vec.t();
output[ix]=temp;
}
return output;
}
//@}
/** @name Transformations. */
//@{
/**
* return the barred spinor
*/
LorentzRSSpinorBar<Value> bar() const;
/**
* Standard Lorentz boost specifying the components of the beta vector.
*/
LorentzRSSpinor & boost(double,double,double);
/**
* Standard Lorentz boost specifying the beta vector.
*/
LorentzRSSpinor & boost(const Boost &);
/**
* General transform
*/
LorentzRSSpinor & transform(const LorentzRotation &);
//@}
/** @name Functions related to type. */
//@{
/**
* Return the type of the spinor.
*/
SpinorType Type() const {return _type;}
//@}
/**
* Scalar product \f$\bar{f}^\alpha(c_LP_L+c_RP_R)f_\alpha\f$for general couplings
* @param fbar The barred spinor
* @param left The left-handed coupling, \f$c_L\f$.
* @param right The right-handed coupling, \f$c_R\f$.
*/
template <typename ValueB>
- complex<typename BinaryOpTraits<Value,ValueB>::MulT>
- generalScalar(LorentzRSSpinorBar<ValueB>& fbar, Complex left, Complex right) {
- complex<typename BinaryOpTraits<Value,ValueB>::MulT> output;
+ auto generalScalar(LorentzRSSpinorBar<ValueB>& fbar,
+ Complex left, Complex right)
+ -> decltype(left*fbar(3,0)*ts1())
+ {
+ decltype(left*fbar(3,0)*ts1()) output;
unsigned int iz;
output =
left*(fbar(3,0)*_spin[3][0]+fbar(3,1)*_spin[3][1])
+right*(fbar(3,2)*_spin[3][2]+fbar(3,3)*_spin[3][3]);
for(iz=0;iz<3;++iz) {
output -=
left*(fbar(iz,0)*_spin[iz][0]+fbar(iz,1)*_spin[iz][1])
+right*(fbar(iz,2)*_spin[iz][2]+fbar(iz,3)*_spin[iz][3]);
}
return output;
}
/**
* Current \f$\bar{f}(c_LP_L+c_RP_R)f^\alpha\f$ for general couplings.
* @param fbar The barred spinor
* @param left The left-handed coupling, \f$c_L\f$.
* @param right The right-handed coupling, \f$c_R\f$.
*/
template <typename ValueB>
- LorentzVector<complex<typename BinaryOpTraits<Value,ValueB>::MulT> >
- generalCurrent(LorentzSpinorBar<ValueB>& fbar, Complex left, Complex right) {
- typedef complex<typename BinaryOpTraits<Value,ValueB>::MulT> ResultT;
+ auto generalCurrent(LorentzSpinorBar<ValueB>& fbar,
+ Complex left, Complex right)
+ -> LorentzVector<decltype(left*fbar.s1()*ts1())>
+ {
+ typedef decltype(left*fbar.s1()*ts1()) ResultT;
ResultT output[4];
for(size_t iz=0;iz<4;++iz)
output[iz]= left*(fbar.s1()*_spin[iz][0]+fbar.s2()*_spin[iz][1])
+right*(fbar.s3()*_spin[iz][2]+fbar.s4()*_spin[iz][3]);
return LorentzVector<ResultT>(output[0],output[1],output[2],output[3]);
}
private:
/**
* Type of spinor
*/
SpinorType _type;
/**
* Storage of the components.
*/
std::array<std::array<complex<Value>,4>,4> _spin;
};
}
}
#ifndef ThePEG_TEMPLATES_IN_CC_FILE
#include "LorentzRSSpinor.tcc"
#endif
#endif
diff --git a/Helicity/LorentzRSSpinorBar.h b/Helicity/LorentzRSSpinorBar.h
--- a/Helicity/LorentzRSSpinorBar.h
+++ b/Helicity/LorentzRSSpinorBar.h
@@ -1,346 +1,347 @@
// -*- C++ -*-
//
// LorentzRSSpinorBar.h is a part of ThePEG - Toolkit for HEP Event Generation
// Copyright (C) 2003-2017 Peter Richardson, Leif Lonnblad
//
// ThePEG is licenced under version 3 of the GPL, see COPYING for details.
// Please respect the MCnet academic guidelines, see GUIDELINES for details.
//
#ifndef ThePEG_LorentzRSSpinorBar_H
#define ThePEG_LorentzRSSpinorBar_H
// This is the declaration of the LorentzRSSpinorBar class.
#include "ThePEG/Config/ThePEG.h"
#include "ThePEG/Vectors/ThreeVector.h"
#include "HelicityDefinitions.h"
#include "LorentzRSSpinor.fh"
#include "LorentzRSSpinorBar.fh"
#include "LorentzSpinorBar.h"
#include "LorentzSpinor.h"
#include "LorentzPolarizationVector.h"
namespace ThePEG {
namespace Helicity {
/**
* The <code>LorentzRSSpinorBar</code> class implements the storage of a
* barred Lorentz Rarita-Schwinger Spinor for a spin-3/2 particle.
* The design is based on that of the
* <code>LorentzRSSpinor</code> class and the details of the implemented
* are discussed in more detail in the header file for that class.
*
* @see LorentzRSSpinor
*
* \author Peter Richardson
*
*/
template <typename Value>
class LorentzRSSpinorBar {
public:
/** @name Standard constructors. */
//@{
/**
* Default zero constructor, optionally specifying \a t, the type.
*/
LorentzRSSpinorBar(SpinorType t = SpinorType::unknown) : _type(t), _spin() {}
/**
* Constructor with complex numbers specifying the components,
* optionally specifying \a t, the type.
*/
LorentzRSSpinorBar(complex<Value> a1,complex<Value> b1,
complex<Value> c1,complex<Value> d1,
complex<Value> a2,complex<Value> b2,
complex<Value> c2,complex<Value> d2,
complex<Value> a3,complex<Value> b3,
complex<Value> c3,complex<Value> d3,
complex<Value> a4,complex<Value> b4,
complex<Value> c4,complex<Value> d4,
SpinorType t=SpinorType::unknown)
: _type(t), _spin{{ {{a1,b1,c1,d1}},
{{a2,b2,c2,d2}},
{{a3,b3,c3,d3}},
{{a4,b4,c4,d4}}
}} {}
//@}
/** @name Access the components. */
//@{
/**
* Subscript operator to return spinor components
*/
complex<Value> operator()(int i, int j) const {
assert( i >= 0 && i <= 3 && j>=0 && j<=3 );
return _spin[i][j];
}
/**
* Set components by index
*/
complex<Value> & operator () (int i, int j) {
assert( i >= 0 && i <= 3 && j>=0 && j<=3 );
return _spin[i][j];
}
/**
* Get first spinor component for the x vector
*/
complex<Value> xs1() const {return _spin[0][0];}
/**
* Get second spinor component for the x vector
*/
complex<Value> xs2() const {return _spin[0][1];}
/**
* Get third spinor component for the x vector
*/
complex<Value> xs3() const {return _spin[0][2];}
/**
* Get fourth spinor component for the x vector
*/
complex<Value> xs4() const {return _spin[0][3];}
/**
* Get first spinor component for the y vector
*/
complex<Value> ys1() const {return _spin[1][0];}
/**
* Get second spinor component for the y vector
*/
complex<Value> ys2() const {return _spin[1][1];}
/**
* Get third spinor component for the y vector
*/
complex<Value> ys3() const {return _spin[1][2];}
/**
* Get fourth spinor component for the y vector
*/
complex<Value> ys4() const {return _spin[1][3];}
/**
* Get first spinor component for the z vector
*/
complex<Value> zs1() const {return _spin[2][0];}
/**
* Get second spinor component for the z vector
*/
complex<Value> zs2() const {return _spin[2][1];}
/**
* Get third spinor component for the z vector
*/
complex<Value> zs3() const {return _spin[2][2];}
/**
* Get fourth spinor component for the z vector
*/
complex<Value> zs4() const {return _spin[2][3];}
/**
* Get first spinor component for the t vector
*/
complex<Value> ts1() const {return _spin[3][0];}
/**
* Get second spinor component for the t vector
*/
complex<Value> ts2() const {return _spin[3][1];}
/**
* Get third spinor component for the t vector
*/
complex<Value> ts3() const {return _spin[3][2];}
/**
* Get fourth spinor component for the t vector
*/
complex<Value> ts4() const {return _spin[3][3];}
/**
* Set first spinor component for the x vector
*/
void setXS1(complex<Value> in) {_spin[0][0]=in;}
/**
* Set second spinor component for the x vector
*/
void setXS2(complex<Value> in) {_spin[0][1]=in;}
/**
* Set third spinor component for the x vector
*/
void setXS3(complex<Value> in) {_spin[0][2]=in;}
/**
* Set fourth spinor component for the x vector
*/
void setXS4(complex<Value> in) {_spin[0][3]=in;}
/**
* Set first spinor component for the y vector
*/
void setYS1(complex<Value> in) {_spin[1][0]=in;}
/**
* Set second spinor component for the y vector
*/
void setYS2(complex<Value> in) {_spin[1][1]=in;}
/**
* Set third spinor component for the y vector
*/
void setYS3(complex<Value> in) {_spin[1][2]=in;}
/**
* Set fourth spinor component for the y vector
*/
void setYS4(complex<Value> in) {_spin[1][3]=in;}
/**
* Set first spinor component for the z vector
*/
void setZS1(complex<Value> in) {_spin[2][0]=in;}
/**
* Set second spinor component for the z vector
*/
void setZS2(complex<Value> in) {_spin[2][1]=in;}
/**
* Set third spinor component for the z vector
*/
void setZS3(complex<Value> in) {_spin[2][2]=in;}
/**
* Set fourth spinor component for the z vector
*/
void setZS4(complex<Value> in) {_spin[2][3]=in;}
/**
* Set first spinor component for the t vector
*/
void setTS1(complex<Value> in) {_spin[3][0]=in;}
/**
* Set second spinor component for the t vector
*/
void setTS2(complex<Value> in) {_spin[3][1]=in;}
/**
* Set third spinor component for the t vector
*/
void setTS3(complex<Value> in) {_spin[3][2]=in;}
/**
* Set fourth spinor component for the t vector
*/
void setTS4(complex<Value> in ) {_spin[3][3]=in;}
//@}
/** @name Arithmetic operators. */
//@{
/**
* dot product with a polarization vector
*/
LorentzSpinorBar<Value> dot(const LorentzPolarizationVector & vec) const {
LorentzSpinorBar<Value> output(_type);
for(unsigned int ix=0;ix<4;++ix) {
output[ix]=_spin[3][ix]*vec.t()-_spin[0][ix]*vec.x()
-_spin[1][ix]*vec.y()-_spin[2][ix]*vec.z();
}
return output;
}
/**
* dot product with a 4-momentum
*/
LorentzSpinorBar<Value> dot(const LorentzMomentum & invec) const {
LorentzSpinorBar<Value> output(_type);
LorentzVector<double> vec = UnitRemoval::InvE * invec;
unsigned int ix;
for(ix=0;ix<4;++ix) {
output[ix]=_spin[3][ix]*vec.t()-_spin[0][ix]*vec.x()
-_spin[1][ix]*vec.y()-_spin[2][ix]*vec.z();
}
return output;
}
//@}
/** @name Transformations. */
//@{
/**
* return the barred spinor
*/
LorentzRSSpinor<Value> bar() const;
/**
* Standard Lorentz boost specifying the components of the beta vector.
*/
LorentzRSSpinorBar & boost(double,double,double);
/**
* Standard Lorentz boost specifying the beta vector.
*/
LorentzRSSpinorBar & boost(const Boost &);
/**
* General transform
*/
LorentzRSSpinorBar & transform(const LorentzRotation &);
//@}
/** @name Functions related to type. */
//@{
/**
* Return the type of the spinor.
*/
SpinorType Type() const {return _type;}
//@}
/**
* Current \f$\bar{f}^\alpha(c_LP_L+c_RP_R)f\f$ for general couplings.
* @param f The unbarred spinor
* @param left The left-handed coupling, \f$c_L\f$.
* @param right The right-handed coupling, \f$c_R\f$.
*/
template <typename ValueB>
- LorentzVector<complex<
- typename BinaryOpTraits<Value,ValueB>::MulT> >
- generalCurrent(LorentzSpinor<ValueB>& f, Complex left, Complex right) {
- typedef complex<typename BinaryOpTraits<Value,ValueB>::MulT> ResultT;
+ auto generalCurrent(LorentzSpinor<ValueB>& f,
+ Complex left, Complex right)
+ -> LorentzVector<decltype(left*ts1()*f.s1())>
+ {
+ typedef decltype(left*ts1()*f.s1()) ResultT;
ResultT output[4];
unsigned int iz;
for(iz=0;iz<4;++iz){
output[iz]= left*(_spin[iz][0]*f.s1()+_spin[iz][1]*f.s2())
+right*(_spin[iz][2]*f.s3()+_spin[iz][3]*f.s4());
}
return LorentzVector<ResultT>(output[0],output[1],
output[2],output[3]);
}
private:
/**
* Type of spinor.
*/
SpinorType _type;
/**
* Storage of the components.
*/
std::array<std::array<complex<Value>,4>,4> _spin;
};
}
}
#ifndef ThePEG_TEMPLATES_IN_CC_FILE
#include "LorentzRSSpinorBar.tcc"
#endif
#endif
diff --git a/Helicity/LorentzSpinor.h b/Helicity/LorentzSpinor.h
--- a/Helicity/LorentzSpinor.h
+++ b/Helicity/LorentzSpinor.h
@@ -1,494 +1,507 @@
// -*- C++ -*-
//
// LorentzSpinor.h is a part of ThePEG - Toolkit for HEP Event Generation
// Copyright (C) 2003-2017 Peter Richardson, Leif Lonnblad
//
// ThePEG is licenced under version 3 of the GPL, see COPYING for details.
// Please respect the MCnet academic guidelines, see GUIDELINES for details.
//
#ifndef ThePEG_LorentzSpinor_H
#define ThePEG_LorentzSpinor_H
// This is the declaration of the LorentzSpinor class.
#include "ThePEG/Config/ThePEG.h"
#include "ThePEG/Vectors/LorentzRotation.h"
#include "ThePEG/Vectors/ThreeVector.h"
#include "HelicityDefinitions.h"
#include "LorentzSpinor.fh"
#include "LorentzSpinorBar.h"
#include "LorentzPolarizationVector.h"
#include "LorentzTensor.h"
#include <array>
namespace ThePEG{
namespace Helicity{
/**
* The LorentzSpinor class is designed to store a spinor. In addition
* to storing the components of the spinor, information is stored on
* the representation of the type of spinor, for example u or v type.
*
* At the moment only one choice of the Dirac matrix representation
* is supported. For high-energy calculations the choice made by the
* HELAS collaboration is more efficient for numerical
* calculations. In this representation
*
* \f[
* \gamma_{i=1,2,3}=\left(\begin{array}{cc}
* 0 & \sigma_i \\
* -\sigma_i & 0
* \end{array}\right)
* \quad
* \gamma_0=\left(\begin{array}{cc}
* 0 & 1 \\
* 1 & 0
* \end{array}\right)
* \quad
* \gamma_5=\left(\begin{array}{cc}
* -1 & 0 \\
* 0 & 1
* \end{array}\right)
* \f]
*
* The type of the spinor is also stored using the SpinorType
* enumeration. There are three types supported SpinorType::u,
* SpinorType::v, SpinorType::unknown. This information is intended
* mainly for use in the case of Majorana particles where matrix
* elements can be calculated with either u or v type spinors and
* knowledge of which was used will be needed in order to give the
* correct correlations. The SpinorType::unknowne is intended for
* cases where either the spinor for an off-shell line in a matrix
* element calculation or the information is genuinely unknown.
*
* The LorentzSpinorBar class is also provided to store the barred
* spinor.
*
* @see LorentzSpinorBar
*
* @author Peter Richardson
*
*/
template<typename Value>
class LorentzSpinor {
public:
/** @name Standard constructors. */
//@{
/**
* Default zero constructor, optionally specifying \a t, the type.
*/
LorentzSpinor(SpinorType t = SpinorType::unknown) : _type(t), _spin() {}
/**
* Constructor with complex numbers specifying the components,
* optionally specifying \a s, the type.
*/
LorentzSpinor(complex<Value> a,complex<Value> b,
complex<Value> c,complex<Value> d,
SpinorType s = SpinorType::unknown) : _type(s), _spin{{a,b,c,d}} {}
//@}
/** @name Access the components. */
//@{
/**
* Subscript operator to return spinor components
*/
complex<Value> operator[](int i) const {
assert( i >= 0 && i <= 3 );
return _spin[i];
}
/**
* Subscript operator to return spinor components
*/
complex<Value> operator()(int i) const {
assert( i >= 0 && i <= 3 );
return _spin[i];
}
/**
* Set components by index.
*/
complex<Value> & operator()(int i) {
assert( i >= 0 && i <= 3 );
return _spin[i];
}
/**
* Set components by index.
*/
complex<Value> & operator[](int i) {
assert( i >= 0 && i <= 3 );
return _spin[i];
}
/**
* Get first component.
*/
complex<Value> s1() const {return _spin[0];}
/**
* Get second component.
*/
complex<Value> s2() const {return _spin[1];}
/**
* Get third component.
*/
complex<Value> s3() const {return _spin[2];}
/**
* Get fourth component.
*/
complex<Value> s4() const {return _spin[3];}
/**
* Set first component.
*/
void setS1(complex<Value> in) {_spin[0]=in;}
/**
* Set second component.
*/
void setS2(complex<Value> in) {_spin[1]=in;}
/**
* Set third component.
*/
void setS3(complex<Value> in) {_spin[2]=in;}
/**
* Set fourth component.
*/
void setS4(complex<Value> in) {_spin[3]=in;}
//@}
/** @name Transformations. */
//@{
/**
* Return the barred spinor
*/
LorentzSpinorBar<Value> bar() const;
/**
* Return the conjugated spinor \f$u_c=C\bar{u}^T\f$. This operation
* transforms u-spinors to v-spinors and vice-versa and is required when
* dealing with majorana particles.
*/
LorentzSpinor conjugate() const;
/**
* Standard Lorentz boost specifying the components of the beta vector.
*/
LorentzSpinor & boost(double,double,double);
/**
* Standard Lorentz boost specifying the beta vector.
*/
LorentzSpinor & boost(const Boost &);
/**
* General Lorentz transformation
*/
LorentzSpinor & transform(const SpinHalfLorentzRotation & );
/**
* General Lorentz transformation
*/
LorentzSpinor & transform(const LorentzRotation & r) {
transform(r.half());
return *this;
}
//@}
/** @name Functions related to type. */
//@{
/**
* Return the type of the spinor.
*/
SpinorType Type() const {return _type;}
//@}
/**
* @name Functions to apply the projection operator
*/
//@{
/**
* Apply \f$p\!\!\!\!\!\not\,\,\,+m\f$
*/
template<typename ValueB>
- LorentzSpinor<typename BinaryOpTraits<Value,ValueB>::MulT>
- projectionOperator(const LorentzVector<ValueB> & p, const ValueB & m) const {
- typedef typename BinaryOpTraits<Value,ValueB>::MulT ResultT;
- LorentzSpinor<ResultT> spin;
+ auto projectionOperator(const LorentzVector<ValueB> & p,
+ const ValueB & m) const
+ -> LorentzSpinor<decltype(m*s1())>
+ {
+ LorentzSpinor<decltype(m*s1())> spin;
static const Complex ii(0.,1.);
complex<ValueB> p0pp3=p.t()+p.z();
complex<ValueB> p0mp3=p.t()-p.z();
complex<ValueB> p1pp2=p.x()+ii*p.y();
complex<ValueB> p1mp2=p.x()-ii*p.y();
spin.setS1(m*s1()+p0mp3*s3()-p1mp2*s4());
spin.setS2(m*s2()+p0pp3*s4()-p1pp2*s3());
spin.setS3(m*s3()+p0pp3*s1()+p1mp2*s2());
spin.setS4(m*s4()+p0mp3*s2()+p1pp2*s1());
return spin;
}
/**
* Apply \f$g^LP_L+g^RP_R\f$
*/
LorentzSpinor
helicityProjectionOperator(const Complex & gL, const Complex & gR) const {
LorentzSpinor spin;
spin.setS1(gL*s1());
spin.setS2(gL*s2());
spin.setS3(gR*s3());
spin.setS4(gR*s4());
return spin;
}
//@}
/** @name Functions to calculate certain currents. */
//@{
/**
* Apply \f$p\!\!\!\!\!\not\f$
*/
template<typename ValueB>
- LorentzSpinor<typename BinaryOpTraits<Value,ValueB>::MulT>
- slash(const LorentzVector<ValueB> & p) const {
- typedef typename BinaryOpTraits<Value,ValueB>::MulT ResultT;
- LorentzSpinor<ResultT> spin;
+ auto slash(const LorentzVector<ValueB> & p) const
+ -> LorentzSpinor<decltype(p.t()*s3())>
+ {
+ LorentzSpinor<decltype(p.t()*s3())> spin;
static const Complex ii(0.,1.);
complex<ValueB> p0pp3=p.t()+p.z();
complex<ValueB> p0mp3=p.t()-p.z();
complex<ValueB> p1pp2=p.x()+ii*p.y();
complex<ValueB> p1mp2=p.x()-ii*p.y();
spin.setS1(p0mp3*s3()-p1mp2*s4());
spin.setS2(p0pp3*s4()-p1pp2*s3());
spin.setS3(p0pp3*s1()+p1mp2*s2());
spin.setS4(p0mp3*s2()+p1pp2*s1());
return spin;
}
/**
* Apply \f$p\!\!\!\!\!\not\f$
*/
template<typename ValueB>
- LorentzSpinor<typename BinaryOpTraits<Value,ValueB>::MulT>
- slash(const LorentzVector<complex<ValueB> > & p) const {
- typedef typename BinaryOpTraits<Value,ValueB>::MulT ResultT;
- LorentzSpinor<ResultT> spin;
+ auto slash(const LorentzVector<complex<ValueB> > & p) const
+ -> LorentzSpinor<decltype(p.t()*s3())>
+ {
+ LorentzSpinor<decltype(p.t()*s3())> spin;
static const Complex ii(0.,1.);
complex<ValueB> p0pp3=p.t()+p.z();
complex<ValueB> p0mp3=p.t()-p.z();
complex<ValueB> p1pp2=p.x()+ii*p.y();
complex<ValueB> p1mp2=p.x()-ii*p.y();
spin.setS1(p0mp3*s3()-p1mp2*s4());
spin.setS2(p0pp3*s4()-p1pp2*s3());
spin.setS3(p0pp3*s1()+p1mp2*s2());
spin.setS4(p0mp3*s2()+p1pp2*s1());
return spin;
}
/**
* Calculate the left-handed current \f$\bar{f}\gamma^\mu P_Lf\f$.
* @param fb The barred spinor.
*/
template<typename ValueB>
- LorentzVector<complex<typename BinaryOpTraits<Value,ValueB>::MulT> >
- leftCurrent(const LorentzSpinorBar<ValueB>& fb) const {
- typedef complex<typename BinaryOpTraits<Value,ValueB>::MulT> ResultT;
+ auto leftCurrent(const LorentzSpinorBar<ValueB>& fb) const
+ -> LorentzVector<decltype(fb.s3()*s2())>
+ {
+ typedef decltype(fb.s3()*s2()) ResultT;
LorentzVector<ResultT> vec;
Complex ii(0.,1.);
ResultT p1(fb.s3()*s2()),p2(fb.s4()*s1());
vec.setX( -(p1+p2) );
vec.setY( ii*(p1-p2) );
p1 = fb.s3()*s1();p2 = fb.s4()*s2();
vec.setZ( -(p1-p2) );
vec.setT( (p1+p2) );
return vec;
}
/**
* Calculate the right-handed current \f$\bar{f}\gamma^\mu P_Rf\f$.
* @param fb The barred spinor.
*/
template<typename ValueB>
- LorentzVector<complex<typename BinaryOpTraits<Value,ValueB>::MulT> >
- rightCurrent(const LorentzSpinorBar<ValueB>& fb) const {
- typedef complex<typename BinaryOpTraits<Value,ValueB>::MulT> ResultT;
+ auto rightCurrent(const LorentzSpinorBar<ValueB>& fb) const
+ -> LorentzVector<decltype(fb.s1()*s4())>
+ {
+ typedef decltype(fb.s1()*s4()) ResultT;
LorentzVector<ResultT> vec;
Complex ii(0.,1.);
ResultT p1(fb.s1()*s4()),p2(fb.s2()*s3());
vec.setX( (p1+p2));
vec.setY( -ii*(p1-p2));
p1 = fb.s1()*s3();p2 = fb.s2()*s4();
vec.setZ( (p1-p2));
vec.setT( (p1+p2));
return vec;
}
/**
* Calculate the vector current \f$\bar{f}\gamma^\mu f\f$
* @param fb The barred spinor.
*/
template<typename ValueB>
- LorentzVector<complex<typename BinaryOpTraits<Value,ValueB>::MulT> >
- vectorCurrent(const LorentzSpinorBar<ValueB>& fb) const {
- typedef complex<typename BinaryOpTraits<Value,ValueB>::MulT> ResultT;
+ auto vectorCurrent(const LorentzSpinorBar<ValueB>& fb) const
+ -> LorentzVector<decltype(fb.s1()*s4())>
+ {
+ typedef decltype(fb.s1()*s4()) ResultT;
LorentzVector<ResultT> vec;
Complex ii(0.,1.);
ResultT s1s4(fb.s1()*s4()),s2s3(fb.s2()*s3()),
s3s2(fb.s3()*s2()),s4s1(fb.s4()*s1()),
s1s3(fb.s1()*s3()),s2s4(fb.s2()*s4()),
s3s1(fb.s3()*s1()),s4s2(fb.s4()*s2());
vec.setX( s1s4+s2s3-s3s2-s4s1 );
vec.setY( -ii*(s1s4-s2s3-s3s2+s4s1));
vec.setZ( s1s3-s2s4-s3s1+s4s2 );
vec.setT( s1s3+s2s4+s3s1+s4s2);
return vec;
}
/**
* Calculate a general current with arbitary left and right couplings,
* i.e. \f$\bar{f}\gamma^\mu(c_lP_L+c_RP_R)f\f$
* @param fb The barred spinor.
* @param left The left coupling, \f$c_L\f$.
* @param right The right coupling, \f$c_R\f$.
*/
template<typename ValueB>
- LorentzVector<complex<typename BinaryOpTraits<Value,ValueB>::MulT> >
- generalCurrent(const LorentzSpinorBar<ValueB>& fb,
- Complex left, Complex right) const {
- typedef complex<typename BinaryOpTraits<Value,ValueB>::MulT> ResultT;
+ auto generalCurrent(const LorentzSpinorBar<ValueB>& fb,
+ Complex left, Complex right) const
+ -> LorentzVector<decltype(fb.s3()*s2())>
+ {
+ typedef decltype(fb.s3()*s2()) ResultT;
LorentzVector<ResultT> vec;
Complex ii(0.,1.);
ResultT p1(fb.s3()*s2()),p2(fb.s4()*s1());
vec.setX( -left*(p1+p2));
vec.setY( ii*left*(p1-p2));
p1 = fb.s3()*s1();p2 = fb.s4()*s2();
vec.setZ( -left*(p1-p2));
vec.setT( left*(p1+p2));
p1=fb.s1()*s4();p2=fb.s2()*s3();
vec.setX(vec.x()+right*(p1+p2));
vec.setY(vec.y()-ii*right*(p1-p2));
p1 = fb.s1()*s3();p2 = fb.s2()*s4();
vec.setZ(vec.z()+right*(p1-p2));
vec.setT(vec.t()+right*(p1+p2));
return vec;
}
//@}
/** @name Functions to calculate certain scalars. */
//@{
/**
* Calculate the left-handed scalar \f$\bar{f}P_Lf\f$.
* @param fb The barred spinor.
*/
template<typename ValueB>
- complex<typename BinaryOpTraits<Value,ValueB>::MulT>
- leftScalar(const LorentzSpinorBar<ValueB>& fb) const {
+ auto leftScalar(const LorentzSpinorBar<ValueB>& fb) const
+ -> decltype(fb.s1()*s1())
+ {
return fb.s1()*s1()+fb.s2()*s2();
}
/**
* Calculate the right-handed scalar \f$\bar{f}P_Rf\f$.
* @param fb The barred spinor.
*/
template<typename ValueB>
- complex<typename BinaryOpTraits<Value,ValueB>::MulT>
- rightScalar(const LorentzSpinorBar<ValueB>& fb) const {
+ auto rightScalar(const LorentzSpinorBar<ValueB>& fb) const
+ -> decltype(fb.s3()*s3())
+ {
return fb.s3()*s3()+fb.s4()*s4();
}
/**
* Calculate the scalar \f$\bar{f}f\f$.
* @param fb The barred spinor.
*/
template<typename ValueB>
- complex<typename BinaryOpTraits<Value,ValueB>::MulT>
- scalar(const LorentzSpinorBar<ValueB>& fb) const {
- return fb.s1()*s1()+fb.s2()*s2()+fb.s3()*s3()+fb.s4()*s4();
+ auto scalar(const LorentzSpinorBar<ValueB>& fb) const
+ -> decltype(fb.s1()*s1())
+ {
+ return fb.s1()*s1()+fb.s2()*s2()
+ +fb.s3()*s3()+fb.s4()*s4();
}
/**
* Calculate the pseudoscalar \f$\bar{f}\gamma_5f\f$.
* @param fb The barred spinor.
*/
template<typename ValueB>
- complex<typename BinaryOpTraits<Value,ValueB>::MulT>
- pseudoScalar(const LorentzSpinorBar<ValueB>& fb) const {
- return -fb.s1()*s1()-fb.s2()*s2()+fb.s3()*s3()+fb.s4()*s4();
+ auto pseudoScalar(const LorentzSpinorBar<ValueB>& fb) const
+ -> decltype(fb.s1()*s1())
+ {
+ return -fb.s1()*s1()-fb.s2()*s2()
+ +fb.s3()*s3()+fb.s4()*s4();
}
/**
* Calculate a general scalar product with arbitary left and right couplings,
* i.e. \f$\bar{f}c_lP_L+c_RP_Rf\f$
* @param fb The barred spinor.
* @param left The left coupling, \f$c_L\f$.
* @param right The right coupling, \f$c_R\f$.
*/
template<typename ValueB>
- complex<typename BinaryOpTraits<Value,ValueB>::MulT>
- generalScalar(const LorentzSpinorBar<ValueB>& fb,
- Complex left, Complex right) const {
- return left*(fb.s1()*s1()+fb.s2()*s2())
+ auto generalScalar(const LorentzSpinorBar<ValueB>& fb,
+ Complex left, Complex right) const
+ -> decltype(left*fb.s1()*s1())
+ {
+ return left*(fb.s1()*s1()+fb.s2()*s2())
+ right*(fb.s3()*s3()+fb.s4()*s4());
}
//@}
/**
* Calculate the product with \f$\sigma^{\mu\nu}\f$, i.e.
* \f$\bar{f}\sigma^{\mu\nu}f\f$
*/
template<typename ValueB>
- LorentzTensor<typename BinaryOpTraits<Value,ValueB>::MulT>
- sigma(const LorentzSpinorBar<ValueB>& fb) const {
- typedef typename BinaryOpTraits<Value,ValueB>::MulT ResultT;
+ auto sigma(const LorentzSpinorBar<ValueB>& fb) const
+ -> LorentzTensor<decltype(fb.s1()*s1())>
+ {
+ typedef decltype(fb.s1()*s1()) ResultT;
LorentzTensor<ResultT> output;
- complex<ResultT> s11(fb.s1()*s1()),s22(fb.s2()*s2()),
+ ResultT s11(fb.s1()*s1()),s22(fb.s2()*s2()),
s33(fb.s3()*s3()),s44(fb.s4()*s4()),
s12(fb.s1()*s2()),s21(fb.s2()*s1()),
s34(fb.s3()*s4()),s43(fb.s4()*s3());
Complex ii(0.,1.);
- complex<ResultT> zero;
+ ResultT zero;
zero = ZERO;
output.setTT( zero );
output.setTX(-ii*( s12+s21-s34-s43));
output.setTY( -s12+s21+s34-s43 );
output.setTZ(-ii*( s11-s22-s33+s44));
output.setXT( -output.tx() );
output.setXX( zero );
output.setXY( s11-s22+s33-s44 );
output.setXZ(-ii*(-s12+s21-s34+s43));
output.setYT( -output.ty() );
output.setYX( -output.xy() );
output.setYY( zero );
output.setYZ( s12+s21+s34+s43 );
output.setZT( -output.tz() );
output.setZX( -output.xz() );
output.setZY( -output.yz() );
output.setZZ( zero );
return output;
}
private:
/**
* Type of spinor
*/
SpinorType _type;
/**
* Storage of the components.
*/
std::array<complex<Value>,4> _spin;
};
}
}
#ifndef ThePEG_TEMPLATES_IN_CC_FILE
#include "LorentzSpinor.tcc"
#endif
#endif
diff --git a/Helicity/LorentzSpinorBar.h b/Helicity/LorentzSpinorBar.h
--- a/Helicity/LorentzSpinorBar.h
+++ b/Helicity/LorentzSpinorBar.h
@@ -1,233 +1,235 @@
// -*- C++ -*-
//
// LorentzSpinorBar.h is a part of ThePEG - Toolkit for HEP Event Generation
// Copyright (C) 2003-2017 Peter Richardson, Leif Lonnblad
//
// ThePEG is licenced under version 3 of the GPL, see COPYING for details.
// Please respect the MCnet academic guidelines, see GUIDELINES for details.
//
#ifndef ThePEG_LorentzSpinorBar_H
#define ThePEG_LorentzSpinorBar_H
// This is the declaration of the LorentzSpinorBar class.
#include "ThePEG/Config/ThePEG.h"
#include "ThePEG/Vectors/LorentzRotation.h"
#include "ThePEG/Vectors/ThreeVector.h"
#include "HelicityDefinitions.h"
#include "LorentzSpinor.fh"
#include "LorentzSpinorBar.fh"
namespace ThePEG {
namespace Helicity {
/**
* The LorentzSpinorBar class implements the storage of a barred
* LorentzSpinor. The design is based on that of the LorentzSpinor
* class where the details of the implemented are discussed in more
* detail.
*
* @see LorentzSpinor
*
* @author Peter Richardson
*/
template<typename Value>
class LorentzSpinorBar {
public:
/** @name Standard constructors. */
//@{
/**
* Default zero constructor, optionally specifying \a t, the type
*/
LorentzSpinorBar(SpinorType t = SpinorType::unknown) : _type(t), _spin() {}
/**
* Constructor with complex numbers specifying the components,
* optionally specifying \a t, the type
*/
LorentzSpinorBar(complex<Value> a, complex<Value> b,
complex<Value> c, complex<Value> d,
SpinorType t = SpinorType::unknown)
: _type(t), _spin{{a,b,c,d}} {}
//@}
/** @name Access the components. */
//@{
/**
* Subscript operator to return spinor components
*/
complex<Value> operator[](int i) const {
assert( i>= 0 && i <= 3 );
return _spin[i];
}
/**
* Subscript operator to return spinor components
*/
complex<Value> operator()(int i) const {
assert( i>= 0 && i <= 3 );
return _spin[i];
}
/**
* Set components by index.
*/
complex<Value> & operator()(int i) {
assert( i>= 0 && i <= 3 );
return _spin[i];
}
/**
* Set components by index.
*/
complex<Value> & operator[](int i) {
assert( i>= 0 && i <= 3 );
return _spin[i];
}
/**
* Get first component.
*/
complex<Value> s1() const {return _spin[0];}
/**
* Get second component.
*/
complex<Value> s2() const {return _spin[1];}
/**
* Get third component.
*/
complex<Value> s3() const {return _spin[2];}
/**
* Get fourth component.
*/
complex<Value> s4() const {return _spin[3];}
/**
* Set first component.
*/
void setS1(complex<Value> in) {_spin[0]=in;}
/**
* Set second component.
*/
void setS2(complex<Value> in) {_spin[1]=in;}
/**
* Set third component.
*/
void setS3(complex<Value> in) {_spin[2]=in;}
/**
* Set fourth component.
*/
void setS4(complex<Value> in) {_spin[3]=in;}
//@}
/** @name Transformations. */
//@{
/**
* Return the barred spinor
*/
LorentzSpinor<Value> bar() const;
/**
* Return the conjugated spinor \f$u_c=C\bar{u}^T\f$. This operation
* transforms u-spinors to v-spinors and vice-versa and is required when
* dealing with majorana particles.
*/
LorentzSpinorBar conjugate() const;
/**
* Standard Lorentz boost specifying the components of the beta vector.
*/
LorentzSpinorBar & boost(double,double,double);
/**
* Standard Lorentz boost specifying the beta vector.
*/
LorentzSpinorBar & boost(const Boost &);
/**
* General Lorentz transformation
*/
LorentzSpinorBar & transform(const SpinHalfLorentzRotation &) ;
/**
* General Lorentz transformation
*/
LorentzSpinorBar & transform(const LorentzRotation & r) {
transform(r.half());
return *this;
}
//@}
/** @name Functions related to type. */
//@{
/**
* Return the type of the spinor.
*/
SpinorType Type() const {return _type;}
//@}
/**
* @name Functions to apply the projection operator
*/
//@{
/**
* Apply \f$p\!\!\!\!\!\not\,\,\,+m\f$
*/
template<typename ValueB>
- LorentzSpinorBar<typename BinaryOpTraits<Value,ValueB>::MulT>
- projectionOperator(const LorentzVector<ValueB> & p, const ValueB & m) const {
- typedef typename BinaryOpTraits<Value,ValueB>::MulT ResultT;
+ auto projectionOperator(const LorentzVector<ValueB> & p,
+ const ValueB & m) const
+ -> LorentzSpinorBar<decltype(m*s1())>
+ {
+ typedef decltype(m*s1()) ResultT;
LorentzSpinorBar<ResultT> spin;
static const Complex ii(0.,1.);
complex<ValueB> p0pp3=p.t()+p.z();
complex<ValueB> p0mp3=p.t()-p.z();
complex<ValueB> p1pp2=p.x()+ii*p.y();
complex<ValueB> p1mp2=p.x()-ii*p.y();
spin.setS1(m*s1()+p0pp3*s3()+p1pp2*s4());
spin.setS2(m*s2()+p0mp3*s4()+p1mp2*s3());
spin.setS3(m*s3()+p0mp3*s1()-p1pp2*s2());
spin.setS4(m*s4()+p0pp3*s2()-p1mp2*s1());
return spin;
}
/**
* Apply \f$g^LP_L+g^RP_R\f$
*/
LorentzSpinorBar
helicityProjectionOperator(const Complex & gL, const Complex & gR) const {
LorentzSpinorBar spin;
spin.setS1(gL*s1());
spin.setS2(gL*s2());
spin.setS3(gR*s3());
spin.setS4(gR*s4());
return spin;
}
//@}
private:
/**
* Type of spinor
*/
SpinorType _type;
/**
* Storage of the components.
*/
std::array<complex<Value>,4> _spin;
};
}
}
#ifndef ThePEG_TEMPLATES_IN_CC_FILE
#include "LorentzSpinorBar.tcc"
#endif
#endif
diff --git a/Helicity/LorentzTensor.h b/Helicity/LorentzTensor.h
--- a/Helicity/LorentzTensor.h
+++ b/Helicity/LorentzTensor.h
@@ -1,505 +1,518 @@
// -*- C++ -*-
//
// LorentzTensor.h is a part of ThePEG - Toolkit for HEP Event Generation
// Copyright (C) 2003-2017 Peter Richardson, Leif Lonnblad
//
// ThePEG is licenced under version 3 of the GPL, see COPYING for details.
// Please respect the MCnet academic guidelines, see GUIDELINES for details.
//
#ifndef ThePEG_LorentzTensor_H
#define ThePEG_LorentzTensor_H
// This is the declaration of the LorentzTensor class.
-
+#include "ThePEG/Config/PhysicalQtyComplex.h"
#include "ThePEG/Config/ThePEG.h"
#include "LorentzPolarizationVector.h"
namespace ThePEG {
namespace Helicity {
// compiler magic needs these pre-declarations to make friend templates work
template<typename Value> class LorentzTensor;
/**
* The LorentzTensor class is designed to implement the storage of a
* complex tensor to be used to representation the wavefunction of a
* spin-2 particle.
*
* At the moment it only implements the storage of the tensor
* components but it is envisaged that it will be extended to include
* boost methods etc.
*
* @author Peter Richardson
*
*/
template<typename Value>
class LorentzTensor {
public:
/** @name Standard constructors and destructors. */
//@{
/**
* Default zero constructor.
*/
LorentzTensor() = default;
/**
* Constructor specifyign all components.
*/
LorentzTensor(complex<Value> xx, complex<Value> xy,
- complex<Value> xz, complex<Value> xt,
- complex<Value> yx, complex<Value> yy,
- complex<Value> yz, complex<Value> yt,
- complex<Value> zx, complex<Value> zy,
- complex<Value> zz, complex<Value> zt,
- complex<Value> tx, complex<Value> ty,
- complex<Value> tz, complex<Value> tt)
+ complex<Value> xz, complex<Value> xt,
+ complex<Value> yx, complex<Value> yy,
+ complex<Value> yz, complex<Value> yt,
+ complex<Value> zx, complex<Value> zy,
+ complex<Value> zz, complex<Value> zt,
+ complex<Value> tx, complex<Value> ty,
+ complex<Value> tz, complex<Value> tt)
: _tensor{{ {{xx,xy,xz,xt}},
{{yx,yy,yz,yt}},
{{zx,zy,zz,zt}},
{{tx,ty,tz,tt}} }} {}
/**
* Constructor in terms of two polarization vectors.
*/
LorentzTensor(const LorentzPolarizationVector & p,
- const LorentzPolarizationVector & q) {
+ const LorentzPolarizationVector & q) {
setXX(p.x() * q.x()); setYX(p.y() * q.x());
setZX(p.z() * q.x()); setTX(p.t() * q.x());
setXY(p.x() * q.y()); setYY(p.y() * q.y());
setZY(p.z() * q.y()); setTY(p.t() * q.y());
setXZ(p.x() * q.z()); setYZ(p.y() * q.z());
setZZ(p.z() * q.z()); setTZ(p.t() * q.z());
setXT(p.x() * q.t()); setYT(p.y() * q.t());
setZT(p.z() * q.t()); setTT(p.t() * q.t());
}
//@}
/** @name Access individual components. */
//@{
/**
* Get x,x component.
*/
complex<Value> xx() const {return _tensor[0][0];}
/**
* Get y,x component.
*/
complex<Value> yx() const {return _tensor[1][0];}
/**
* Get z,x component.
*/
complex<Value> zx() const {return _tensor[2][0];}
/**
* Get t,x component.
*/
complex<Value> tx() const {return _tensor[3][0];}
/**
* Get x,y component.
*/
complex<Value> xy() const {return _tensor[0][1];}
/**
* Get y,y component.
*/
complex<Value> yy() const {return _tensor[1][1];}
/**
* Get z,y component.
*/
complex<Value> zy() const {return _tensor[2][1];}
/**
* Get t,y component.
*/
complex<Value> ty() const {return _tensor[3][1];}
/**
* Get x,z component.
*/
complex<Value> xz() const {return _tensor[0][2];}
/**
* Get y,z component.
*/
complex<Value> yz() const {return _tensor[1][2];}
/**
* Get z,z component.
*/
complex<Value> zz() const {return _tensor[2][2];}
/**
* Get t,z component.
*/
complex<Value> tz() const {return _tensor[3][2];}
/**
* Get x,t component.
*/
complex<Value> xt() const {return _tensor[0][3];}
/**
* Get y,t component.
*/
complex<Value> yt() const {return _tensor[1][3];}
/**
* Get z,t component.
*/
complex<Value> zt() const {return _tensor[2][3];}
/**
* Get t,t component.
*/
complex<Value> tt() const {return _tensor[3][3];}
/**
* Set x,x component.
*/
void setXX(complex<Value> a) {_tensor[0][0]=a;}
/**
* Set y,x component.
*/
void setYX(complex<Value> a) {_tensor[1][0]=a;}
/**
* Set z,x component.
*/
void setZX(complex<Value> a) {_tensor[2][0]=a;}
/**
* Set t,x component.
*/
void setTX(complex<Value> a) {_tensor[3][0]=a;}
/**
* Set x,y component.
*/
void setXY(complex<Value> a) {_tensor[0][1]=a;}
/**
* Set y,y component.
*/
void setYY(complex<Value> a) {_tensor[1][1]=a;}
/**
* Set z,y component.
*/
void setZY(complex<Value> a) {_tensor[2][1]=a;}
/**
* Set t,y component.
*/
void setTY(complex<Value> a) {_tensor[3][1]=a;}
/**
* Set x,z component.
*/
void setXZ(complex<Value> a) {_tensor[0][2]=a;}
/**
* Set y,z component.
*/
void setYZ(complex<Value> a) {_tensor[1][2]=a;}
/**
* Set z,z component.
*/
void setZZ(complex<Value> a) {_tensor[2][2]=a;}
/**
* Set t,z component.
*/
void setTZ(complex<Value> a) {_tensor[3][2]=a;}
/**
* Set x,t component.
*/
void setXT(complex<Value> a) {_tensor[0][3]=a;}
/**
* Set y,t component.
*/
void setYT(complex<Value> a) {_tensor[1][3]=a;}
/**
* Set z,t component.
*/
void setZT(complex<Value> a) {_tensor[2][3]=a;}
/**
* Set t,t component.
*/
void setTT(complex<Value> a) {_tensor[3][3]=a;}
/**
* Get components by indices.
*/
complex<Value> operator () (int i, int j) const {
assert( i>=0 && i<=3 && j>=0 && j<=3);
return _tensor[i][j];
}
/**
* Set components by indices.
*/
complex<Value> & operator () (int i, int j) {
assert( i>=0 && i<=3 && j>=0 && j<=3);
return _tensor[i][j];
}
//@}
/** @name Transformations. */
//@{
/**
* Standard Lorentz boost specifying the components of the beta vector.
*/
LorentzTensor & boost(double,double,double);
/**
* Standard Lorentz boost specifying the beta vector.
*/
LorentzTensor<Value> & boost(const Boost & b) {
return boost(b.x(), b.y(), b.z());
}
/**
* General Lorentz transformation
*/
LorentzTensor & transform(const SpinOneLorentzRotation & r){
unsigned int ix,iy,ixa,iya;
LorentzTensor<Value> output;
complex<Value> temp;
for(ix=0;ix<4;++ix) {
for(iy=0;iy<4;++iy) {
- temp=complex<Value>();
- for(ixa=0;ixa<4;++ixa) {
- for(iya=0;iya<4;++iya)
- temp+=r(ix,ixa)*r(iy,iya)*(*this)(ixa,iya);
- }
- output(ix,iy)=temp;
+ temp=complex<Value>();
+ for(ixa=0;ixa<4;++ixa) {
+ for(iya=0;iya<4;++iya)
+ temp+=r(ix,ixa)*r(iy,iya)*(*this)(ixa,iya);
+ }
+ output(ix,iy)=temp;
}
}
*this=output;
return *this;
}
/**
* Return the complex conjugate.
*/
LorentzTensor<Value> conjugate() {
return LorentzTensor<Value>(conj(xx()), conj(xy()), conj(xz()), conj(xt()),
- conj(yx()), conj(yy()), conj(yz()), conj(yt()),
- conj(zx()), conj(zy()), conj(zz()), conj(zt()),
- conj(tx()), conj(ty()), conj(tz()), conj(tt()));
+ conj(yx()), conj(yy()), conj(yz()), conj(yt()),
+ conj(zx()), conj(zy()), conj(zz()), conj(zt()),
+ conj(tx()), conj(ty()), conj(tz()), conj(tt()));
}
//@}
/** @name Arithmetic operators. */
//@{
/**
* Scaling with a complex number
*/
LorentzTensor<Value> operator*=(Complex a) {
for(int ix=0;ix<4;++ix)
for(int iy=0;iy<4;++iy) _tensor[ix][iy]*=a;
return *this;
}
/**
* Scalar product with other tensor
*/
template <typename T, typename U>
- friend complex<typename BinaryOpTraits<T,U>::MulT>
- operator*(const LorentzTensor<T> & t, const LorentzTensor<U> & u);
+ friend auto
+ operator*(const LorentzTensor<T> & t, const LorentzTensor<U> & u)
+ -> decltype(t.xx()*u.xx())
+ ;
/**
* Addition.
*/
LorentzTensor<Value> operator+(const LorentzTensor<Value> & in) const {
return LorentzTensor<Value>(xx()+in.xx(),xy()+in.xy(),xz()+in.xz(),xt()+in.xt(),
- yx()+in.yx(),yy()+in.yy(),yz()+in.yz(),yt()+in.yt(),
- zx()+in.zx(),zy()+in.zy(),zz()+in.zz(),zt()+in.zt(),
- tx()+in.tx(),ty()+in.ty(),tz()+in.tz(),tt()+in.tt());
+ yx()+in.yx(),yy()+in.yy(),yz()+in.yz(),yt()+in.yt(),
+ zx()+in.zx(),zy()+in.zy(),zz()+in.zz(),zt()+in.zt(),
+ tx()+in.tx(),ty()+in.ty(),tz()+in.tz(),tt()+in.tt());
}
/**
* Subtraction.
*/
LorentzTensor<Value> operator-(const LorentzTensor<Value> & in) const {
return LorentzTensor<Value>(xx()-in.xx(),xy()-in.xy(),xz()-in.xz(),xt()-in.xt(),
- yx()-in.yx(),yy()-in.yy(),yz()-in.yz(),yt()-in.yt(),
- zx()-in.zx(),zy()-in.zy(),zz()-in.zz(),zt()-in.zt(),
- tx()-in.tx(),ty()-in.ty(),tz()-in.tz(),tt()-in.tt());
+ yx()-in.yx(),yy()-in.yy(),yz()-in.yz(),yt()-in.yt(),
+ zx()-in.zx(),zy()-in.zy(),zz()-in.zz(),zt()-in.zt(),
+ tx()-in.tx(),ty()-in.ty(),tz()-in.tz(),tt()-in.tt());
}
/**
* Trace
*/
complex<Value> trace() const {
return _tensor[3][3]-_tensor[0][0]-_tensor[1][1]-_tensor[2][2];
}
//@}
/**
* Various dot products
*/
//@{
/**
* First index dot product with polarization vector
*/
LorentzVector<complex<Value> > preDot (const LorentzPolarizationVector & vec) const {
LorentzVector<complex<Value> > output;
output.setX(vec.t()*_tensor[3][0]-vec.x()*_tensor[0][0]-
- vec.y()*_tensor[1][0]-vec.z()*_tensor[2][0]);
+ vec.y()*_tensor[1][0]-vec.z()*_tensor[2][0]);
output.setY(vec.t()*_tensor[3][1]-vec.x()*_tensor[0][1]-
- vec.y()*_tensor[1][1]-vec.z()*_tensor[2][1]);
+ vec.y()*_tensor[1][1]-vec.z()*_tensor[2][1]);
output.setZ(vec.t()*_tensor[3][2]-vec.x()*_tensor[0][2]-
- vec.y()*_tensor[1][2]-vec.z()*_tensor[2][2]);
+ vec.y()*_tensor[1][2]-vec.z()*_tensor[2][2]);
output.setT(vec.t()*_tensor[3][3]-vec.x()*_tensor[0][3]-
- vec.y()*_tensor[1][3]-vec.z()*_tensor[2][3]);
+ vec.y()*_tensor[1][3]-vec.z()*_tensor[2][3]);
return output;
}
/**
* Second index dot product with polarization vector
*/
LorentzVector<complex<Value> > postDot(const LorentzPolarizationVector & vec) const {
LorentzVector<complex<Value> > output;
output.setX(vec.t()*_tensor[0][3]-vec.x()*_tensor[0][0]-
- vec.y()*_tensor[0][1]-vec.z()*_tensor[0][2]);
+ vec.y()*_tensor[0][1]-vec.z()*_tensor[0][2]);
output.setY(vec.t()*_tensor[1][3]-vec.x()*_tensor[1][0]-
- vec.y()*_tensor[1][1]-vec.z()*_tensor[1][2]);
+ vec.y()*_tensor[1][1]-vec.z()*_tensor[1][2]);
output.setZ(vec.t()*_tensor[2][3]-vec.x()*_tensor[2][0]-
- vec.y()*_tensor[2][1]-vec.z()*_tensor[2][2]);
+ vec.y()*_tensor[2][1]-vec.z()*_tensor[2][2]);
output.setT(vec.t()*_tensor[3][3]-vec.x()*_tensor[3][0]-
- vec.y()*_tensor[3][1]-vec.z()*_tensor[3][2]);
+ vec.y()*_tensor[3][1]-vec.z()*_tensor[3][2]);
return output;
}
/**
* First index dot product with momentum
- */
- LorentzVector<complex<typename BinaryOpTraits<Value,Energy>::MulT> >
- preDot (const Lorentz5Momentum & vec) const {
- LorentzVector<complex<typename BinaryOpTraits<Value,Energy>::MulT> > output;
+ */
+ auto preDot (const Lorentz5Momentum & vec) const
+ -> LorentzVector<decltype(vec.x()*xx())>
+ {
+ LorentzVector<decltype(vec.x()*xx())> output;
output.setX(vec.t()*_tensor[3][0]-vec.x()*_tensor[0][0]-
- vec.y()*_tensor[1][0]-vec.z()*_tensor[2][0]);
+ vec.y()*_tensor[1][0]-vec.z()*_tensor[2][0]);
output.setY(vec.t()*_tensor[3][1]-vec.x()*_tensor[0][1]-
- vec.y()*_tensor[1][1]-vec.z()*_tensor[2][1]);
+ vec.y()*_tensor[1][1]-vec.z()*_tensor[2][1]);
output.setZ(vec.t()*_tensor[3][2]-vec.x()*_tensor[0][2]-
- vec.y()*_tensor[1][2]-vec.z()*_tensor[2][2]);
+ vec.y()*_tensor[1][2]-vec.z()*_tensor[2][2]);
output.setT(vec.t()*_tensor[3][3]-vec.x()*_tensor[0][3]-
- vec.y()*_tensor[1][3]-vec.z()*_tensor[2][3]);
+ vec.y()*_tensor[1][3]-vec.z()*_tensor[2][3]);
return output;
}
/**
* Second index dot product with momentum
- */
- LorentzVector<complex<typename BinaryOpTraits<Value,Energy>::MulT> >
- postDot(const Lorentz5Momentum & vec) const {
- LorentzVector<complex<typename BinaryOpTraits<Value,Energy>::MulT> > output;
+ */
+ auto postDot(const Lorentz5Momentum & vec) const
+ -> LorentzVector<decltype(vec.x()*xx())>
+ {
+ LorentzVector<decltype(vec.x()*xx())> output;
output.setX(vec.t()*_tensor[0][3]-vec.x()*_tensor[0][0]-
- vec.y()*_tensor[0][1]-vec.z()*_tensor[0][2]);
+ vec.y()*_tensor[0][1]-vec.z()*_tensor[0][2]);
output.setY(vec.t()*_tensor[1][3]-vec.x()*_tensor[1][0]-
- vec.y()*_tensor[1][1]-vec.z()*_tensor[1][2]);
+ vec.y()*_tensor[1][1]-vec.z()*_tensor[1][2]);
output.setZ(vec.t()*_tensor[2][3]-vec.x()*_tensor[2][0]-
- vec.y()*_tensor[2][1]-vec.z()*_tensor[2][2]);
+ vec.y()*_tensor[2][1]-vec.z()*_tensor[2][2]);
output.setT(vec.t()*_tensor[3][3]-vec.x()*_tensor[3][0]-
- vec.y()*_tensor[3][1]-vec.z()*_tensor[3][2]);
+ vec.y()*_tensor[3][1]-vec.z()*_tensor[3][2]);
return output;
}
//@}
private:
/**
* The components.
*/
std::array<std::array<complex<Value>,4>,4> _tensor;
};
/**
* Multiplication by a complex number.
*/
template<typename T, typename U>
-inline LorentzTensor<typename BinaryOpTraits<T,U>::MulT>
-operator*(complex<U> a, const LorentzTensor<T> & t) {
- return LorentzTensor<typename BinaryOpTraits<T,U>::MulT>
- (a*t.xx(), a*t.xy(), a*t.xz(), a*t.xt(),
+inline auto
+operator*(complex<U> a, const LorentzTensor<T> & t)
+-> LorentzTensor<decltype(a.real()*t.xx().real())>
+{
+ return
+ {a*t.xx(), a*t.xy(), a*t.xz(), a*t.xt(),
a*t.yx(), a*t.yy(), a*t.yz(), a*t.yt(),
a*t.zx(), a*t.zy(), a*t.zz(), a*t.zt(),
- a*t.tx(), a*t.ty(), a*t.tz(), a*t.tt());
+ a*t.tx(), a*t.ty(), a*t.tz(), a*t.tt()};
}
/**
* Multiply a LorentzVector by a LorentzTensor.
*/
template<typename T, typename U>
-inline LorentzVector<typename BinaryOpTraits<complex<T>,U>::MulT>
-operator*(const LorentzVector<U> & invec,
- const LorentzTensor<T> & inten) {
- LorentzVector<typename BinaryOpTraits<complex<T>,U>::MulT> outvec;
- outvec.setX(invec.t()*inten(3,0)-invec.x()*inten(0,0)
- -invec.y()*inten(1,0)-invec.z()*inten(2,0));
- outvec.setY(invec.t()*inten(3,1)-invec.x()*inten(0,1)
- -invec.y()*inten(1,1)-invec.z()*inten(2,1));
- outvec.setZ(invec.t()*inten(3,2)-invec.x()*inten(0,2)
- -invec.y()*inten(1,2)-invec.z()*inten(2,2));
- outvec.setT(invec.t()*inten(3,3)-invec.x()*inten(0,3)
- -invec.y()*inten(1,3)-invec.z()*inten(2,3));
+inline auto
+operator*(const LorentzVector<U> & v,
+ const LorentzTensor<T> & t)
+-> LorentzVector<decltype(v.t()*t(3,0))>
+{
+ LorentzVector<decltype(v.t()*t(3,0))> outvec;
+ outvec.setX( v.t()*t(3,0)-v.x()*t(0,0)
+ -v.y()*t(1,0)-v.z()*t(2,0));
+ outvec.setY( v.t()*t(3,1)-v.x()*t(0,1)
+ -v.y()*t(1,1)-v.z()*t(2,1));
+ outvec.setZ( v.t()*t(3,2)-v.x()*t(0,2)
+ -v.y()*t(1,2)-v.z()*t(2,2));
+ outvec.setT( v.t()*t(3,3)-v.x()*t(0,3)
+ -v.y()*t(1,3)-v.z()*t(2,3));
return outvec;
}
/**
* Multiply a LorentzTensor by a LorentzVector.
*/
template<typename T, typename U>
-inline LorentzVector<typename BinaryOpTraits<complex<T>,U>::MulT>
-operator*(const LorentzTensor<T> & inten, const LorentzVector<U> & invec){
- LorentzVector<typename BinaryOpTraits<complex<T>,U>::MulT> outvec;
- outvec.setX(invec.t()*inten(0,3)-invec.x()*inten(0,0)
- -invec.y()*inten(0,1)-invec.z()*inten(0,2));
- outvec.setY(invec.t()*inten(1,3)-invec.x()*inten(1,0)
- -invec.y()*inten(1,1)-invec.z()*inten(1,2));
- outvec.setZ(invec.t()*inten(2,3)-invec.x()*inten(2,0)
- -invec.y()*inten(2,1)-invec.z()*inten(2,2));
- outvec.setT(invec.t()*inten(3,3)-invec.x()*inten(3,0)
- -invec.y()*inten(3,1)-invec.z()*inten(3,2));
+inline auto
+operator*(const LorentzTensor<T> & t, const LorentzVector<U> & v)
+-> LorentzVector<decltype(v.t()*t(0,3))>
+{
+ LorentzVector<decltype(v.t()*t(0,3))> outvec;
+ outvec.setX( v.t()*t(0,3)-v.x()*t(0,0)
+ -v.y()*t(0,1)-v.z()*t(0,2));
+ outvec.setY( v.t()*t(1,3)-v.x()*t(1,0)
+ -v.y()*t(1,1)-v.z()*t(1,2));
+ outvec.setZ( v.t()*t(2,3)-v.x()*t(2,0)
+ -v.y()*t(2,1)-v.z()*t(2,2));
+ outvec.setT( v.t()*t(3,3)-v.x()*t(3,0)
+ -v.y()*t(3,1)-v.z()*t(3,2));
return outvec;
}
/**
* Multiply a LorentzTensor by a LorentzTensor
*/
template <typename T, typename U>
-inline complex<typename BinaryOpTraits<T,U>::MulT>
-operator*(const LorentzTensor<T> & t, const LorentzTensor<U> & u) {
- typedef complex<typename BinaryOpTraits<T,U>::MulT> RetT;
+inline auto
+operator*(const LorentzTensor<T> & t,
+ const LorentzTensor<U> & u)
+-> decltype(t.xx()*u.xx())
+{
+ using RetT = decltype(t.xx()*u.xx());
RetT output=RetT(),temp;
for(unsigned int ix=0;ix<4;++ix) {
temp = t._tensor[ix][3]*u._tensor[ix][3];
for(unsigned int iy=0;iy<3;++iy) {
temp+= t._tensor[ix][iy]*u._tensor[ix][iy];
}
if(ix<3) output-=temp;
else output+=temp;
}
return output;
}
}
}
#ifndef ThePEG_TEMPLATES_IN_CC_FILE
#include "LorentzTensor.tcc"
#endif
#endif
diff --git a/Helicity/epsilon.h b/Helicity/epsilon.h
--- a/Helicity/epsilon.h
+++ b/Helicity/epsilon.h
@@ -1,69 +1,66 @@
// -*- C++ -*-
//
// epsilon.h is a part of ThePEG - Toolkit for HEP Event Generation
// Copyright (C) 2003-2017 Peter Richardson, Leif Lonnblad
//
// ThePEG is licenced under version 3 of the GPL, see COPYING for details.
// Please respect the MCnet academic guidelines, see GUIDELINES for details.
//
#ifndef ThePEG_epsilon_H
#define ThePEG_epsilon_H
//
// This is the declaration of the epsilon class.
#include "ThePEG/Vectors/LorentzVector.h"
namespace ThePEG {
namespace Helicity {
/** \ingroup Helicity
* \author Peter Richardson
*
* This class is designed to combine 5-momenta and polarization
* vectors together with the result being the product with the
* eps function. The class is purely static and contains no data.
*
* @see LorentzPolarizationVector
* @see Lorentz5Vector
*/
/**
* Return the product
* \f$\epsilon^{\mu\alpha\beta\gamma}v_{1\alpha}v_{2\beta}v_{3\gamma}\f$.
* @param a The first vector \f$v_{1\alpha}\f$.
* @param b The second vector \f$v_{2\alpha}\f$.
* @param c The third vector \f$v_{3\alpha}\f$.
* @return The product
* \f$\epsilon^{\mu\alpha\beta\gamma}v_{1\alpha}v_{2\beta}v_{3\gamma}\f$.
*/
template <typename A, typename B, typename C>
- inline LorentzVector<typename BinaryOpTraits<
- typename BinaryOpTraits<A,B>::MulT, C>::MulT>
- epsilon(const LorentzVector<A> & a,
- const LorentzVector<B> & b,
- const LorentzVector<C> & c) {
- typedef typename BinaryOpTraits<A,B>::MulT ABType;
- typedef typename BinaryOpTraits<ABType, C>::MulT ABCType;
- typedef LorentzVector<ABCType> ResultType;
-
- ABType diffxy = a.x() * b.y() - a.y() * b.x();
- ABType diffxz = a.x() * b.z() - a.z() * b.x();
- ABType diffxt = a.x() * b.t() - a.t() * b.x();
- ABType diffyz = a.y() * b.z() - a.z() * b.y();
- ABType diffyt = a.y() * b.t() - a.t() * b.y();
- ABType diffzt = a.z() * b.t() - a.t() * b.z();
-
+ auto epsilon(const LorentzVector<A> & a,
+ const LorentzVector<B> & b,
+ const LorentzVector<C> & c)
+ -> LorentzVector<decltype(a.x()*b.y()*c.z())>
+ {
+ auto diffxy = a.x() * b.y() - a.y() * b.x();
+ auto diffxz = a.x() * b.z() - a.z() * b.x();
+ auto diffxt = a.x() * b.t() - a.t() * b.x();
+ auto diffyz = a.y() * b.z() - a.z() * b.y();
+ auto diffyt = a.y() * b.t() - a.t() * b.y();
+ auto diffzt = a.z() * b.t() - a.t() * b.z();
+
+ using ResultType = LorentzVector<decltype(a.x()*b.x()*c.x())>;
ResultType result;
result.setX( c.z() * diffyt - c.t() * diffyz - c.y() * diffzt);
result.setY( c.t() * diffxz - c.z() * diffxt + c.x() * diffzt);
result.setZ(-c.t() * diffxy + c.y() * diffxt - c.x() * diffyt);
result.setT(-c.z() * diffxy + c.y() * diffxz - c.x() * diffyz);
return result;
}
}
}
#endif /* ThePEG_epsilon_H */
diff --git a/Vectors/Lorentz5Vector.h b/Vectors/Lorentz5Vector.h
--- a/Vectors/Lorentz5Vector.h
+++ b/Vectors/Lorentz5Vector.h
@@ -1,395 +1,325 @@
// -*- C++ -*-
//
// Lorentz5Vector.h is a part of ThePEG - Toolkit for HEP Event Generation
// Copyright (C) 1999-2017 Leif Lonnblad
//
// ThePEG is licenced under version 3 of the GPL, see COPYING for details.
// Please respect the MCnet academic guidelines, see GUIDELINES for details.
//
#ifndef ThePEG_Lorentz5Vector_H
#define ThePEG_Lorentz5Vector_H
// This is the declaration of the Lorentz5vector class.
#include "LorentzVector.h"
#include "Lorentz5Vector.fh"
#include "ThePEG/Utilities/Maths.h"
#include "ThePEG/Utilities/Direction.h"
#include "ThePEG/Utilities/UnitIO.h"
#include "LorentzRotation.h"
namespace ThePEG {
template <typename Value>
/**
* The Lorentz5Vector inherits from the
* <code>LorentzVector</code> class. It is templated on the
* type of the member variables. The <code>Lorentz5Vector</code> class is a
* <code>LorentzVector</code> with an extra member for the invariant
* length/mass of the vector. Note that an object of the
* <code>Lorentz5Vector</code> class may be internally inconsistent in
* that the invariant length/mass of the <code>LorentzVector</code>
* class need not be the same as the member variable representing the
* invariant length/mass. The degree of inconsistency can be accessed
* with the <code>massError()</code>, <code>energyError()</code> and
* <code>rhoError()</code> methods and an object can be made consistent
* using the <code>rescaleMass()</code>, <code>rescaleEnergy()</code> or
* <code>rescaleRho()</code> methods.
*
* @see Math
*
*/
class Lorentz5Vector: public LorentzVector<Value> {
public:
/** Template argument typedef. */
- typedef typename BinaryOpTraits<Value,Value>::MulT Value2;
+ using Value2 = decltype(sqr(std::declval<Value>()));
public:
/// Component access.
//@{
Value x() const { return LorentzVector<Value>::x(); }
Value y() const { return LorentzVector<Value>::y(); }
Value z() const { return LorentzVector<Value>::z(); }
Value t() const { return LorentzVector<Value>::t(); }
//@}
public:
/** @name Constructors and destructor. */
//@{
/**
* Constructor giving the null vector.
*/
Lorentz5Vector() : mm() {}
/**
* Constructor giving the invariant length.
*/
Lorentz5Vector(Value m)
: LorentzVector<Value>(Value(), Value(), Value(), m), mm(m) {}
/**
* Constructor giving the components x, y, z, t. The invariant
* length is set to LorentzVector::mag().
*/
Lorentz5Vector(Value x, Value y, Value z, Value t = Value())
: LorentzVector<Value>(x, y, z, t) { rescaleMass(); }
/**
* Constructor giving the components x, y, z, t and invariant length.
* May result in an inconsistent Lorentz5Vector.
*/
Lorentz5Vector(Value x, Value y, Value z, Value t, Value tau)
: LorentzVector<Value>(x, y, z, t), mm(tau) {}
/**
* Constructor giving a 3-Vector and a time component. The invariant
* length is set to LorentzVector::mag().
*/
Lorentz5Vector(const ThreeVector<Value> & p, Value e)
: LorentzVector<Value>(p, e) { rescaleMass(); }
/**
* Constructor giving an invariant length and a 3-Vector
* component. The time component is set to the corresponding value.
*/
Lorentz5Vector(Value m, const ThreeVector<Value> & p)
: LorentzVector<Value>(p, sqrt(p.mag2() + m*m)), mm(m) {}
/**
* Constructor giving a 3-Vector, a time component and an invariant
* length. May result in an inconsistent Lorentz5Vector.
*/
Lorentz5Vector(const ThreeVector<Value> & p, Value t, Value tau)
: LorentzVector<Value>(p, t), mm(tau) {}
/**
* Constructor giving a LorentzVector and an invariant length.
* May result in an inconsistent Lorentz5Vector.
*/
Lorentz5Vector(const LorentzVector<Value> & p, Value m)
: LorentzVector<Value>(p), mm(m) {}
/**
* Copy from HepLorentzVector constructor. The invariant
* length is set to LorentzVector::mag().
*/
Lorentz5Vector(const LorentzVector<Value> & p)
: LorentzVector<Value>(p) { rescaleMass(); }
/**
* Construct from value type U convertible to Value.
*/
template<class U>
Lorentz5Vector(const Lorentz5Vector<U> & p)
: LorentzVector<Value>(p), mm(p.m) {}
//@}
/** @name Assignment and set functions. */
//@{
/**
* Set invariant length/mass.
*/
void setTau(Value a) { mm = a; }
/**
* Set invariant length/mass.
*/
void setMass(Value a) { mm = a; }
/**
* Assignment. The invariant length is kept fixed. May result in an
* inconsistent Lorentz5Vector.
*/
Lorentz5Vector & operator=(const LorentzVector<Value> & q) {
LorentzVector<Value>::operator=(q);
return *this;
}
//@}
/** @name Rescale functions to make consistent. */
//@{
/**
* Rescale energy, so that the invariant length/mass of the
* LorentzVector agrees with the current one.
*/
void rescaleEnergy() {
LorentzVector<Value>::setT(sqrt(LorentzVector<Value>::vect().mag2() + mass2()));
}
/**
* Rescale spatial component, so that the invariant length/mass of
* the LorentzVector agrees with the current one.
*/
void rescaleRho() {
LorentzVector<Value>::setRho(sqrt(t()*t() - mass2()));
}
/**
* Set the invariant length/mass member, so that it agrees with the
* invariant length/mass of the LorentzVector.
*/
void rescaleMass() {
mm = LorentzVector<Value>::m();
}
//@}
/** @name Check consistency. */
//@{
/**
* Return the relative inconsistency in the mass component.
*/
double massError() const {
return sqrt(abs(Math::relativeError(mass2(),
LorentzVector<Value>::m2())));
}
/**
* Return the relative inconsistency in the energy component.
*/
double energyError() const {
return sqrt(abs(Math::relativeError(t()*t(), mass2()
+ LorentzVector<Value>::vect().mag2())));
}
/**
* Return the relative inconsistency in the spatial components.
*/
double rhoError() const {
return sqrt(abs(Math::relativeError(LorentzVector<Value>::vect().mag2(),
t()*t() - mass2())));
}
//@}
/** @name Access components. */
//@{
/**
* Mass/invariant length component squared. m2() gives
* the same calculated from the LorentzVector
*/
Value2 mass2() const { return mm > Value() ? mm*mm: -mm*mm; }
/**
* Mass/invariant length component squared. m2() gives
* the same calculated from the LorentzVector
*/
Value2 tau2() const { return mass2(); }
/**
* Mass/invariant length component. m() gives the same
* calculated from the LorentzVector
*/
Value mass() const { return mm; }
/**
* Mass/invariant length component. m() gives the same
* calculated from the LorentzVector
*/
Value tau() const { return mass(); }
/**
* Return the positive negative light-cone components (depending on
* the value of Direction<0>.
*/
Value dirPlus() const {
return Direction<0>::pos() ?
LorentzVector<Value>::plus()
:
LorentzVector<Value>::minus();
}
/**
* Return the positive negative light-cone components (depending on
* the value of Direction<0>.
*/
Value dirMinus() const {
return Direction<0>::neg() ?
LorentzVector<Value>::plus()
:
LorentzVector<Value>::minus();
}
//@}
/**
* Perform a Lorentz transformation
*/
Lorentz5Vector & transform(const LorentzRotation & r)
{
LorentzVector<Value>::transform(r.one());
return *this;
}
private:
/** The invariant mass/length member. */
Value mm;
};
/** Output a Lorentz5Vector to a stream. */
template <typename OStream, typename T, typename UT>
void ounitstream(OStream & os, const Lorentz5Vector<T> & p, UT & u) {
os << ounit(p.x(), u) << ounit(p.y(), u) << ounit(p.z(), u)
<< ounit(p.e(), u) << ounit(p.mass(), u);
}
/** Input a Lorentz5Vector from a stream. */
template <typename IStream, typename T, typename UT>
void iunitstream(IStream & is, Lorentz5Vector<T> & p, UT & u) {
T x, y, z, e, mass;
is >> iunit(x, u) >> iunit(y, u) >> iunit(z, u) >> iunit(e, u)
>> iunit(mass, u);
p = Lorentz5Vector<T>(x, y, z, e, mass);
}
-template <typename T, typename U>
-struct BinaryOpTraits;
-
-/**
- * Template for multiplication by scalar
- */
-template <typename T>
-struct BinaryOpTraits<Lorentz5Vector<T>, double> {
- /** The type resulting from multiplication of the template type with
- itself. */
- typedef Lorentz5Vector<T> MulT;
- /** The type resulting from division of one template type with
- another. */
- typedef Lorentz5Vector<T> DivT;
-};
-
-/**
- * Template for multiplication by scalar
- */
-template <typename U>
-struct BinaryOpTraits<double, Lorentz5Vector<U> > {
- /** The type resulting from multiplication of the template type with
- itself. */
- typedef Lorentz5Vector<U> MulT;
-};
-
-/**
- * Template for multiplication for complex and Lorentz5Vector
- */
-template <typename T, typename U>
-struct BinaryOpTraits<Lorentz5Vector<T>, std::complex<U> > {
- /** The type resulting from multiplication of the template type with
- itself. */
- typedef Lorentz5Vector<std::complex<typename BinaryOpTraits<T,U>::MulT> > MulT;
- /** The type resulting from division of one template type with
- another. */
- typedef Lorentz5Vector<std::complex<typename BinaryOpTraits<T,U>::DivT> > DivT;
-};
-
-/**
- * Template for multiplication by scalar
- */
-template <typename T, typename U>
-struct BinaryOpTraits<std::complex<T>, Lorentz5Vector<U> > {
- /** The type resulting from multiplication of the template type with
- itself. */
- typedef Lorentz5Vector<std::complex<typename BinaryOpTraits<T,U>::MulT> > MulT;
-};
-
-/**
- * Template for multiplication of two Lorentz5Vectors
- */
-template <typename T, typename U>
-struct BinaryOpTraits<Lorentz5Vector<T>, Lorentz5Vector<U> > {
- /** The type resulting from multiplication of the template type with
- itself. */
- typedef typename BinaryOpTraits<T,U>::MulT MulT;
-};
-
-/**
- * Template for multiplication for LorentzVector and Lorentz5Vector
- */
-template <typename T, typename U>
-struct BinaryOpTraits<LorentzVector<T>, Lorentz5Vector<U> > {
- /** The type resulting from multiplication of the template type with
- itself. */
- typedef typename BinaryOpTraits<T,U>::MulT MulT;
-};
-
-/**
- * Template for multiplication for LorentzVector and Lorentz5Vector
- */
-template <typename T, typename U>
-struct BinaryOpTraits<Lorentz5Vector<T>, LorentzVector<U> > {
- /** The type resulting from multiplication of the template type with
- itself. */
- typedef typename BinaryOpTraits<T,U>::MulT MulT;
-};
/// @name Dot product overloads.
//@{
template <typename ValueA, typename ValueB>
-inline typename BinaryOpTraits<ValueA,ValueB>::MulT
-operator*(const Lorentz5Vector<ValueA> & a, const Lorentz5Vector<ValueB> & b) {
+inline auto
+operator*(const Lorentz5Vector<ValueA> & a, const Lorentz5Vector<ValueB> & b)
+-> decltype(a.dot(b))
+{
return a.dot(b);
}
template <typename ValueA, typename ValueB>
-inline typename BinaryOpTraits<ValueA,ValueB>::MulT
-operator*(const LorentzVector<ValueA> & a, const Lorentz5Vector<ValueB> & b) {
+inline auto
+operator*(const LorentzVector<ValueA> & a, const Lorentz5Vector<ValueB> & b)
+-> decltype(a.dot(b))
+{
return a.dot(b);
}
template <typename ValueA, typename ValueB>
-inline typename BinaryOpTraits<ValueA,ValueB>::MulT
-operator*(const Lorentz5Vector<ValueA> & a, const LorentzVector<ValueB> & b) {
+inline auto
+operator*(const Lorentz5Vector<ValueA> & a, const LorentzVector<ValueB> & b)
+-> decltype(a.dot(b))
+{
return a.dot(b);
}
template <typename Value>
-inline typename BinaryOpTraits<Value,Value>::MulT
-operator*(const Lorentz5Vector<Value> & a, const Lorentz5Vector<Value> & b) {
+inline auto
+operator*(const Lorentz5Vector<Value> & a, const Lorentz5Vector<Value> & b)
+-> decltype(a.dot(b))
+{
return a.dot(b);
}
//@}
}
#endif /* ThePEG_Particle_H */
diff --git a/Vectors/LorentzVector.h b/Vectors/LorentzVector.h
--- a/Vectors/LorentzVector.h
+++ b/Vectors/LorentzVector.h
@@ -1,783 +1,749 @@
// -*- C++ -*-
//
// LorentzVector.h is a part of ThePEG - Toolkit for HEP Event Generation
// Copyright (C) 2006-2017 David Grellscheid, Leif Lonnblad
//
// ThePEG is licenced under version 3 of the GPL, see COPYING for details.
// Please respect the MCnet academic guidelines, see GUIDELINES for details.
//
#ifndef ThePEG_LorentzVector_H
#define ThePEG_LorentzVector_H
/**
* @file LorentzVector.h contains the LorentzVector class. Lorentz
* vectors can be created with any unit type as template parameter.
* All basic mathematical operations are supported, as well as a
* subset of the CLHEP LorentzVector functionality.
*/
#include "LorentzVector.fh"
#include "ThePEG/Utilities/Direction.h"
#include "ThePEG/Utilities/UnitIO.h"
#include "LorentzRotation.h"
#include "ThreeVector.h"
/// Debug helper function
#ifdef NDEBUG
#define ERROR_IF(condition,message) if (false) {}
#else
#define ERROR_IF(condition,message) \
if ( condition ) throw ThePEG::Exception( (message) , ThePEG::Exception::eventerror)
#endif
namespace ThePEG {
template <typename Value> class LorentzVector;
/**
* A 4-component Lorentz vector. It can be created with any unit type
* as template parameter. All basic mathematical operations are
* supported, as well as a subset of the CLHEP LorentzVector
* functionality.
*/
template <typename Value> class LorentzVector
{
private:
/// Value squared
- typedef typename BinaryOpTraits<Value,Value>::MulT Value2;
+ using Value2 = decltype(sqr(std::declval<Value>()));
public:
/** @name Constructors. */
//@{
LorentzVector()
: theX(), theY(), theZ(), theT() {}
LorentzVector(Value x, Value y, Value z, Value t)
: theX(x), theY(y), theZ(z), theT(t) {}
LorentzVector(const ThreeVector<Value> & v, Value t)
: theX(v.x()), theY(v.y()), theZ(v.z()), theT(t) {}
template<typename U>
LorentzVector(const LorentzVector<U> & v)
: theX(v.x()), theY(v.y()), theZ(v.z()), theT(v.t()) {}
//@}
/// Assignment operator
template <typename ValueB>
LorentzVector<Value> & operator=(const LorentzVector<ValueB> & b) {
setX(b.x());
setY(b.y());
setZ(b.z());
setT(b.t());
return *this;
}
public:
/// @name Component access methods.
//@{
Value x() const { return theX; }
Value y() const { return theY; }
Value z() const { return theZ; }
Value t() const { return theT; }
Value e() const { return t(); }
//@}
/// @name Component set methods.
//@{
void setX(Value x) { theX = x; }
void setY(Value y) { theY = y; }
void setZ(Value z) { theZ = z; }
void setT(Value t) { theT = t; }
void setE(Value e) { setT(e); }
//@}
public:
/// Access to the 3-component part.
ThreeVector<Value> vect() const {
return ThreeVector<Value>(x(),y(),z());
}
/// Cast to the 3-component part.
operator ThreeVector<Value>() const { return vect(); }
/// Set the 3-component part.
void setVect(const ThreeVector<Value> & p) {
theX = p.x();
theY = p.y();
theZ = p.z();
}
public:
/// The complex conjugate vector.
LorentzVector<Value> conjugate() const
{
return LorentzVector<Value>(conj(x()),conj(y()),conj(z()),conj(t()));
}
/// Squared magnitude \f$x^\mu\,x_\mu=t^2 - \vec{x}^2\f$.
Value2 m2() const
{
return (t()-z())*(t()+z()) - sqr(x()) - sqr(y());
}
/// Squared magnitude with another vector
Value2 m2(const LorentzVector<Value> & a) const {
Value tt(a.t()+t()),zz(a.z()+z());
return (tt-zz)*(tt+zz)-sqr(a.x()+x())-sqr(a.y()+y());
}
/// Magnitude (signed) \f$\pm\sqrt{|t^2 - \vec{x}^2|}\f$.
Value m() const
{
Value2 tmp = m2();
return tmp < Value2() ? -Value(sqrt(-tmp)) : Value(sqrt(tmp));
}
/// Transverse mass squared \f$t^2-z^2\f$.
Value2 mt2() const { return (t()-z())*(t()+z()); }
/// Transverse mass (signed) \f$\pm\sqrt{|t^2 - z^2|}\f$.
Value mt() const
{
Value2 tmp = mt2();
return tmp < Value2() ? -Value(sqrt(-tmp)) : Value(sqrt(tmp));
}
/// Squared transverse component of the spatial vector \f$x^2+y^2\f$.
Value2 perp2() const { return sqr(x()) + sqr(y()); }
/// Transverse component of the spatial vector \f$\pm\sqrt{x^2 + y^2}\f$.
Value perp() const { return sqrt(perp2()); }
/**
* Squared transverse component of the spatial vector with respect to the
* given axis.
*/
template <typename U>
Value2 perp2(const ThreeVector<U> & p) const
{
return vect().perp2(p);
}
/**
* Transverse component of the spatial vector with respect to the
* given axis.
*/
template <typename U>
Value perp(const ThreeVector<U> & p) const
{
return vect().perp(p);
}
/// Transverse energy squared.
Value2 et2() const
{
Value2 pt2 = vect().perp2();
return pt2 == Value2() ? Value2() : e()*e() * pt2/(pt2+z()*z());
}
/// Transverse energy (signed).
Value et() const
{
Value2 etet = et2();
return e() < Value() ? -sqrt(etet) : sqrt(etet);
}
/// Transverse energy squared with respect to the given axis.
Value2 et2(const ThreeVector<double> & v) const
{
Value2 pt2 = vect().perp2(v);
Value pv = vect().dot(v.unit());
return pt2 == Value2() ? Value2() : e()*e() * pt2/(pt2+pv*pv);
}
/// Transverse energy with respect to the given axis (signed).
Value et(const ThreeVector<double> & v) const
{
Value2 etet = et2(v);
return e() < Value() ? -sqrt(etet) : sqrt(etet);
}
/// @name Spherical coordinates for the spatial part.
//@{
/// Radius squared.
Value2 rho2() const { return sqr(x()) + sqr(y()) + sqr(z()); }
/// Radius.
Value rho() const { return sqrt(rho2()); }
/// Set new radius.
void setRho(Value newRho)
{
Value oldRho = rho();
if (oldRho == Value())
return;
double factor = newRho / oldRho;
setX(x()*factor);
setY(y()*factor);
setZ(z()*factor);
}
/// Polar angle.
double theta() const
{
assert(!(x() == Value() && y() == Value() && z() == Value()));
return atan2(perp(),z());
}
/// Cosine of the polar angle.
double cosTheta() const
{
Value ptot = rho();
assert( ptot > Value() );
return z() / ptot;
}
/// Azimuthal angle.
double phi() const {
return atan2(y(),x()) ;
}
//@}
/// Pseudorapidity of spatial part.
double eta() const {
Value m = rho();
if ( m == Value() ) return 0.0;
Value pt = max(Constants::epsilon*m, perp());
double rap = log((m + abs(z()))/pt);
return z() > ZERO? rap: -rap;
}
/// Spatial angle with another vector.
double angle(const LorentzVector<Value> & w) const
{
return vect().angle(w.vect());
}
/// Rapidity \f$\frac{1}{2}\ln\frac{t+z}{t-z} \f$
double rapidity() const {
if ( z() == ZERO ) return 0.0;
ERROR_IF(t() <= ZERO, "Tried to take rapidity of negative-energy Lorentz vector");
Value pt = sqrt(max(sqr(t()*Constants::epsilon), perp2() + m2()));
double rap = log((t() + abs(z()))/pt);
return z() > ZERO? rap: -rap;
}
/// Rapidity with respect to another vector
double rapidity(const Axis & ref) const {
double r = ref.mag2();
ERROR_IF(r == 0,"A zero vector used as reference to LorentzVector rapidity");
Value vdotu = vect().dot(ref)/sqrt(r);
if ( vdotu == ZERO ) return 0.0;
ERROR_IF(t() <= ZERO, "Tried to take rapidity of negative-energy Lorentz vector");
Value pt = sqrt(max(sqr(t()*Constants::epsilon), perp2(ref) + m2()));
double rap = log((t() + abs(z()))/pt);
return z() > ZERO? rap: -rap;
}
/**
* Boost from reference frame into this vector's rest
* frame: \f$\frac{\vec{x}}{t}\f$.
*/
Boost boostVector() const {
if (t() == Value()) {
if (rho2() == Value2())
return Boost();
else
ERROR_IF(true,"boostVector computed for LorentzVector with t=0 -- infinite result");
}
// result will make analytic sense but is physically meaningless
ERROR_IF(m2() <= Value2(),"boostVector computed for a non-timelike LorentzVector");
return vect() * (1./t());
}
/**
* Boost from reference frame into this vector's rest
* frame: \f$-\frac{\vec{x}}{t}\f$.
*/
Boost findBoostToCM() const
{
return -boostVector();
}
/// Returns the positive light-cone component \f$t + z\f$.
Value plus() const { return t() + z(); }
/// Returns the negative light-cone component \f$t - z\f$.
Value minus() const { return t() - z(); }
/// Are two vectors nearby, using Euclidean measure \f$t^2 + |\vec{x}|^2\f$?
bool isNear(const LorentzVector<Value> & w, double epsilon) const
{
Value2 limit = abs(vect().dot(w.vect()));
limit += 0.25 * sqr( t() + w.t() );
limit *= sqr(epsilon);
Value2 delta = (vect() - w.vect()).mag2();
delta += sqr( t() - w.t() );
return (delta <= limit);
}
/// Rotate the vector. Resets \f$x^\mu\rightarrow\mathsf{M}^\mu_\nu x^\nu\f$.
LorentzVector<Value> & transform(const SpinOneLorentzRotation & m)
{
return *this = m.operator*(*this);
}
/// Rotate the vector. Resets \f$x^\mu\rightarrow\mathsf{M}^\mu_\nu x^\nu\f$.
LorentzVector<Value> & operator*=(const SpinOneLorentzRotation & m)
{
return transform(m);
}
/// Dot product with metric \f$(+,-,-,-)\f$
template <typename U>
- typename BinaryOpTraits<Value,U>::MulT
- dot(const LorentzVector<U> & a) const
+ auto dot(const LorentzVector<U> & a) const -> decltype(t() * a.t())
{
return t() * a.t() - ( x() * a.x() + y() * a.y() + z() * a.z() );
}
public:
/**
* Apply boost.
*
* @param bx Component x of the boost.
* @param by Component y of the boost.
* @param bz Component z of the boost.
* @param gamma Optional gamma parameter for higher numerical
* accuracy. The user has to ensure consistency. If not given, it
* will be calculated as \f$\gamma=1/\sqrt{1-\beta^2}\f$.
*
*/
LorentzVector<Value> &
boost(double bx, double by, double bz, double gamma=-1.)
{
const double b2 = bx*bx + by*by + bz*bz;
if ( b2 == 0.0 ) return *this;
if ( gamma < 0.0 ) {
gamma = 1.0 / sqrt(1.0 - b2);
}
const Value bp = bx*x() + by*y() + bz*z();
const double gamma2 = (gamma - 1.0)/b2;
setX(x() + gamma2*bp*bx + gamma*bx*t());
setY(y() + gamma2*bp*by + gamma*by*t());
setZ(z() + gamma2*bp*bz + gamma*bz*t());
setT(gamma*(t() + bp));
return *this;
}
/**
* Apply boost.
*
* @param b Three-vector giving the boost.
*
* @param gamma Optional gamma parameter for higher numerical
* accuracy. The user has to ensure consistency. If not given, it
* will be calculated as \f$\gamma=1/\sqrt{1-\beta^2}\f$.
*
*/
LorentzVector<Value> & boost(Boost b, double gamma=-1.) {
return boost(b.x(), b.y(), b.z(),gamma);
}
/**
* Apply rotation around the x-axis.
*
* @param phi Angle in radians.
*/
LorentzVector<Value> & rotateX (double phi) {
double sinphi = sin(phi);
double cosphi = cos(phi);
Value ty = y() * cosphi - z() * sinphi;
theZ = z() * cosphi + y() * sinphi;
theY = ty;
return *this;
}
/**
* Apply rotation around the y-axis.
*
* @param phi Angle in radians.
*/
LorentzVector<Value> & rotateY (double phi) {
double sinphi = sin(phi);
double cosphi = cos(phi);
Value tz = z() * cosphi - x() * sinphi;
theX = x() * cosphi + z() * sinphi;
theZ = tz;
return *this;
}
/**
* Apply rotation around the z-axis.
*
* @param phi Angle in radians.
*/
LorentzVector<Value> & rotateZ (double phi) {
double sinphi = sin(phi);
double cosphi = cos(phi);
Value tx = x() * cosphi - y() * sinphi;
theY = y() * cosphi + x() * sinphi;
theX = tx;
return *this;
}
/**
* Rotate the reference frame to a new z-axis.
*/
LorentzVector<Value> & rotateUz (const Axis & axis) {
Axis ax = axis.unit();
double u1 = ax.x();
double u2 = ax.y();
double u3 = ax.z();
double up = u1*u1 + u2*u2;
if (up>0) {
up = sqrt(up);
Value px = x(), py = y(), pz = z();
setX( (u1*u3*px - u2*py)/up + u1*pz );
setY( (u2*u3*px + u1*py)/up + u2*pz );
setZ( -up*px + u3*pz );
}
else if (u3 < 0.) {
setX(-x());
setZ(-z());
}
return *this;
}
/**
* Apply a rotation.
* @param angle Rotation angle in radians.
* @param axis Rotation axis.
*/
template <typename U>
LorentzVector<Value> & rotate(double angle, const ThreeVector<U> & axis) {
if (angle == 0.0)
return *this;
const U ll = axis.mag();
assert( ll > U() );
const double sa = sin(angle), ca = cos(angle);
const double dx = axis.x()/ll, dy = axis.y()/ll, dz = axis.z()/ll;
const Value xx = x(), yy = y(), zz = z();
setX((ca+(1-ca)*dx*dx) * xx
+((1-ca)*dx*dy-sa*dz) * yy
+((1-ca)*dx*dz+sa*dy) * zz
);
setY(((1-ca)*dy*dx+sa*dz) * xx
+(ca+(1-ca)*dy*dy) * yy
+((1-ca)*dy*dz-sa*dx) * zz
);
setZ(((1-ca)*dz*dx-sa*dy) * xx
+((1-ca)*dz*dy+sa*dx) * yy
+(ca+(1-ca)*dz*dz) * zz
);
return *this;
}
public:
/// @name Mathematical assignment operators.
//@{
template <typename ValueB>
LorentzVector<Value> & operator+=(const LorentzVector<ValueB> & a) {
theX += a.x();
theY += a.y();
theZ += a.z();
theT += a.t();
return *this;
}
template <typename ValueB>
LorentzVector<Value> & operator-=(const LorentzVector<ValueB> & a) {
theX -= a.x();
theY -= a.y();
theZ -= a.z();
theT -= a.t();
return *this;
}
LorentzVector<Value> & operator*=(double a) {
theX *= a;
theY *= a;
theZ *= a;
theT *= a;
return *this;
}
LorentzVector<Value> & operator/=(double a) {
theX /= a;
theY /= a;
theZ /= a;
theT /= a;
return *this;
}
//@}
private:
/// @name Vector components
//@{
Value theX;
Value theY;
Value theZ;
Value theT;
//@}
};
/// @name Basic mathematical operations
//@{
template <typename Value>
inline LorentzVector<double>
operator/(const LorentzVector<Value> & v, Value a) {
return LorentzVector<double>(v.x()/a, v.y()/a, v.z()/a, v.t()/a);
}
inline LorentzVector<Complex>
operator/(const LorentzVector<Complex> & v, Complex a) {
return LorentzVector<Complex>(v.x()/a, v.y()/a, v.z()/a, v.t()/a);
}
template <typename Value>
inline LorentzVector<Value> operator-(const LorentzVector<Value> & v) {
return LorentzVector<Value>(-v.x(),-v.y(),-v.z(),-v.t());
}
template <typename ValueA, typename ValueB>
inline LorentzVector<ValueA>
operator+(LorentzVector<ValueA> a, const LorentzVector<ValueB> & b) {
return a += b;
}
template <typename ValueA, typename ValueB>
inline LorentzVector<ValueA>
operator-(LorentzVector<ValueA> a, const LorentzVector<ValueB> & b) {
return a -= b;
}
template <typename Value>
inline LorentzVector<Value>
operator*(const LorentzVector<Value> & a, double b) {
return LorentzVector<Value>(a.x()*b, a.y()*b, a.z()*b, a.t()*b);
}
template <typename Value>
inline LorentzVector<Value>
operator*(double b, LorentzVector<Value> a) {
return a *= b;
}
template <typename ValueA, typename ValueB>
-inline
-LorentzVector<typename BinaryOpTraits<ValueA,ValueB>::MulT>
-operator*(ValueB a, const LorentzVector<ValueA> & v) {
- typedef typename BinaryOpTraits<ValueB,ValueA>::MulT ResultT;
- return LorentzVector<ResultT>(a*v.x(), a*v.y(), a*v.z(), a*v.t());
+inline auto operator*(ValueB a, const LorentzVector<ValueA> & v)
+-> LorentzVector<decltype(a*v.x())>
+{
+ return {a*v.x(), a*v.y(), a*v.z(), a*v.t()};
}
template <typename ValueA, typename ValueB>
-inline
-LorentzVector<typename BinaryOpTraits<ValueA,ValueB>::MulT>
-operator*(const LorentzVector<ValueA> & v, ValueB b) {
+inline auto operator*(const LorentzVector<ValueA> & v, ValueB b)
+-> LorentzVector<decltype(b*v.x())>
+{
return b*v;
}
template <typename ValueA, typename ValueB>
-inline
-LorentzVector<typename BinaryOpTraits<ValueA,ValueB>::DivT>
-operator/(const LorentzVector<ValueA> & v, ValueB b) {
- typedef typename BinaryOpTraits<ValueA,ValueB>::DivT ResultT;
- return LorentzVector<ResultT>(v.x()/b, v.y()/b, v.z()/b, v.t()/b);
+inline auto operator/(const LorentzVector<ValueA> & v, ValueB b)
+-> LorentzVector<decltype(v.x()/b)>
+{
+ return {v.x()/b, v.y()/b, v.z()/b, v.t()/b};
}
//@}
/// @name Scalar product with metric \f$(+,-,-,-)\f$
//@{
template <typename ValueA, typename ValueB>
-inline typename BinaryOpTraits<ValueA,ValueB>::MulT
-operator*(const LorentzVector<ValueA> & a, const LorentzVector<ValueB> & b) {
+inline auto
+operator*(const LorentzVector<ValueA> & a, const LorentzVector<ValueB> & b)
+-> decltype(a.dot(b))
+{
return a.dot(b);
}
-template <typename Value>
-inline typename BinaryOpTraits<Value,Value>::MulT
-operator*(const LorentzVector<Value> & a, const LorentzVector<Value> & b) {
- return a.dot(b);
-}
//@}
/// Equality
template <typename Value>
inline bool
operator==(const LorentzVector<Value> & a, const LorentzVector<Value> & b) {
return a.x() == b.x() && a.y() == b.y() && a.z() == b.z() && a.t() == b.t();
}
/// Stream output. Format \f$(x,y,z;t)\f$.
inline ostream & operator<< (ostream & os, const LorentzVector<double> & v) {
return os << "(" << v.x() << "," << v.y() << "," << v.z()
<< ";" << v.t() << ")";
}
/** Return the positive light-cone component. Or negative if the
* current Direction<0> is reversed. */
template <typename Value>
inline Value dirPlus(const LorentzVector<Value> & p) {
return Direction<0>::pos()? p.plus(): p.minus();
}
/** Return the negative light-cone component. Or positive if the
* current Direction<0> is reversed. */
template <typename Value>
inline Value dirMinus(const LorentzVector<Value> & p) {
return Direction<0>::neg()? p.plus(): p.minus();
}
/** Return the component along the positive z-axis. Or the negative
* z-axis if the current Direction<0> is reversed. */
template <typename Value>
inline Value dirZ(const LorentzVector<Value> & p) {
return Direction<0>::dir()*p.z();
}
/** Return the polar angle wrt. the positive z-axis. Or the negative
* z-axis if the current Direction<0> is reversed. */
template <typename Value>
inline double dirTheta(const LorentzVector<Value> & p) {
return Direction<0>::pos()? p.theta(): Constants::pi - p.theta();
}
/** Return the cosine of the polar angle wrt. the positive z-axis. Or
* the negative z-axis if the current Direction<0> is reversed. */
template <typename Value>
inline double dirCosTheta(const LorentzVector<Value> & p) {
return Direction<0>::pos()? p.cosTheta(): -p.cosTheta();
}
/** Get the boost vector for the LorentzVector. If the current
* Direction<0> is reversed, so is the z-component. */
template <typename Value>
inline ThreeVector<Value> dirBoostVector(const LorentzVector<Value> & p) {
ThreeVector<Value> b(p.boostVector());
if ( Direction<0>::neg() ) b.setZ(-b.z());
return b;
}
/** Create a LorentzVector giving its light-cone and transverse
* components. */
template <typename Value>
inline LorentzVector<Value>
lightCone(Value plus, Value minus, Value x, Value y) {
LorentzVector<Value> r(x, y, 0.5*(plus-minus), 0.5*(plus+minus));
return r;
}
/** Create a LorentzVector giving its light-cone components. */
template <typename Value>
inline LorentzVector<Value>
lightCone(Value plus, Value minus) {
// g++-3.3 has a problem with using Value() directly
// gcc-bug c++/3650, fixed in 3.4
static const Value zero = Value();
LorentzVector<Value> r(zero, zero,
0.5*(plus-minus), 0.5*(plus+minus));
return r;
}
}
// delayed header inclusion to break inclusion loop:
// LorentzVec -> Transverse -> Lorentz5Vec -> LorentzVec
#include "Transverse.h"
namespace ThePEG {
/** Create a LorentzVector giving its light-cone and transverse
* components. */
template <typename Value>
inline LorentzVector<Value>
lightCone(Value plus, Value minus, Transverse<Value> pt) {
LorentzVector<Value> r(pt.x(), pt.y(), 0.5*(plus-minus), 0.5*(plus+minus));
return r;
}
/** Create a LorentzVector giving its light-cone and transverse
* components. If the current Direction<0> is reversed, so is the
* z-component. */
template <typename Value>
inline LorentzVector<Value>
lightConeDir(Value plus, Value minus,
Value x = Value(), Value y = Value()) {
LorentzVector<Value> r(x, y, Direction<0>::dir()*0.5*(plus - minus),
0.5*(plus + minus));
return r;
}
/** Create a LorentzVector giving its light-cone and transverse
* components. If the current Direction<0> is reversed, so is the
* z-component. */
template <typename Value>
inline LorentzVector<Value>
lightConeDir(Value plus, Value minus, Transverse<Value> pt) {
LorentzVector<Value> r(pt.x(), pt.y(), Direction<0>::dir()*0.5*(plus - minus),
0.5*(plus + minus));
return r;
}
/** Output a LorentzVector with units to a stream. */
template <typename OStream, typename UnitT, typename Value>
void ounitstream(OStream & os, const LorentzVector<Value> & p, UnitT & u) {
os << ounit(p.x(), u) << ounit(p.y(), u) << ounit(p.z(), u)
<< ounit(p.e(), u);
}
/** Input a LorentzVector with units from a stream. */
template <typename IStream, typename UnitT, typename Value>
void iunitstream(IStream & is, LorentzVector<Value> & p, UnitT & u) {
Value x, y, z, e;
is >> iunit(x, u) >> iunit(y, u) >> iunit(z, u) >> iunit(e, u);
p = LorentzVector<Value>(x, y, z, e);
}
-/// @name Traits for binary operations
-//@{
-template <typename T, typename U>
-struct BinaryOpTraits;
-/**
- * Template for multiplication by scalar
- */
-template <typename T, typename U>
-struct BinaryOpTraits<LorentzVector<T>, U> {
- /** The type resulting from multiplication of the template type with
- itself. */
- typedef LorentzVector<typename BinaryOpTraits<T,U>::MulT> MulT;
- /** The type resulting from division of one template type with
- another. */
- typedef LorentzVector<typename BinaryOpTraits<T,U>::DivT> DivT;
-};
-
-/**
- * Template for multiplication by scalar
- */
-template <typename T, typename U>
-struct BinaryOpTraits<T, LorentzVector<U> > {
- /** The type resulting from multiplication of the template type with
- itself. */
- typedef LorentzVector<typename BinaryOpTraits<T,U>::MulT> MulT;
-};
-//@}
-
}
#undef ERROR_IF
#endif /* ThePEG_LorentzVector_H */
diff --git a/Vectors/ThreeVector.h b/Vectors/ThreeVector.h
--- a/Vectors/ThreeVector.h
+++ b/Vectors/ThreeVector.h
@@ -1,426 +1,421 @@
// -*- C++ -*-
//
// ThreeVector.h is a part of ThePEG - Toolkit for HEP Event Generation
// Copyright (C) 2006-2017 David Grellscheid, Leif Lonnblad
//
// ThePEG is licenced under version 3 of the GPL, see COPYING for details.
// Please respect the MCnet academic guidelines, see GUIDELINES for details.
//
#ifndef ThePEG_ThreeVector_H
#define ThePEG_ThreeVector_H
/**
* @file ThreeVector.h contains the ThreeVector class. ThreeVector can be
* created with any unit type as template parameter. All basic
* mathematical operations are supported, as well as a subset of the
* CLHEP Vector3 functionality.
*/
#include "ThreeVector.fh"
#include "ThePEG/Config/ThePEG.h"
#include "ThePEG/Utilities/UnitIO.h"
#include <cassert>
#include <cmath>
namespace ThePEG {
/**
* A 3-component vector. It can be created with any unit type
* as template parameter. All basic mathematical operations are
* supported, as well as a subset of the CLHEP Vector3
* functionality.
*/
template <typename Value>
class ThreeVector
-{
+{
private:
/// Value squared
- typedef typename BinaryOpTraits<Value,Value>::MulT Value2;
- /// Value to the 4th power
- typedef typename BinaryOpTraits<Value2,Value2>::MulT Value4;
+ using Value2 = decltype(sqr(std::declval<Value>()));
public:
/** @name Constructors. */
//@{
ThreeVector()
: theX(), theY(), theZ() {}
ThreeVector(Value x, Value y, Value z)
: theX(x), theY(y), theZ(z) {}
template<typename ValueB>
ThreeVector(const ThreeVector<ValueB> & v)
: theX(v.x()), theY(v.y()), theZ(v.z()) {}
//@}
public:
/// @name Component access methods.
//@{
Value x() const { return theX; }
Value y() const { return theY; }
Value z() const { return theZ; }
//@}
/// @name Component set methods.
//@{
void setX(Value x) { theX = x; }
void setY(Value y) { theY = y; }
void setZ(Value z) { theZ = z; }
//@}
public:
/// Squared magnitude \f$x^2+y^2+z^2\f$.
Value2 mag2() const { return sqr(x()) + sqr(y()) + sqr(z()); }
/// Magnitude \f$\sqrt{x^2+y^2+z^2}\f$.
Value mag() const { return sqrt(mag2()); }
/// Squared transverse component \f$x^2+y^2\f$.
Value2 perp2() const { return sqr(x()) + sqr(y()); }
/// Transverse component \f$\sqrt{x^2+y^2}\f$.
Value perp() const { return sqrt(perp2()); }
/// Dot product.
template <typename U>
- typename BinaryOpTraits<Value,U>::MulT
- dot(const ThreeVector<U> & a) const {
+ auto dot(const ThreeVector<U> & a) const
+ -> decltype(x()*a.x())
+ {
return x()*a.x() + y()*a.y() + z()*a.z();
}
/// Squared transverse component with respect to the given axis.
template <typename U>
Value2 perp2(const ThreeVector<U> & p) const {
- typedef typename BinaryOpTraits<U,U>::MulT pSqType;
- const pSqType pMag2 = p.mag2();
- assert( pMag2 > pSqType() );
- typename BinaryOpTraits<Value,U>::MulT
- ss = this->dot(p);
+ const auto pMag2 = p.mag2();
+ assert( pMag2 > ZERO );
+ auto ss = this->dot(p);
Value2 ret = mag2() - sqr(ss)/pMag2;
- if ( ret <= Value2() )
- ret = Value2();
+ if ( ret <= ZERO )
+ ret = ZERO;
return ret;
}
/// Transverse component with respect to the given axis.
template <typename U>
Value perp(const ThreeVector<U> & p) const {
return sqrt(perp2(p));
}
/// @name Spherical coordinates.
//@{
/// Polar angle.
double theta() const {
- assert(!(x() == Value() && y() == Value() && z() == Value()));
+ assert(!(x() == ZERO && y() == ZERO && z() == ZERO));
return atan2(perp(),z());
}
/// Azimuthal angle.
double phi() const {
return atan2(y(),x());
}
/// Set the polar angle.
void setTheta(double th) {
double ma = mag();
double ph = phi();
setX(ma*sin(th)*cos(ph));
setY(ma*sin(th)*sin(ph));
setZ(ma*cos(th));
}
/// Set the azimuthal angle.
void setPhi(double ph) {
double xy = perp();
setX(xy*cos(ph));
setY(xy*sin(ph));
}
//@}
/// Parallel vector with unit length.
ThreeVector<double> unit() const {
Value2 mg2 = mag2();
- assert(mg2 > Value2());
+ assert(mg2 > ZERO);
Value mg = sqrt(mg2);
- return ThreeVector<double>(x()/mg, y()/mg, z()/mg);
+ return {x()/mg, y()/mg, z()/mg};
}
/// Orthogonal vector.
ThreeVector<Value> orthogonal() const {
Value xx = abs(x());
Value yy = abs(y());
Value zz = abs(z());
+ using TVec = ThreeVector<Value>;
if (xx < yy) {
- return xx < zz ? ThreeVector<Value>(Value(),z(),-y())
- : ThreeVector<Value>(y(),-x(),Value());
+ return xx < zz ? TVec{ZERO,z(),-y()} : TVec{y(),-x(),ZERO};
} else {
- return yy < zz ? ThreeVector<Value>(-z(),Value(),x())
- : ThreeVector<Value>(y(),-x(),Value());
+ return yy < zz ? TVec{-z(),ZERO,x()} : TVec{y(),-x(),ZERO};
}
}
/// Azimuthal angle difference, brought into the range \f$(-\pi,\pi]\f$.
template <typename U>
double deltaPhi (const ThreeVector<U> & v2) const {
double dphi = v2.phi() - phi();
if ( dphi > Constants::pi ) {
dphi -= Constants::twopi;
} else if ( dphi <= -Constants::pi ) {
dphi += Constants::twopi;
}
return dphi;
}
/**
* Apply a rotation.
* @param angle Rotation angle in radians.
* @param axis Rotation axis.
*/
template <typename U>
ThreeVector<Value> & rotate(double angle, const ThreeVector<U> & axis) {
if (angle == 0.0)
return *this;
const U ll = axis.mag();
- assert( ll > U() );
+ assert( ll > ZERO );
const double sa = sin(angle), ca = cos(angle);
const double dx = axis.x()/ll, dy = axis.y()/ll, dz = axis.z()/ll;
const Value xx = x(), yy = y(), zz = z();
setX((ca+(1-ca)*dx*dx) * xx
- +((1-ca)*dx*dy-sa*dz) * yy
- +((1-ca)*dx*dz+sa*dy) * zz
- );
+ +((1-ca)*dx*dy-sa*dz) * yy
+ +((1-ca)*dx*dz+sa*dy) * zz
+ );
setY(((1-ca)*dy*dx+sa*dz) * xx
- +(ca+(1-ca)*dy*dy) * yy
- +((1-ca)*dy*dz-sa*dx) * zz
- );
+ +(ca+(1-ca)*dy*dy) * yy
+ +((1-ca)*dy*dz-sa*dx) * zz
+ );
setZ(((1-ca)*dz*dx-sa*dy) * xx
- +((1-ca)*dz*dy+sa*dx) * yy
- +(ca+(1-ca)*dz*dz) * zz
- );
+ +((1-ca)*dz*dy+sa*dx) * yy
+ +(ca+(1-ca)*dz*dz) * zz
+ );
return *this;
}
/**
* Rotate the reference frame to a new z-axis.
*/
ThreeVector<Value> & rotateUz (const Axis & axis) {
Axis ax = axis.unit();
double u1 = ax.x();
double u2 = ax.y();
double u3 = ax.z();
double up = u1*u1 + u2*u2;
if (up>0) {
up = sqrt(up);
Value px = x(), py = y(), pz = z();
setX( (u1*u3*px - u2*py)/up + u1*pz );
setY( (u2*u3*px + u1*py)/up + u2*pz );
setZ( -up*px + u3*pz );
}
else if (u3 < 0.) {
setX(-x());
setZ(-z());
}
return *this;
}
/**
* Rotate from a reference frame to the z-axis.
*/
ThreeVector<Value> & rotateUzBack (const Axis & axis) {
Axis ax = axis.unit();
double u1 = ax.x();
double u2 = ax.y();
double u3 = ax.z();
double up = u1*u1 + u2*u2;
if (up>0) {
up = sqrt(up);
Value px = x(), py = y(), pz = z();
setX( ( u1*u3*px + u2*u3*py)/up - up*pz );
setY( (-u2*px + u1*py)/up );
setZ( u1*px + u2*py + u3*pz );
}
else if (u3 < 0.) {
setX(-x());
setZ(-z());
}
return *this;
}
/// Vector cross-product
template <typename U>
- ThreeVector<typename BinaryOpTraits<Value,U>::MulT>
- cross(const ThreeVector<U> & a) const {
- typedef ThreeVector<typename BinaryOpTraits<Value,U>::MulT> ResultT;
- return ResultT( y()*a.z()-z()*a.y(),
- -x()*a.z()+z()*a.x(),
- x()*a.y()-y()*a.x());
+ auto cross(const ThreeVector<U> & a) const
+ -> ThreeVector<decltype(y()*a.z())>
+ {
+ return { y()*a.z()-z()*a.y(),
+ -x()*a.z()+z()*a.x(),
+ x()*a.y()-y()*a.x() };
}
public:
/// @name Comparison operators.
//@{
bool operator==(const ThreeVector<Value> & a) const {
return (theX == a.x() && theY == a.y() && theZ == a.z());
}
bool operator!=(const ThreeVector<Value> & a) const {
return !(*this == a);
}
bool almostEqual(const ThreeVector<Value> & a, double threshold = 1e-04) const {
return ((std::abs(theX - a.x()) < threshold) && (std::abs(theY - a.y()) < threshold) && (std::abs(theZ - a.z()) < threshold));
}
bool almostUnequal(const ThreeVector<Value> & a, double threshold = 1e-04) const {
return ! this->almostEqual(a, threshold);
}
//@}
public:
/// @name Mathematical assignment operators.
//@{
ThreeVector<Value> & operator+=(const ThreeVector<Value> & a) {
theX += a.x();
theY += a.y();
theZ += a.z();
return *this;
}
ThreeVector<Value> & operator-=(const ThreeVector<Value> & a) {
theX -= a.x();
theY -= a.y();
theZ -= a.z();
return *this;
}
ThreeVector<Value> & operator*=(double a) {
theX *= a;
theY *= a;
theZ *= a;
return *this;
}
ThreeVector<Value> & operator/=(double a) {
theX /= a;
theY /= a;
theZ /= a;
return *this;
}
//@}
/// Cosine of the azimuthal angle between two vectors.
template <typename U>
double cosTheta(const ThreeVector<U> & q) const {
- typedef typename BinaryOpTraits<Value,U>::MulT
- ProdType;
- ProdType ptot = mag()*q.mag();
- assert( ptot > ProdType() );
+ auto ptot = mag()*q.mag();
+ assert( ptot > ZERO );
double arg = dot(q)/ptot;
if (arg > 1.0) arg = 1.0;
else if(arg < -1.0) arg = -1.0;
return arg;
}
/// Angle between two vectors.
template <typename U>
double angle(const ThreeVector<U> & v) const {
return acos(cosTheta(v));
}
private:
/// @name Vector components
//@{
Value theX;
Value theY;
Value theZ;
//@}
};
/// Stream output. Format \f$(x,y,z)\f$.
inline ostream &
operator<< (ostream & os, const ThreeVector<double> & v)
{
return os << '(' << v.x() << ',' << v.y() << ',' << v.z() << ')';
}
/// @name Basic mathematical operations
//@{
template <typename Value>
inline ThreeVector<Value>
operator+(ThreeVector<Value> a,
- const ThreeVector<Value> & b)
+ const ThreeVector<Value> & b)
{
return a += b;
}
template <typename Value>
inline ThreeVector<Value>
operator-(ThreeVector<Value> a,
- const ThreeVector<Value> & b)
+ const ThreeVector<Value> & b)
{
return a -= b;
}
template <typename Value>
inline ThreeVector<Value> operator-(const ThreeVector<Value> & v) {
- return ThreeVector<Value>(-v.x(),-v.y(),-v.z());
+ return {-v.x(),-v.y(),-v.z()};
}
template <typename Value>
inline ThreeVector<Value> operator*(ThreeVector<Value> v, double a) {
return v *= a;
}
template <typename Value>
inline ThreeVector<Value> operator*(double a, ThreeVector<Value> v) {
return v *= a;
}
template <typename ValueA, typename ValueB>
-inline ThreeVector<typename BinaryOpTraits<ValueA,ValueB>::MulT>
-operator*(ValueB a, ThreeVector<ValueA> v) {
- typedef typename BinaryOpTraits<ValueA,ValueB>::MulT ResultT;
- return ThreeVector<ResultT>(a*v.x(), a*v.y(), a*v.z());
+inline auto operator*(ValueB a, ThreeVector<ValueA> v)
+-> ThreeVector<decltype(a*v.x())>
+{
+ return {a*v.x(), a*v.y(), a*v.z()};
}
template <typename ValueA, typename ValueB>
-inline ThreeVector<typename BinaryOpTraits<ValueA,ValueB>::MulT>
-operator*(ThreeVector<ValueA> v, ValueB a) {
- return a*v;
+inline auto operator*(ThreeVector<ValueA> v, ValueB a)
+-> ThreeVector<decltype(v.x()*a)>
+{
+ return {v.x()*a, v.y()*a, v.z()*a};
}
//@}
/// Vector dot product.
template <typename ValueA, typename ValueB>
-inline typename BinaryOpTraits<ValueA,ValueB>::MulT
-operator*(const ThreeVector<ValueA> & a,
- const ThreeVector<ValueB> & b)
+inline auto operator*(const ThreeVector<ValueA> & a,
+ const ThreeVector<ValueB> & b)
+-> decltype(a.x()*b.x())
{
return a.dot(b);
}
/// A parallel vector with unit length.
template <typename Value>
ThreeVector<double> unitVector(const ThreeVector<Value> & v) {
return v.unit();
}
/** Output a ThreeVector with units to a stream. */
template <typename OStream, typename UT, typename Value>
void ounitstream(OStream & os, const ThreeVector<Value> & p, UT & u) {
os << ounit(p.x(), u) << ounit(p.y(), u) << ounit(p.z(), u);
}
/** Input a ThreeVector with units from a stream. */
template <typename IStream, typename UT, typename Value>
void iunitstream(IStream & is, ThreeVector<Value> & p, UT & u) {
Value x, y, z;
is >> iunit(x, u) >> iunit(y, u) >> iunit(z, u);
p = ThreeVector<Value>(x, y, z);
}
}
#endif /* ThePEG_ThreeVector_H */
diff --git a/Vectors/Transverse.h b/Vectors/Transverse.h
--- a/Vectors/Transverse.h
+++ b/Vectors/Transverse.h
@@ -1,262 +1,260 @@
// -*- C++ -*-
//
// Transverse.h is a part of ThePEG - Toolkit for HEP Event Generation
// Copyright (C) 1999-2017 Leif Lonnblad
//
// ThePEG is licenced under version 3 of the GPL, see COPYING for details.
// Please respect the MCnet academic guidelines, see GUIDELINES for details.
//
#ifndef ThePEG_Transverse_H
#define ThePEG_Transverse_H
// This is the declaration of the Transverse class.
#include "ThePEG/Config/ThePEG.h"
#include "ThePEG/Vectors/Lorentz5Vector.h"
#include "Transverse.fh"
namespace ThePEG {
/**
* Transverse represents the transverse components of a
* LorentzVector. It inherits from
* <code>std::pair<Value,Value></code> and can be used
* anywhere such a pair is called for. It can also be created directly
* from a <code>ThreeVector</code>, <code>LorentzVector</code> and
* <code>Lorentz5Momentum</code>.
*
* @see Lorentz5Vector
*/
template <typename Value>
class Transverse: public pair<Value,Value> {
public:
/** Template argument typedef. */
- typedef typename BinaryOpTraits<Value,Value>::MulT Value2;
+ using Value2 = decltype(sqr(std::declval<Value>()));
+
/** Template argument typedef. */
- typedef pair<Value,Value> BasePair;
+ using BasePair = pair<Value,Value>;
public:
/** @name Constructors. */
//@{
/**
* Default constructor.
*/
Transverse() : BasePair(Value(), Value()) {}
/**
* Constructor from underlying representation.
*/
Transverse(const BasePair & p) : BasePair(p) {}
/**
* Constructor from x and y components.
*/
Transverse(Value x, Value y) : BasePair(x, y) {}
/**
* Constructor taking the transverse parts of a ThreeVector.
*/
Transverse(const ThreeVector<Value> & p) : BasePair(p.x(), p.y()) {}
/**
* Constructor taking the transverse parts of a LorentzVector.
*/
Transverse(const LorentzVector<Value> & p) : BasePair(p.x(), p.y()) {}
/**
* Constructor taking the transverse parts of a Lorentz5Vector.
*/
Transverse(const Lorentz5Vector<Value> & p) : BasePair(p.x(), p.y()) {}
//@}
/** @name Assignment operators. */
//@{
/**
* Assignment from underlying representation.
*/
const Transverse & operator=(const BasePair & p) {
BasePair::operator=(p);
return *this;
}
/**
* Assignment taking the transverse parts of a ThreeVector.
*/
const Transverse & operator=(const ThreeVector<Value> & p) {
BasePair::operator=(BasePair(p.x(), p.y()));
return *this;
}
/**
* Assignment taking the transverse parts of a LorentzVector.
*/
const Transverse & operator=(const LorentzVector<Value> & p) {
BasePair::operator=(BasePair(p.x(), p.y()));
return *this;
}
/**
* Assignment taking the transverse parts of a Lorentz5Vector.
*/
const Transverse & operator=(const Lorentz5Vector<Value> & p) {
BasePair::operator=(BasePair(p.x(), p.y()));
return *this;
}
//@}
/** @name Arithmetric operations */
//@{
/**
* Unary minus.
*/
Transverse operator-() const { return Transverse(-x(), -y()); }
/**
* Binary minus.
*/
Transverse operator-(const Transverse & pt) const {
return Transverse(x() - pt.x(), y() - pt.y());
}
/**
* Assign-subtract.
*/
Transverse & operator-=(const Transverse & pt) {
BasePair::first -= pt.x();
BasePair::second -= pt.y();
return *this;
}
/**
* Addition.
*/
Transverse operator+(const Transverse & pt) const {
return Transverse(x() + pt.x(), y() + pt.y());
}
/**
* Assign-add.
*/
Transverse & operator+=(const Transverse & pt) {
BasePair::first += pt.x();
BasePair::second += pt.y();
return *this;
}
/**
* Multiply-assign with a scalar.
*/
inline Transverse & operator*=(double a) {
BasePair::first *= a;
BasePair::second *= a;
return *this;
}
/**
* Divide-assign with a scalar.
*/
inline Transverse & operator/=(double a) {
BasePair::first /= a;
BasePair::second /= a;
return *this;
}
//@}
/** @name Access coordinates. */
//@{
/**
* The x-component.
*/
Value x() const { return BasePair::first; }
/**
* The y-component.
*/
Value y() const { return BasePair::second; }
/**
* The magnitude squared.
*/
Value2 pt2() const { return sqr(x()) + sqr(y()); }
/**
* The magnitude.
*/
Value pt() const { return sqrt(pt2()); }
/**
* The azimuth angle.
*/
double phi() const { return atan2(y(), x()); }
//@}
};
/** Output a Transverse with units to a stream. */
template <typename OStream, typename T, typename UT>
void ounitstream(OStream & os, const Transverse<T> & p, UT & u) {
os << ounit(p.x(), u) << ounit(p.y(), u);
}
/** Input a Transverse with units from a stream. */
template <typename IStream, typename T, typename UT>
void iunitstream(IStream & is, Transverse<T> & p, UT & u) {
T x, y;
is >> iunit(x, u) >> iunit(y, u);
p = Transverse<T>(x, y);
}
/** Multiply a Transverse with a number. */
template <typename Value>
inline Transverse<Value>
operator*(Transverse<Value> a, double b) {
return a *= b;
}
/** Multiply a number with a Transverse. */
template <typename Value>
inline Transverse<Value>
operator*(double b, Transverse<Value> a) {
return a *= b;
}
/** Multiply a (unitful) number with a Transverse. */
template <typename ValueA, typename ValueB>
-inline
-Transverse<typename BinaryOpTraits<ValueA,ValueB>::MulT>
-operator*(ValueB a, const Transverse<ValueA> & v) {
- typedef typename BinaryOpTraits<ValueB,ValueA>::MulT ResultT;
- return Transverse<ResultT>(a*v.x(), a*v.y());
+inline auto operator*(ValueB a, const Transverse<ValueA> & v)
+-> Transverse<decltype(a*v.x())>
+{
+ return {a*v.x(), a*v.y()};
}
/** Multiply a Transverse with a (unitful) number. */
template <typename ValueA, typename ValueB>
-inline
-Transverse<typename BinaryOpTraits<ValueA,ValueB>::MulT>
-operator*(const Transverse<ValueA> & v, ValueB a) {
- typedef typename BinaryOpTraits<ValueB,ValueA>::MulT ResultT;
- return Transverse<ResultT>(a*v.x(), a*v.y());
+inline auto operator*(const Transverse<ValueA> & v, ValueB a)
+-> Transverse<decltype(a*v.x())>
+{
+ return {a*v.x(), a*v.y()};
}
/** Divide a Transverse by a number. */
template <typename Value>
inline Transverse<double>
operator/(const Transverse<Value> & v, Value a) {
- return Transverse<double>(v.x()/a, v.y()/a);
+ return {v.x()/a, v.y()/a};
}
/** Divide a Transverse by a (unitful) number. */
template <typename ValueA, typename ValueB>
-inline
-Transverse<typename BinaryOpTraits<ValueA,ValueB>::DivT>
-operator/(const Transverse<ValueA> & v, ValueB b) {
- typedef typename BinaryOpTraits<ValueA,ValueB>::DivT ResultT;
- return Transverse<ResultT>(v.x()/b, v.y()/b);
+inline auto operator/(const Transverse<ValueA> & v, ValueB b)
+-> Transverse<decltype(v.x()/b)>
+{
+ return {v.x()/b, v.y()/b};
}
}
#endif /* ThePEG_Transverse_H */
File Metadata
Details
Attached
Mime Type
text/x-diff
Expires
Sat, Dec 21, 5:02 PM (19 h, 10 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
4023561
Default Alt Text
(177 KB)
Attached To
rTHEPEGHG thepeghg
Event Timeline
Log In to Comment