File indexing completed on 2026-09-24 09:08:22
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022 #ifndef __FASTJET_CONTRIB_EEHELPERS_HH__
0023 #define __FASTJET_CONTRIB_EEHELPERS_HH__
0024
0025 #include "fastjet/PseudoJet.hh"
0026 #include <array>
0027 #include <limits>
0028
0029 FASTJET_BEGIN_NAMESPACE
0030
0031 namespace contrib{
0032 namespace lund_plane {
0033
0034
0035
0036
0037
0038 inline PseudoJet cross_product(const PseudoJet & p1, const PseudoJet & p2, bool lightlike=false) {
0039 double px = p1.py() * p2.pz() - p2.py() * p1.pz();
0040 double py = p1.pz() * p2.px() - p2.pz() * p1.px();
0041 double pz = p1.px() * p2.py() - p2.px() * p1.py();
0042
0043 double E;
0044 if (lightlike) {
0045 E = sqrt(px*px + py*py + pz*pz);
0046 } else {
0047 E = 0.0;
0048 }
0049 return PseudoJet(px, py, pz, E);
0050 }
0051
0052
0053 inline const double map_to_pi(const double &phi) {
0054 if (phi < -M_PI) return phi + 2 * M_PI;
0055 else if (phi > M_PI) return phi - 2 * M_PI;
0056 else return phi;
0057 }
0058
0059 inline double dot_product_3d(const PseudoJet & a, const PseudoJet & b) {
0060 return a.px()*b.px() + a.py()*b.py() + a.pz()*b.pz();
0061 }
0062
0063
0064 inline double one_minus_costheta(const PseudoJet & p1, const PseudoJet & p2) {
0065
0066 if (p1.m2() == 0 && p2.m2() == 0) {
0067
0068
0069 return dot_product(p1,p2) / (p1.E() * p2.E());
0070 } else {
0071 double p1mod = p1.modp();
0072 double p2mod = p2.modp();
0073 double p1p2mod = p1mod*p2mod;
0074 double dot = dot_product_3d(p1,p2);
0075
0076 if (dot > (1-std::numeric_limits<double>::epsilon()) * p1p2mod) {
0077 PseudoJet cross_result = cross_product(p1, p2, false);
0078
0079
0080
0081 return -cross_result.m2()/(p1p2mod * (p1p2mod+dot));
0082 }
0083
0084 return 1.0 - dot/p1p2mod;
0085
0086 }
0087 }
0088
0089
0090
0091
0092
0093
0094
0095
0096 inline double signed_angle_between_planes(const PseudoJet& n1,
0097 const PseudoJet& n2, const PseudoJet& n) {
0098
0099
0100 assert(fabs(n1.modp()-1) < sqrt(std::numeric_limits<double>::epsilon()) && fabs(n2.modp()-1) < sqrt(std::numeric_limits<double>::epsilon()));
0101
0102 double omcost = one_minus_costheta(n1,n2);
0103 double theta;
0104
0105
0106 if(fabs(omcost-2) < sqrt(std::numeric_limits<double>::epsilon())) {
0107 theta = M_PI;
0108 } else if (omcost > sqrt(std::numeric_limits<double>::epsilon())) {
0109 double cos_theta = 1.0 - omcost;
0110 theta = acos(cos_theta);
0111 } else {
0112
0113 theta = sqrt(2. * omcost);
0114 }
0115
0116 PseudoJet cp = cross_product(n1,n2);
0117 double sign = dot_product_3d(cp,n);
0118
0119 if (sign > 0) return theta;
0120 else return -theta;
0121 }
0122
0123 class Matrix3 {
0124 public:
0125
0126 Matrix3() : matrix_({{{{0,0,0}}, {{0,0,0}}, {{0,0,0}}}}) {}
0127
0128
0129 Matrix3(double unit) : matrix_({{{{unit,0,0}}, {{0,unit,0}}, {{0,0,unit}}}}) {}
0130
0131
0132 Matrix3(const std::array<std::array<double,3>,3> & mat) : matrix_(mat) {}
0133
0134
0135 inline double operator()(int i, int j) const {
0136 return matrix_[i][j];
0137 }
0138
0139
0140
0141 static Matrix3 azimuthal_rotation(double phi) {
0142 double cos_phi = cos(phi);
0143 double sin_phi = sin(phi);
0144 Matrix3 phi_rot( {{ {{cos_phi, sin_phi, 0}},
0145 {{-sin_phi, cos_phi, 0}},
0146 {{0,0,1}}}});
0147 return phi_rot;
0148 }
0149
0150
0151
0152 static Matrix3 polar_rotation(double theta) {
0153 double cos_theta = cos(theta);
0154 double sin_theta = sin(theta);
0155 Matrix3 theta_rot( {{ {{cos_theta, 0, sin_theta}},
0156 {{0,1,0}},
0157 {{-sin_theta, 0, cos_theta}}}});
0158 return theta_rot;
0159 }
0160
0161
0162
0163
0164
0165
0166
0167
0168 template<class T>
0169 static Matrix3 from_direction(const T & p, bool skip_pre_rotation = false) {
0170 double pt = p.pt();
0171 double modp = p.modp();
0172 double cos_theta = p.pz() / modp;
0173 double sin_theta = pt / modp;
0174 double cos_phi, sin_phi;
0175 if (pt > 0.0) {
0176 cos_phi = p.px()/pt;
0177 sin_phi = p.py()/pt;
0178 } else {
0179 cos_phi = 1.0;
0180 sin_phi = 0.0;
0181 }
0182
0183 Matrix3 phi_rot({{ {{ cos_phi,-sin_phi, 0 }},
0184 {{ sin_phi, cos_phi, 0 }},
0185 {{ 0, 0, 1 }} }});
0186 Matrix3 theta_rot( {{ {{ cos_theta, 0, sin_theta }},
0187 {{ 0, 1, 0 }},
0188 {{-sin_theta, 0, cos_theta }} }});
0189
0190
0191
0192
0193 if (skip_pre_rotation) {
0194 return phi_rot * theta_rot;
0195 } else {
0196 return phi_rot * (theta_rot * phi_rot.transpose());
0197 }
0198 }
0199
0200 template<class T>
0201 static Matrix3 from_direction_no_pre_rotn(const T & p) {
0202 return from_direction(p,true);
0203 }
0204
0205
0206
0207
0208 Matrix3 transpose() const {
0209
0210
0211
0212 Matrix3 result = *this;
0213 std::swap(result.matrix_[0][1],result.matrix_[1][0]);
0214 std::swap(result.matrix_[0][2],result.matrix_[2][0]);
0215 std::swap(result.matrix_[1][2],result.matrix_[2][1]);
0216 return result;
0217 }
0218
0219
0220 Matrix3 operator*(const Matrix3 & other) const {
0221 Matrix3 result;
0222
0223 for (int i = 0; i < 3; i++) {
0224 for (int j = 0; j < 3; j++) {
0225 for (int k = 0; k < 3; k++) {
0226 result.matrix_[i][j] += this->matrix_[i][k] * other.matrix_[k][j];
0227 }
0228 }
0229 }
0230 return result;
0231 }
0232
0233 friend std::ostream & operator<<(std::ostream & ostr, const Matrix3 & mat);
0234 private:
0235 std::array<std::array<double,3>,3> matrix_;
0236 };
0237
0238 inline std::ostream & operator<<(std::ostream & ostr, const Matrix3 & mat) {
0239 ostr << mat.matrix_[0][0] << " " << mat.matrix_[0][1] << " " << mat.matrix_[0][2] << std::endl;
0240 ostr << mat.matrix_[1][0] << " " << mat.matrix_[1][1] << " " << mat.matrix_[1][2] << std::endl;
0241 ostr << mat.matrix_[2][0] << " " << mat.matrix_[2][1] << " " << mat.matrix_[2][2] << std::endl;
0242 return ostr;
0243 }
0244
0245
0246
0247 inline PseudoJet operator*(const Matrix3 & mat, const PseudoJet & p) {
0248
0249 std::array<double,3> res3{{0,0,0}};
0250 for (unsigned i = 0; i < 3; i++) {
0251 for (unsigned j = 0; j < 3; j++) {
0252 res3[i] += mat(i,j) * p[j];
0253 }
0254 }
0255
0256
0257
0258 PseudoJet result(p);
0259
0260 result.reset_momentum(res3[0], res3[1], res3[2], p[3]);
0261 return result;
0262 }
0263
0264 }
0265 }
0266
0267 FASTJET_END_NAMESPACE
0268
0269 #endif
0270