CMS 3D CMS Logo

ThirdHitPredictionFromCircle.cc
Go to the documentation of this file.
1 #include <cmath>
4 
7 
10 
11 #include <iostream>
12 #include <algorithm>
13 
16 
17 // there are tons of safety checks.
18 // Try to move all of the out the regular control flow using gcc magic
20 namespace {
21  inline float f_atan2f(float y, float x) { return unsafe_atan2f<7>(y, x); }
22  template <typename V>
23  inline float f_phi(V v) {
24  return f_atan2f(v.y(), v.x());
25  }
26 } // namespace
27 
28 namespace {
29  template <class T>
30  inline T sqr(T t) {
31  return t * t;
32  }
33  template <class T>
34  inline T sgn(T t) {
35  return std::signbit(t) ? -T(1.) : T(1.);
36  }
37  template <class T>
38  inline T clamped_acos(T x) {
39  x = std::min(T(1.), std::max(-T(1.), x));
40  return unsafe_acos<5>(x);
41  }
42 
43  template <class T>
44  inline T clamped_sqrt(T t) {
45  return std::sqrt(std::max(T(0), t));
46  }
47 } // namespace
48 
50  const GlobalPoint &P2,
51  float tolerance)
52  : p1(P1.x(), P1.y()), theTolerance(tolerance) {
53  Vector2D p2(P2.x(), P2.y());
54  Vector2D diff = 0.5 * (p2 - p1);
55  delta2 = diff.mag2();
57  axis = Vector2D(-diff.y(), diff.x()) / delta;
58  center = p1 + diff;
59 }
60 
62  float phi;
63  if (UNLIKELY(std::abs(curvature) < float(1.0e-5))) {
64  float cos = (center * axis) / radius;
65  phi = axis.phi() - clamped_acos(cos);
66  } else {
67  float sign = sgn(curvature);
68  float radius2 = sqr(1.0f / curvature);
69  float orthog = clamped_sqrt(radius2 - delta2);
71  float rc2 = lcenter.mag2();
72  float r2 = sqr(radius);
73  float cos = (rc2 + r2 - radius2) / std::sqrt(4.f * rc2 * r2);
74  phi = f_phi(lcenter) + sign * clamped_acos(cos);
75  }
76  return phi; // not normalized
77 }
78 
80  if (UNLIKELY(std::abs(curvature) < float(1.0e-5))) {
81  float sin = (center * axis) / radius;
82  return sin / clamped_sqrt(1 - sqr(sin));
83  } else {
84  float radius2 = sqr(1.0f / curvature);
85  float orthog = clamped_sqrt(radius2 - delta2);
87 
88  float cos = (radius2 + sqr(radius) - lcenter.mag2()) * curvature / (2 * radius);
89  return -cos / clamped_sqrt(1.f - sqr(cos));
90  }
91 }
92 
94  float phi1 = normalizedPhi(phi(curvature.second, radius));
95  float phi2 = proxim(phi(curvature.first, radius), phi1);
96  if (phi2 < phi1)
97  std::swap(phi2, phi1);
98 
99  return Range(phi1 * radius - theTolerance, phi2 * radius + theTolerance);
100 }
101 
103  // this is a mess. Use a CAS and lots of drawings to verify...
104 
106  double transverseIP2 = sqr(transverseIP);
107  double tip = axis * center;
108  double tip2 = sqr(tip);
109  double lip = axis.x() * center.y() - axis.y() * center.x();
110  double lip2 = sqr(lip);
111 
112  double origin = std::sqrt(tip2 + lip2);
113  double tmp1 = lip2 + tip2 - transverseIP2;
114  double tmp2 = 2. * (tip - transverseIP) * (tip + transverseIP);
115  double tmp3 = 2. * delta * origin;
116  double tmp4 = tmp1 + delta2;
117  double tmp5 = 2. * delta * lip;
118 
119  // I am probably being overly careful here with border cases
120  // but you never know what crap you might get fed
121  // VI fixed for finiteMath
122 
123  double u1 = 0, u2 = 0;
124  constexpr double SMALL = 1.0e-23;
125  constexpr double LARGE = 1.0e23;
126 
127  if (UNLIKELY(tmp4 - tmp5 < 1.0e-15)) {
128  u1 = -SMALL;
129  u2 = +SMALL;
130  } else {
131  if (UNLIKELY(std::abs(tmp2) < 1.0e-15)) {
132  // the denominator is zero
133  // this means that one of the tracks will be straight
134  // and the other can be computed from the limit of the equation
135  double tmp = lip2 - delta2;
136  u1 = LARGE;
137  u2 = (sqr(0.5 * tmp) - delta2 * tip2) / (tmp * tip);
138  if (tip < 0)
139  std::swap(u1, u2);
140  } else {
141  double tmp6 = (tmp4 - tmp5) * (tmp4 + tmp5);
142  if (UNLIKELY(tmp6 < 1.0e-15)) {
143  u1 = -SMALL;
144  u2 = +SMALL;
145  } else {
146  double tmp7 = tmp6 > 0 ? (transverseIP * std::sqrt(tmp6) / tmp2) : 0.;
147  double tmp8 = tip * (tmp1 - delta2) / tmp2;
148  // the two quadratic solutions
149  u1 = tmp8 + tmp7;
150  u2 = tmp8 - tmp7;
151  }
152  }
153 
154  if (tmp4 <= std::abs(tmp3)) {
155  if ((tmp3 < 0) == (tip < 0))
156  u2 = +SMALL;
157  else
158  u1 = -SMALL;
159  }
160  }
161 
162  return Range(sgn(u1) / std::sqrt(sqr(u1) + delta2), sgn(u2) / std::sqrt(sqr(u2) + delta2));
163 }
164 
166  Vector2D del = p2 - p1;
167  Vector2D axis2 = Vector2D(-del.y(), del.x()) / del.mag();
168  Vector2D diff = p1 + 0.5f * del - center;
169  Scalar a = diff.y() * axis2.x() - diff.x() * axis2.y();
170  Scalar b = axis.y() * axis2.x() - axis.x() * axis2.y();
171  return b / a;
172 }
173 
175  double invDist = invCenterOnAxis(p2);
176  double invDist2 = sqr(invDist);
177  double curv = std::sqrt(invDist2 / (1. + invDist2 * delta2));
178  return sgn(invDist) * curv;
179 }
180 
182  double invDist = invCenterOnAxis(p2);
183  if (UNLIKELY(std::abs(invDist) < 1.0e-5))
184  return std::abs(p2 * axis);
185  else {
186  double dist = 1.0 / invDist;
187  double radius = std::sqrt(sqr(dist) + delta2);
188  return std::abs((center + axis * dist).mag() - radius);
189  }
190 }
191 
192 //------------------------------------------------------------------------------
193 
194 namespace {
195  // 2asin(cd)/c
196  inline float arc(float c, float d) {
197  float z = c * d;
198  z *= z;
199  float x = 2.f * d;
200 
201  if (z > 0.5f)
202  return std::min(1.f, 2.f * unsafe_asin<5>(c * d) / c);
203 
204  return x * approx_asin_P<7>(z);
205  }
206 } // namespace
207 
209  double iz1,
210  double z2,
211  double curv)
212  : circle(icircle), curvature(curv), radius(1. / curv), z1(iz1) {
213  Scalar orthog = sgn(curv) * clamped_sqrt(radius * radius - circle->delta2);
214  center = circle->center + orthog * circle->axis;
215 
216  Scalar absCurv = std::abs(curv);
217  seg = circle->delta;
218  seg = arc(absCurv, seg);
219  dzdu = (z2 - z1) / seg;
220 }
221 
223  double z1,
224  double z2,
225  double z3) {
226  constexpr double maxAngle = M_PI;
227  double halfAngle = (0.5 * maxAngle) * (z2 - z1) / (z3 - z1);
228  if (UNLIKELY(halfAngle <= 0.0))
229  return 0.0;
230 
231  return std::sin(halfAngle) / circle->delta;
232 }
233 
235  if (UNLIKELY(std::abs(curvature) < 1.0e-5)) {
236  Scalar tip = circle->axis * circle->p1;
237  Scalar lip = circle->axis.y() * circle->p1.x() - circle->axis.x() * circle->p1.y();
238  return z1 + (std::sqrt(sqr(r) - sqr(tip)) - lip) * dzdu;
239  }
240 
241  Scalar radius2 = sqr(radius);
242 
243  Scalar b2 = center.mag2();
244  Scalar b = std::sqrt(b2);
245 
246  Scalar cos1 = 0.5 * curvature * (radius2 + b2 - sqr(r)) / b;
247  Scalar cos2 = 0.5 * curvature * (radius2 + b2 - circle->p1.mag2()) / b;
248 
249  Scalar phi1 = clamped_acos(cos1);
250  Scalar phi2 = clamped_acos(cos2);
251 
252  // more plausbility checks needed...
253  // the two circles can have two possible intersections
254  Scalar u1 = std::abs((phi1 - phi2) * radius);
255  Scalar u2 = std::abs((phi1 + phi2) * radius);
256 
257  return z1 + ((u1 >= seg && u1 < u2) ? u1 : u2) * dzdu;
258 }
259 
260 #include <vdt/sincos.h>
261 
263  if (UNLIKELY(std::abs(dzdu) < 1.0e-5))
264  return 99999.0;
265 
266  if (UNLIKELY(std::abs(curvature) < 1.0e-5)) {
267  Scalar tip = circle->axis * circle->p1;
268  Scalar lip = circle->axis.y() * circle->p1.x() - circle->axis.x() * circle->p1.y();
269  return std::sqrt(sqr(tip) + sqr(lip + (z - z1) / dzdu));
270  }
271 
272  // we won't go below that (see comment below)
273  Scalar minR2 = (2. * circle->center - circle->p1).mag2();
274 
275  float phi = curvature * (z - z1) / dzdu;
276 
277  if (UNLIKELY(std::abs(phi) > 2. * M_PI)) {
278  // with a helix we can get problems here - this is used to get the limits
279  // however, if phi gets large, we get into the regions where we loop back
280  // to smaller r's. The question is - do we care about these tracks?
281  // The answer is probably no: Too much pain, and the rest of the
282  // tracking won't handle looping tracks anyway.
283  // So, what we do here is to return nothing smaller than the radius
284  // than any of the two hits, i.e. the second hit, which is presumably
285  // outside of the 1st hit.
286 
287  return std::sqrt(minR2);
288  }
289 
290  Vector2D rel = circle->p1 - center;
291 
292  float c;
293  float s;
294  vdt::fast_sincosf(phi, s, c);
295 
296  Vector2D p(center.x() + c * rel.x() - s * rel.y(), center.y() + s * rel.x() + c * rel.y());
297 
298  return std::sqrt(std::max(minR2, p.mag2()));
299 }
constexpr float approx_asin_P< 7 >(float z)
Definition: approx_asin.h:20
T mag2() const
The vector magnitude squared. Equivalent to vec.dot(vec)
const double tolerance
float sgn(float val)
Definition: FWPFMaths.cc:9
constexpr T normalizedPhi(T phi)
Definition: normalizedPhi.h:8
Sin< T >::type sin(const T &t)
Definition: Sin.h:22
T y() const
Cartesian y coordinate.
Scalar invCenterOnAxis(const Vector2D &thirdPoint) const
int sqr(const T &t)
float float float z
T curvature(T InversePt, const MagneticField &field)
constexpr T proxim(T b, T a)
Definition: normalizedPhi.h:14
double transverseIP(const Vector2D &thirdPoint) const
T x() const
Definition: PV3DBase.h:59
T y() const
Definition: PV3DBase.h:60
Geom::Phi< T > phi() const
uint32_t T const *__restrict__ uint32_t const *__restrict__ int32_t int Histo::index_type cudaStream_t V
void swap(edm::DataFrameContainer &lhs, edm::DataFrameContainer &rhs)
T sqrt(T t)
Definition: SSEVec.h:19
Cos< T >::type cos(const T &t)
Definition: Cos.h:22
Abs< T >::type abs(const T &t)
Definition: Abs.h:22
ThirdHitPredictionFromCircle::Scalar Scalar
double f[11][100]
d
Definition: ztail.py:151
#define M_PI
ThirdHitPredictionFromCircle(const GlobalPoint &P1, const GlobalPoint &P2, float tolerance)
static double maxCurvature(const ThirdHitPredictionFromCircle *circle, double z1, double z2, double z3)
T mag() const
The vector magnitude. Equivalent to sqrt(vec.mag2())
T mag2() const
The vector magnitude squared. Equivalent to vec.dot(vec)
double b
Definition: hdecay.h:118
T mag() const
The vector magnitude. Equivalent to sqrt(vec.mag2())
double a
Definition: hdecay.h:119
float angle(float curvature, float radius) const
const ThirdHitPredictionFromCircle * circle
float x
#define UNLIKELY(x)
Definition: Likely.h:21
static constexpr float b2
tmp
align.sh
Definition: createJobs.py:716
long double T
float phi(float curvature, float radius) const
Range operator()(Range curvature, float radius) const
T x() const
Cartesian x coordinate.
Range curvature(double transverseIP) const