Belle II Software  release-08-01-10
SinEqLine.cc
1 /**************************************************************************
2  * basf2 (Belle II Analysis Software Framework) *
3  * Author: The Belle II Collaboration *
4  * *
5  * See git log for contributors and copyright holders. *
6  * This file is licensed under LGPL-3.0, see LICENSE.md. *
7  **************************************************************************/
8 #include <tracking/trackFindingCDC/numerics/SinEqLine.h>
9 
10 #include <framework/logging/Logger.h>
11 
12 #include <cmath>
13 
14 using namespace Belle2;
15 using namespace TrackFindingCDC;
16 
17 double SinEqLine::computeSmallestPositiveRoot(int maxIHalfPeriod) const
18 {
21  if (root > 0) return root;
22 
26  if (root > 0) return root;
27 
28  for (int iHalfPeriod = 1; iHalfPeriod <= maxIHalfPeriod; ++iHalfPeriod) {
29  root = computeRootLargerThanExtemumInHalfPeriod(iHalfPeriod);
30 
32  if (root > 0) return root;
33  }
34 
35  return NAN;
36 }
37 
39 {
40  if (hasLargeSlope()) {
41  return computeRootForLargeSlope();
42 
43  } else {
44  double lowerX = computeExtremumXInHalfPeriod(iHalfPeriod);
45  double upperX = computeExtremumXInHalfPeriod(iHalfPeriod + 1);
46  return computeRootInInterval(lowerX, upperX);
47  }
48 }
49 
51 {
52  if (not hasLargeSlope()) return NAN;
53 
54  double xLineIsPlusOne = (1.0 - getIntercept()) / getSlope();
55  double xLineIsMinusOne = (-1.0 - getIntercept()) / getSlope();
56 
57  if (xLineIsPlusOne > xLineIsMinusOne) {
58  return computeRootInInterval(xLineIsMinusOne, xLineIsPlusOne);
59 
60  } else if (xLineIsPlusOne < xLineIsMinusOne) {
61  return computeRootInInterval(xLineIsPlusOne, xLineIsMinusOne);
62  } else {
63  return NAN;
64  }
65 }
66 
67 double SinEqLine::computeRootInInterval(double lowerX, double upperX) const
68 {
69  if (not(lowerX < upperX)) return NAN;
70 
71  Vector2D lower(lowerX, map(lowerX));
72  Vector2D upper(upperX, map(upperX));
73 
76  if (isConverged(lower, upper)) {
77  B2INFO("Coverage early");
78  return getConvergedBound(lower, upper);
79  }
80 
82  if (not changesSign(lower, upper)) {
83  return NAN;
84  }
85 
86  Vector2D last(lower);
87  Vector2D current(upper);
88 
89  Vector2D next;
90  next.setX(secantX(last, current));
91  next.setY(map(next.x()));
92 
93  // Should always succeed since we checked everything before
94  bool updatedBound = updateBounds(lower, upper, next);
95  if (not updatedBound) return NAN;
96 
97  while (not isConverged(lower, upper)) {
98  // swap accepted values
99  last.set(current);
100  current.set(next);
101 
102  next.setX(newtonX(current));
103  next.setY(map(next.x()));
104 
105  updatedBound = updateBounds(lower, upper, next);
106 
107  if (not updatedBound) {
108 
109  // fall back to sekant.
110  next.setX(secantX(last, current));
111  next.setY(map(next.x()));
112 
113  updatedBound = updateBounds(lower, upper, next);
114 
115  if (not updatedBound) {
116  // fallback to interval devision.
117  next.setX(middleX(lower, upper));
118  next.setY(map(next.x()));
119  updatedBound = updateBounds(lower, upper, next);
120 
121  if (not updatedBound) break;
122  }
123  }
124  }
125 
126  if (isConverged(lower, upper)) {
127  return getConvergedBound(lower, upper);
128 
129  } else {
130  return NAN;
131  }
132 }
133 
134 double SinEqLine::middleX(const Vector2D& lower, const Vector2D& upper)
135 {
136  return (lower.x() + upper.x()) / 2.0;
137 }
138 
139 double SinEqLine::secantX(const Vector2D& lower, const Vector2D& upper)
140 {
141  return (lower.x() * upper.y() - upper.x() * lower.y()) / (upper.y() - lower.y());
142 }
143 
144 double SinEqLine::newtonX(const Vector2D& pos) const
145 {
146  return pos.x() - pos.y() / gradient(pos.x());
147 }
148 
149 bool SinEqLine::updateBounds(Vector2D& lower, Vector2D& upper, const Vector2D& next)
150 {
152  if (not isBetween(lower, next, upper)) return false;
153 
154  EIncDec incDecInfo = getEIncDec(lower, upper);
155  if (incDecInfo == EIncDec::c_Increasing) {
156  if (next.y() > 0.0 and upper.y() > 0.0) {
157  upper.set(next);
158  return true;
159 
160  } else if (next.y() <= 0.0 and lower.y() <= 0.0) {
161  lower.set(next);
162  return true;
163 
164  } else {
165  return false;
166  }
167 
168  } else if (incDecInfo == EIncDec::c_Decreasing) {
169  if (next.y() >= 0 and lower.y() >= 0.0) {
170  lower.set(next);
171  return true;
172 
173  } else if (next.y() < 0 and upper.y() < 0) {
174  upper.set(next);
175  return true;
176 
177  } else {
178  return false;
179  }
180  } else {
181  return false;
182  }
183 }
184 
185 double SinEqLine::computeExtremumXInHalfPeriod(int iHalfPeriod) const
186 {
187  const double slope = getSlope();
188  double extremumInFirstHalfPeriod = acos(slope);
189 
190  double extremumInFirstPeriod =
191  isEven(iHalfPeriod) ? extremumInFirstHalfPeriod : 2 * M_PI - extremumInFirstHalfPeriod;
192 
193  int iPeriod = getIPeriodFromIHalfPeriod(iHalfPeriod);
194  return extremumInFirstPeriod + 2 * M_PI * iPeriod;
195 }
static bool isBetween(const Vector2D &lower, const Vector2D &next, const Vector2D &upper)
Check is next position is within the intervall given by lower and upper.
Definition: SinEqLine.h:100
static EIncDec getEIncDec(const Vector2D &lower, const Vector2D &upper)
Determines if the function is increasing or decreasing in the intervall.
Definition: SinEqLine.h:133
double getIntercept() const
Getter for the intercept.
Definition: SinEqLine.h:164
double computeExtremumXInHalfPeriod(int iHalfPeriod) const
Get the local extermum that is located in the half period indicated by the given index.
Definition: SinEqLine.cc:185
static bool updateBounds(Vector2D &lower, Vector2D &upper, const Vector2D &next)
Replaces the lower or upper bound inplace if the next candidate position is valid and within the inte...
Definition: SinEqLine.cc:149
bool hasLargeSlope() const
Indicates that the slope is so large such that the function has no local exterma.
Definition: SinEqLine.h:156
double computeRootInInterval(double lowerX, double upperX) const
Computes the solution in between the given x values. The x values are generally choosen consecutive l...
Definition: SinEqLine.cc:67
double getSlope() const
Getter for the slope.
Definition: SinEqLine.h:160
double computeSmallestPositiveRoot(int maxIHalfPeriod=5) const
Definition: SinEqLine.cc:17
static double secantX(const Vector2D &lower, const Vector2D &upper)
Fall back shrinking method to the secant algorithm.
Definition: SinEqLine.cc:139
double computeRootForLargeSlope() const
Compute single solution in the case that fabs(slope) >= 1.
Definition: SinEqLine.cc:50
double newtonX(const Vector2D &pos) const
Shrinking method of the newton algorithm return the next candidate root.
Definition: SinEqLine.cc:144
double computeRootLargerThanExtemumInHalfPeriod(int iHalfPeriod) const
Computes the solution that is addressed by the given half period index.
Definition: SinEqLine.cc:38
static bool isConverged(const Vector2D &lower, const Vector2D &upper)
Check if the intervall has shrunk close enough to the solution.
Definition: SinEqLine.h:104
static int getIPeriodFromIHalfPeriod(int iHalfPeriod)
Helper function to translate the index of the half period to index of the containing period.
Definition: SinEqLine.h:151
double gradient(const double x) const
Interpreting as the function f this method calculates the gradient as need in Newtons algorithms.
Definition: SinEqLine.h:64
static double middleX(const Vector2D &lower, const Vector2D &upper)
Simple fall back shrinking method using trivial devision of the intervall.
Definition: SinEqLine.cc:134
double map(const double x) const
Interpreting as the function f this method carries out the translation from x to y coordinates.
Definition: SinEqLine.h:60
static double getConvergedBound(const Vector2D &lower, const Vector2D &upper)
Returns the better solution x from the bounds of the intervall.
Definition: SinEqLine.h:110
static bool changesSign(const Vector2D &lower, const Vector2D &upper)
Checks if the function changes sign in the intervall.
Definition: SinEqLine.h:129
A two dimensional vector which is equipped with functions for correct handeling of orientation relat...
Definition: Vector2D.h:35
void set(const double first, const double second)
Setter for both coordinate.
Definition: Vector2D.h:662
double x() const
Getter for the x coordinate.
Definition: Vector2D.h:607
void setY(const double y)
Setter for the y coordinate.
Definition: Vector2D.h:622
double y() const
Getter for the y coordinate.
Definition: Vector2D.h:617
void setX(const double x)
Setter for the x coordinate.
Definition: Vector2D.h:612
EIncDec
Enumeration to represent the distinct possibilities of the right left passage information.
Definition: EIncDec.h:25
Abstract base class for different kinds of events.