CMS 3D CMS Logo

 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Pages
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
22  float f_atan2f(float y, float x) { return unsafe_atan2f<7>(y,x); }
23  template<typename V> inline float f_phi(V v) { return f_atan2f(v.y(),v.x());}
24 }
25 
26 
27 namespace {
28  template<class T> inline T sqr(T t) { return t * t; }
29  template<class T> inline T sgn(T t) { return std::signbit(t) ? -T(1.) : T(1.); }
30  template<class T> inline T clamped_acos(T x) {
31  x = std::min(T(1.),std::max(-T(1.),x));
32  return unsafe_acos<5>(x);
33  }
34 
35  template<class T> inline T clamped_sqrt(T t) { return std::sqrt(std::max(T(0),t)); }
36 }
37 
39  const GlobalPoint& P1, const GlobalPoint& P2, float tolerance)
40  : p1(P1.x(), P1.y()), theTolerance(tolerance)
41 {
42  Vector2D p2(P2.x(), P2.y());
43  Vector2D diff = 0.5 * (p2 - p1);
44  delta2 = diff.mag2();
46  axis = Vector2D(-diff.y(), diff.x()) / delta;
47  center = p1 + diff;
48 }
49 
51 {
52  float phi;
53  if (unlikely(std::abs(curvature) < float(1.0e-5))) {
54  float cos = (center * axis) / radius;
55  phi = axis.phi() - clamped_acos(cos);
56  } else {
57  float sign = sgn(curvature);
58  float radius2 = sqr(1.0f / curvature);
59  float orthog = clamped_sqrt(radius2 - delta2);
61  float rc2 = lcenter.mag2();
62  float r2 = sqr(radius);
63  float cos = (rc2 + r2 - radius2)/std::sqrt(4.f*rc2*r2);
64  phi = f_phi(lcenter) + sign * clamped_acos(cos);
65  }
66  return phi; // not normalized
67 }
68 
70 {
71  if (unlikely(std::abs(curvature) < float(1.0e-5))) {
72  float sin = (center * axis) / radius;
73  return sin / clamped_sqrt(1 - sqr(sin));
74  } else {
75  float radius2 = sqr(1.0f / curvature);
76  float orthog = clamped_sqrt(radius2 - delta2);
78 
79  float cos = (radius2 + sqr(radius) - lcenter.mag2()) *
80  curvature / (2 * radius);
81  return - cos / clamped_sqrt(1.f - sqr(cos));
82  }
83 }
84 
87 {
88  float phi1 = normalizedPhi(phi(curvature.second, radius));
89  float phi2 = proxim(phi(curvature.first, radius),phi1);
90  if(phi2 < phi1) std::swap(phi2,phi1);
91 
92  return Range(phi1 * radius - theTolerance, phi2 * radius + theTolerance);
93 }
94 
96 ThirdHitPredictionFromCircle::curvature(double transverseIP) const
97 {
98  // this is a mess. Use a CAS and lots of drawings to verify...
99 
100  transverseIP = std::abs(transverseIP);
101  double transverseIP2 = sqr(transverseIP);
102  double tip = axis * center;
103  double tip2 = sqr(tip);
104  double lip = axis.x() * center.y() - axis.y() * center.x();
105  double lip2 = sqr(lip);
106 
107  double origin = std::sqrt(tip2 + lip2);
108  double tmp1 = lip2 + tip2 - transverseIP2;
109  double tmp2 = 2. * (tip - transverseIP) * (tip + transverseIP);
110  double tmp3 = 2. * delta * origin;
111  double tmp4 = tmp1 + delta2;
112  double tmp5 = 2. * delta * lip;
113 
114  // I am probably being overly careful here with border cases
115  // but you never know what crap you might get fed
116  // VI fixed for finiteMath
117 
118  double u1=0, u2=0;
119  constexpr double SMALL = 1.0e-23;
120  constexpr double LARGE = 1.0e23;
121 
122  if (unlikely(tmp4 - tmp5 < 1.0e-15)) {
123  u1 = -SMALL;
124  u2 = +SMALL;
125  } else {
126  if (unlikely(std::abs(tmp2) < 1.0e-15)) {
127  // the denominator is zero
128  // this means that one of the tracks will be straight
129  // and the other can be computed from the limit of the equation
130  double tmp = lip2 - delta2;
131  u1 = LARGE;
132  u2 = (sqr(0.5 * tmp) - delta2 * tip2) / (tmp * tip);
133  if (tip < 0)
134  std::swap(u1, u2);
135  } else {
136  double tmp6 = (tmp4 - tmp5) * (tmp4 + tmp5);
137  if (unlikely(tmp6 < 1.0e-15)) {
138  u1 = -SMALL;
139  u2 = +SMALL;
140  } else {
141  double tmp7 = tmp6 > 0 ? (transverseIP * std::sqrt(tmp6) / tmp2) : 0.;
142  double tmp8 = tip * (tmp1 - delta2) / tmp2;
143  // the two quadratic solutions
144  u1 = tmp8 + tmp7;
145  u2 = tmp8 - tmp7;
146  }
147  }
148 
149  if (tmp4 <= std::abs(tmp3)) {
150  if ((tmp3 < 0) == (tip < 0))
151  u2 = +SMALL;
152  else
153  u1 = -SMALL;
154  }
155  }
156 
157  return Range(sgn(u1) / std::sqrt(sqr(u1) + delta2),
158  sgn(u2) / std::sqrt(sqr(u2) + delta2));
159 }
160 
163 {
164  Vector2D del = p2 - p1;
165  Vector2D axis2 = Vector2D(-del.y(), del.x()) / del.mag();
166  Vector2D diff = p1 + 0.5f * del - center;
167  Scalar a = diff.y() * axis2.x() - diff.x() * axis2.y();
168  Scalar b = axis.y() * axis2.x() - axis.x() * axis2.y();
169  return b / a;
170 }
171 
173 {
174  double invDist = invCenterOnAxis(p2);
175  double invDist2 = sqr(invDist);
176  double curv = std::sqrt(invDist2 / (1. + invDist2 * delta2));
177  return sgn(invDist) * curv;
178 }
179 
181 {
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 
195 namespace {
196  // 2asin(cd)/c
197  inline
198 float arc(float c, float d) {
199  float z = c*d; z*=z;
200  float x = 2.f*d;
201 
202  if (z>0.5f) return std::min(1.f,2.f*unsafe_asin<5>(c*d)/c);
203 
204  return x*approx_asin_P<7>(z);
205 
206  }
207 }
208 
209 
211  const ThirdHitPredictionFromCircle * icircle, double iz1, double z2, double curv) :
212  circle(icircle), curvature(curv), radius(1./curv), z1(iz1)
213 {
214  Scalar orthog = sgn(curv) * clamped_sqrt(radius*radius - circle->delta2);
215  center = circle->center + orthog * circle->axis;
216 
217  Scalar absCurv = std::abs(curv);
218  seg = circle->delta;
219  seg = arc(absCurv,seg);
220  dzdu = (z2 - z1) / seg;
221 }
222 
224  const ThirdHitPredictionFromCircle *circle, double z1, double z2, double z3)
225 {
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 
234 
237  if (unlikely(std::abs(curvature) < 1.0e-5)) {
238  Scalar tip = circle->axis * circle->p1;
239  Scalar lip = circle->axis.y() * circle->p1.x() -
240  circle->axis.x() * circle->p1.y();
241  return z1 + (std::sqrt(sqr(r) - sqr(tip)) - lip) * dzdu;
242  }
243 
244  Scalar radius2 = sqr(radius);
245 
246  Scalar b2 = center.mag2();
247  Scalar b = std::sqrt(b2);
248 
249  Scalar cos1 = 0.5 * curvature * (radius2 + b2 - sqr(r)) / b;
250  Scalar cos2 = 0.5 * curvature * (radius2 + b2 - circle->p1.mag2()) / b;
251 
252  Scalar phi1 = clamped_acos(cos1);
253  Scalar phi2 = clamped_acos(cos2);
254 
255  // more plausbility checks needed...
256  // the two circles can have two possible intersections
257  Scalar u1 = std::abs((phi1 - phi2) * radius);
258  Scalar u2 = std::abs((phi1 + phi2) * radius);
259 
260  return z1 + ((u1 >= seg && u1 < u2)? u1 : u2) * dzdu;
261 }
262 
263 
264 #include<vdt/sincos.h>
265 
268  if (unlikely(std::abs(dzdu) < 1.0e-5))
269  return 99999.0;
270 
271  if (unlikely(std::abs(curvature) < 1.0e-5)) {
272  Scalar tip = circle->axis * circle->p1;
273  Scalar lip = circle->axis.y() * circle->p1.x() -
274  circle->axis.x() * circle->p1.y();
275  return std::sqrt(sqr(tip) + sqr(lip + (z - z1) / dzdu));
276  }
277 
278  // we won't go below that (see comment below)
279  Scalar minR2 = (2. * circle->center - circle->p1).mag2();
280 
281  float phi = curvature * (z - z1) / dzdu;
282 
283  if (unlikely(std::abs(phi) > 2. * M_PI)) {
284  // with a helix we can get problems here - this is used to get the limits
285  // however, if phi gets large, we get into the regions where we loop back
286  // to smaller r's. The question is - do we care about these tracks?
287  // The answer is probably no: Too much pain, and the rest of the
288  // tracking won't handle looping tracks anyway.
289  // So, what we do here is to return nothing smaller than the radius
290  // than any of the two hits, i.e. the second hit, which is presumably
291  // outside of the 1st hit.
292 
293  return std::sqrt(minR2);
294  }
295 
296  Vector2D rel = circle->p1 - center;
297 
298  float c;
299  float s;
300  vdt::fast_sincosf(phi,s,c);
301 
302  Vector2D p(center.x() + c * rel.x() - s * rel.y(),
303  center.y() + s * rel.x() + c * rel.y());
304 
305  return std::sqrt(std::max(minR2, p.mag2()));
306 }
double transverseIP(const Vector2D &thirdPoint) const
float approx_asin_P< 7 >(float z)
Definition: approx_asin.h:18
Scalar invCenterOnAxis(const Vector2D &thirdPoint) const
float angle(float curvature, float radius) const
T mag() const
The vector magnitude. Equivalent to sqrt(vec.mag2())
float sgn(float val)
Definition: FWPFMaths.cc:9
double sign(double x)
Sin< T >::type sin(const T &t)
Definition: Sin.h:22
T y() const
Definition: PV3DBase.h:63
T mag() const
The vector magnitude. Equivalent to sqrt(vec.mag2())
list diff
Definition: mps_update.py:85
#define constexpr
float float float z
Range curvature(double transverseIP) const
#define unlikely(x)
tuple d
Definition: ztail.py:151
T x() const
Cartesian x coordinate.
T curvature(T InversePt, const edm::EventSetup &iSetup)
void swap(edm::DataFrameContainer &lhs, edm::DataFrameContainer &rhs)
T sqrt(T t)
Definition: SSEVec.h:18
T mag2() const
The vector magnitude squared. Equivalent to vec.dot(vec)
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]
T min(T a, T b)
Definition: MathUtil.h:58
static const double SMALL
Definition: herwig.h:292
double p2[4]
Definition: TauolaWrapper.h:90
T y() const
Cartesian y coordinate.
#define M_PI
ThirdHitPredictionFromCircle(const GlobalPoint &P1, const GlobalPoint &P2, float tolerance)
Range operator()(Range curvature, float radius) const
static double maxCurvature(const ThirdHitPredictionFromCircle *circle, double z1, double z2, double z3)
T proxim(T b, T a)
Definition: normalizedPhi.h:14
double b
Definition: hdecay.h:120
T mag2() const
The vector magnitude squared. Equivalent to vec.dot(vec)
std::vector< std::vector< double > > tmp
Definition: MVATrainer.cc:100
double p1[4]
Definition: TauolaWrapper.h:89
double a
Definition: hdecay.h:121
Square< F >::type sqr(const F &f)
Definition: Square.h:13
const ThirdHitPredictionFromCircle * circle
Geom::Phi< T > phi() const
long double T
T x() const
Definition: PV3DBase.h:62
float phi(float curvature, float radius) const
T normalizedPhi(T phi)
Definition: normalizedPhi.h:9
T x() const
Cartesian x coordinate.