File indexing completed on 2026-08-06 09:38:20
0001
0002
0003
0004
0005
0006
0007
0008
0009 #ifndef Physical_Qty_Complex_H
0010 #define Physical_Qty_Complex_H
0011 #include "PhysicalQty.h"
0012 #include "PhysicalQtyOps.h"
0013 #include <complex>
0014
0015
0016
0017
0018
0019 namespace std {
0020
0021
0022
0023
0024 template<>
0025 class complex<ThePEG::QtyDouble>
0026 {
0027 public:
0028
0029 constexpr complex(double r=0.0, double i=0.0)
0030 : rawValue_(r,i) {}
0031
0032
0033 constexpr complex(complex<double> C)
0034 : rawValue_(C) {}
0035
0036
0037
0038
0039
0040 constexpr complex<double> rawValue() const { return rawValue_; }
0041
0042
0043 constexpr double real() const { return rawValue_.real(); }
0044
0045
0046 constexpr double imag() const { return rawValue_.imag(); }
0047
0048
0049 constexpr operator complex<double>() const {
0050 return rawValue_;
0051 }
0052
0053
0054 complex<ThePEG::QtyDouble> &
0055 operator+=(const complex<ThePEG::QtyDouble> x) {
0056 rawValue_ += x.rawValue();
0057 return *this;
0058 }
0059
0060
0061 complex<ThePEG::QtyDouble> &
0062 operator-=(const complex<ThePEG::QtyDouble> x) {
0063 rawValue_ -= x.rawValue();
0064 return *this;
0065 }
0066
0067 private:
0068
0069 complex<double> rawValue_;
0070 };
0071 }
0072
0073
0074 namespace ThePEG {
0075
0076
0077
0078
0079 template<typename L1, typename E1, typename Q1,
0080 typename L2, typename E2, typename Q2>
0081 inline constexpr auto
0082 operator*(std::complex<Qty<L1,E1,Q1>> q1,
0083 std::complex<Qty<L2,E2,Q2>> q2)
0084 -> std::complex<decltype(q1.real()*q2.real())>
0085 {
0086 return {q1.real()*q2.real() - q1.imag()*q2.imag(),
0087 q1.real()*q2.imag() + q1.imag()*q2.real()};
0088 }
0089
0090
0091 template<typename L, typename E, typename Q>
0092 inline constexpr std::complex<typename Qty<L,E,Q>::Squared>
0093 operator*(std::complex<Qty<L,E,Q>> q1,
0094 std::complex<Qty<L,E,Q>> q2)
0095 {
0096 return {q1.real()*q2.real() - q1.imag()*q2.imag(),
0097 q1.real()*q2.imag() + q1.imag()*q2.real()};
0098 }
0099
0100
0101 inline constexpr std::complex<double>
0102 operator-(std::complex<double> q1, std::complex<QtyDouble> q2) {
0103 return {q1.real()-q2.real(), q1.imag()-q2.imag()};
0104 }
0105
0106
0107 inline constexpr std::complex<double>
0108 operator+(std::complex<double> q1, std::complex<QtyDouble> q2) {
0109 return {q1.real()+q2.real(), q1.imag()+q2.imag()};
0110 }
0111
0112
0113 template<typename L, typename E, typename Q>
0114 inline constexpr std::complex<Qty<L,E,Q>>
0115 operator*(std::complex<double> q1, std::complex<Qty<L,E,Q>> q2) {
0116 return {q1.real()*q2.real() - q1.imag()*q2.imag(),
0117 q1.real()*q2.imag() + q1.imag()*q2.real()};
0118 }
0119
0120
0121 template<typename L, typename E, typename Q>
0122 inline std::complex<typename Qty<L,E,Q>::Inverse>
0123 operator/(std::complex<double> q1, std::complex<Qty<L,E,Q>> q2) {
0124 auto tmp = q1*conj(q2);
0125 auto norm = (q2*conj(q2)).real();
0126 return {tmp.real()/norm, tmp.imag()/norm};
0127 }
0128
0129
0130 template<typename L, typename E, typename Q>
0131 inline constexpr std::complex<typename Qty<L,E,Q>::Inverse>
0132 operator/(std::complex<double> q1, Qty<L,E,Q> q2) {
0133 return {q1.real()/q2, q1.imag()/q2};
0134 }
0135
0136
0137 template<typename L, typename E, typename Q>
0138 inline std::complex<Qty<L,E,Q>>
0139 operator/(std::complex<Qty<L,E,Q>> q1, std::complex<double> q2) {
0140 auto tmp = q1*conj(q2);
0141 auto norm = (q2*conj(q2)).real();
0142 return {tmp.real()/norm, tmp.imag()/norm};
0143 }
0144
0145
0146 template<typename L, typename E, typename Q>
0147 inline std::complex<Qty<L,E,Q>>
0148 operator/(Qty<L,E,Q> q1, std::complex<double> q2) {
0149 auto tmp = q1*conj(q2);
0150 auto norm = (q2*conj(q2)).real();
0151 return {tmp.real()/norm, tmp.imag()/norm};
0152 }
0153
0154
0155 template<typename L, typename E, typename Q>
0156 inline std::complex<double>
0157 operator/(std::complex<Qty<L,E,Q>> q1,
0158 std::complex<Qty<L,E,Q>> q2) {
0159 auto tmp = q1*conj(q2);
0160 auto norm = (q2*conj(q2)).real();
0161 return {tmp.real()/norm, tmp.imag()/norm};
0162 }
0163
0164
0165 template<typename L, typename E, typename Q>
0166 inline std::complex<double>
0167 operator/(Qty<L,E,Q> q1, std::complex<Qty<L,E,Q>> q2) {
0168 auto tmp = q1*conj(q2);
0169 auto norm = (q2*conj(q2)).real();
0170 return {tmp.real()/norm, tmp.imag()/norm};
0171 }
0172
0173
0174 template<typename L, typename E, typename Q>
0175 inline constexpr std::complex<double>
0176 operator/(std::complex<Qty<L,E,Q>> q1, Qty<L,E,Q> q2) {
0177 return {q1.real()/q2, q1.imag()/q2};
0178 }
0179
0180
0181 template<typename L1, typename E1, typename Q1,
0182 typename L2, typename E2, typename Q2>
0183 inline auto
0184 operator/(std::complex<Qty<L1,E1,Q1>> q1,
0185 std::complex<Qty<L2,E2,Q2>> q2)
0186 -> std::complex<decltype(q1.real()/q2.real())>
0187 {
0188 auto tmp = q1*conj(q2);
0189 auto norm = (q2*conj(q2)).real();
0190 return {tmp.real()/norm, tmp.imag()/norm};
0191 }
0192
0193
0194 template<typename L1, typename E1, typename Q1,
0195 typename L2, typename E2, typename Q2>
0196 inline auto
0197 operator/(Qty<L1,E1,Q1> q1,
0198 std::complex<Qty<L2,E2,Q2>> q2)
0199 -> std::complex<decltype(q1/q2.real())>
0200 {
0201 auto tmp = q1*conj(q2);
0202 auto norm = (q2*conj(q2)).real();
0203 return {tmp.real()/norm, tmp.imag()/norm};
0204 }
0205
0206
0207 template<typename L1, typename E1, typename Q1,
0208 typename L2, typename E2, typename Q2>
0209 inline constexpr auto
0210 operator/(std::complex<Qty<L1,E1,Q1>> q1, Qty<L2,E2,Q2> q2)
0211 -> std::complex<decltype(q1.real()/q2)>
0212 {
0213 return {q1.real()/q2, q1.imag()/q2};
0214 }
0215
0216
0217
0218 template<typename L, typename E, typename Q>
0219 inline constexpr std::complex<Qty<L,E,Q>>
0220 operator*(std::complex<Qty<L,E,Q>> q1, std::complex<double> q2) {
0221 return q2 * q1;
0222 }
0223
0224
0225
0226 template<typename L1, typename E1, typename Q1,
0227 typename L2, typename E2, typename Q2>
0228 inline constexpr auto
0229 operator*(Qty<L1,E1,Q1> q1, std::complex<Qty<L2,E2,Q2>> q2)
0230 -> std::complex<decltype(q1*q2.real())>
0231 {
0232 return {q1*q2.real(), q1*q2.imag()};
0233 }
0234
0235
0236 template<typename L, typename E, typename Q>
0237 inline constexpr std::complex<typename Qty<L,E,Q>::Squared>
0238 operator*(Qty<L,E,Q> q1, std::complex<Qty<L,E,Q>> q2) {
0239 return {q1*q2.real(), q1*q2.imag()};
0240 }
0241
0242
0243 template<typename L, typename E, typename Q>
0244 inline constexpr std::complex<Qty<L,E,Q>>
0245 operator*(Qty<L,E,Q> q1, std::complex<double> q2) {
0246 return {q1*q2.real(), q1*q2.imag()};
0247 }
0248
0249
0250 template<typename L, typename E, typename Q>
0251 inline constexpr std::complex<Qty<L,E,Q>>
0252 operator*(std::complex<double> q1, Qty<L,E,Q> q2) {
0253 return q2 * q1;
0254 }
0255
0256
0257
0258 template<typename L1, typename E1, typename Q1,
0259 typename L2, typename E2, typename Q2>
0260 inline constexpr auto
0261 operator*(std::complex<Qty<L1,E1,Q1>> q1, Qty<L2,E2,Q2> q2)
0262 -> decltype(q2*q1)
0263 {
0264 return q2 * q1;
0265 }
0266
0267
0268 template<typename L, typename E, typename Q>
0269 inline constexpr std::complex<typename Qty<L,E,Q>::Squared>
0270 operator*(std::complex<Qty<L,E,Q>> q1, Qty<L,E,Q> q2) {
0271 return q2 * q1;
0272 }
0273
0274
0275 template<typename L, typename E, typename Q>
0276 inline constexpr std::complex<Qty<L,E,Q>> &
0277 operator*=(std::complex<Qty<L,E,Q>> & q1, double q2) {
0278 return (q1 = q1 * q2);
0279 }
0280
0281
0282 template<typename L, typename E, typename Q>
0283 inline constexpr std::complex<Qty<L,E,Q>> &
0284 operator/=(std::complex<Qty<L,E,Q>> & q1, double q2) {
0285 return (q1 = q1 / q2);
0286 }
0287
0288 }
0289
0290 #endif