Himalaya
PV.cpp
Go to the documentation of this file.
1 // ====================================================================
2 // This file is part of Himalaya.
3 //
4 // Himalaya is licenced under the GNU General Public License (GNU GPL)
5 // version 3.
6 // ====================================================================
7 
8 #include "himalaya/mh2_fo/PV.hpp"
10 
11 #include <cmath>
12 #include <complex>
13 
14 /**
15  * @file PV.cpp
16  *
17  * @brief Implementation of real Passarino-Veltman loop functions with
18  * squared arguments.
19  */
20 
21 namespace himalaya {
22 namespace mh2_fo {
23 namespace {
24 
25 constexpr double EPSTOL = 1.0e-15; ///< underflow accuracy
26 
27 
28 constexpr double sign(double x) noexcept
29 {
30  return x >= 0.0 ? 1.0 : -1.0;
31 }
32 
33 
34 /// fast implementation of complex logarithm
35 template <class T>
36 std::complex<T> fast_log(const std::complex<T>& z) noexcept
37 {
38  const T rz = std::real(z);
39  const T iz = std::imag(z);
40 
41  return std::complex<T>(0.5*std::log(rz*rz + iz*iz), std::atan2(iz, rz));
42 }
43 
44 
45 double fB(const std::complex<double>& x) noexcept
46 {
47  const double re = std::real(x);
48  const double im = std::imag(x);
49 
50  if ((std::abs(re) == 0.0 || std::abs(re) == 1.0) && im == 0.0) {
51  return -1.0;
52  }
53 
54  if (std::abs(re - 1.0) < 1e-3) {
55  const auto d = x - 1.0;
56  const auto logd = fast_log(d);
57  return std::real(-1.0 + d*(1.0 - logd + d*(0.5 - d/6.)));
58  }
59 
60  if (std::abs(re) > 1e3) {
61  return std::real(-0.5/x - 1.0/(6.0*x*x) + fast_log(-x));
62  }
63 
64  return std::real(-1.0 + fast_log(1.0 - x) - x*fast_log(1.0 - 1.0/x));
65 }
66 
67 
68 } // anonymous namespace
69 
70 
71 double a0(double m2, double q2) noexcept
72 {
73  m2 = std::abs(m2);
74 
75  if (m2 < EPSTOL)
76  return 0;
77 
78  return m2 * (1 - std::log(m2 / q2));
79 }
80 
81 
82 /**
83  * Re(B0(s,x,x,q2)), Eq.(2.4) from [hep-ph/0701051]
84  *
85  * @param p2 squared momentum
86  * @param m2 squared mass
87  * @param q2 squared renormalization scale
88  *
89  * @return Re(B0(s,x,x,q2))
90  */
91 double b0xx(double p2, double m2, double q2) noexcept
92 {
93  p2 = std::abs(p2);
94  m2 = std::abs(m2);
95  q2 = std::abs(q2);
96 
97  if (p2 < EPSTOL * q2 && m2 < EPSTOL * q2) {
98  return 0; // IR divergence
99  } else if (p2 < EPSTOL) {
100  return -std::log(m2 / q2);
101  } else if (p2 <= 4 * m2) {
102  return 2 - std::log(m2 / q2) -
103  2 * std::sqrt(4 * m2 / p2 - 1) *
104  std::asin(std::sqrt(p2 / (4 * m2)));
105  } else if (p2 <= 5e2 * m2) {
106  const double sq = std::sqrt(1 - 4 * m2 / p2);
107  return 2 - std::log(m2 / q2) +
108  sq * std::log(p2 * (1 - sq) / (2 * m2) - 1);
109  } else if (p2*EPSTOL < m2) {
110  const double d = m2 / p2;
111  const double logd = std::log(d);
112  return 2 - std::log(p2 / q2)
113  + d * (2 * (1 - logd)
114  + d * (-1 - 2 * logd
115  + d * (-10./3 - 4 * logd
116  + d * (-59./6 - 10 * logd
117  + d * (-449./15 - 28 * logd
118  + d * (-1417./15 - 84 * logd
119  + d * (-32254./105 - 264 * logd)))))));
120  } else {
121  return 2 - std::log(p2 / q2);
122  }
123 }
124 
125 
126 /**
127  * B0 function with squared arguments, from hep-ph/9606211.
128  * @note returns only the real part of B0
129  */
130 double b0(double p2, double m12, double m22, double q2) noexcept
131 {
132  p2 = std::abs(p2);
133  m12 = std::abs(m12);
134  m22 = std::abs(m22);
135  q2 = std::abs(q2);
136 
137  // protect against infrared divergence
138  if (p2 < EPSTOL * q2 && m12 < EPSTOL * q2 && m22 < EPSTOL * q2) {
139  return 0;
140  }
141 
142  if (m12 > m22) {
143  std::swap(m12, m22);
144  }
145 
146  if (m12*(1 + EPSTOL) > m22) {
147  return b0xx(p2, m12, q2);
148  }
149 
150  if (p2 <= 1e-11 * m12) {
151  if (m12 < EPSTOL * m22) {
152  return 1 - std::log(m22 / q2);
153  }
154 
155  return 1 - std::log(m22 / q2) + m12 * std::log(m22 / m12) / (m12 - m22);
156  }
157 
158  if (m12 < EPSTOL * EPSTOL * m22) {
159  const double del = std::hypot(m22 - p2, EPSTOL * m22);
160  return 2 - std::log(m22 / q2) + (m22 - p2) / p2 * std::log(del / p2);
161  }
162 
163  const double s = p2 - m22 + m12;
164  const std::complex<double> imin(m12, -EPSTOL * m12);
165  const std::complex<double> x = std::sqrt(pow2(s) - 4 * p2 * imin);
166  const std::complex<double> xp = (s + sign(s) * x) / (2 * p2);
167  const std::complex<double> xm = imin / (xp * p2);
168 
169  return -std::log(p2 / q2) - fB(xp) - fB(xm);
170 }
171 
172 /**
173  * Derivative of B0(p^2, m1^2, m2^2, Q^2) w.r.t. p^2, for p^2 = 0.
174  *
175  * @note Implemented only in the p^2 = 0 limit.
176  *
177  * @param m12 squared mass
178  * @param m22 squared mass
179  *
180  * @return derivative of B0 w.r.t. p^2 at p^2 = 0
181  */
182 double d1_b0(double m12, double m22) noexcept
183 {
184  m12 = std::abs(m12);
185  m22 = std::abs(m22);
186 
187  if ((m12 < 1e-14*m22) != (m22 < 1e-14*m12)) {
188  return (m12 - m22) * (m12 + m22) / (2 * pow3(m12 - m22));
189  } else if (m12 < EPSTOL && m22 < EPSTOL) {
190  return 0;
191  } else if (std::abs(m22 - m12) < 5e-2*m12) {
192  return 1 / (6 * m12) +
193  (m12 - m22) / (12 * pow2(m12)) +
194  pow2(m12 - m22) / (20 * pow3(m12)) +
195  pow3(m12 - m22) / (30 * pow4(m12)) +
196  pow4(m12 - m22) / (42 * pow5(m12)) +
197  pow5(m12 - m22) / (56 * pow6(m12));
198  }
199 
200  return ((m12 - m22) * (m12 + m22) + 2 * m12 * m22 * std::log(m22 / m12)) /
201  (2 * pow3(m12 - m22));
202 }
203 
204 } // namespace mh2_fo
205 } // namespace himalaya
Definition: H3.cpp:14
double b0xx(double p2, double m2, double q2) noexcept
B0(s,x,x,q2) Passarino-Veltman function.
Definition: PV.cpp:91
double d1_b0(double m12, double m22) noexcept
derivative of B0 Passarino-Veltman function w.r.t. p^2, for p^2 = 0
Definition: PV.cpp:182
Declaration of real Passarino-Veltman loop functions with squared arguments.
Complex< T > log(const Complex< T > &z_) noexcept
Definition: complex.hpp:45
double b0(double p2, double m12, double m22, double q2) noexcept
B0 Passarino-Veltman function.
Definition: PV.cpp:130
double a0(double m2, double q2) noexcept
A0 Passarino-Veltman function.
Definition: PV.cpp:71