Belle II Software development
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
14using namespace Belle2;
15using namespace TrackFindingCDC;
16
17double 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) {
30
32 if (root > 0) return root;
33 }
34
35 return NAN;
36}
37
39{
40 if (hasLargeSlope()) {
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
67double 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 secant.
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 division.
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
134double SinEqLine::middleX(const Vector2D& lower, const Vector2D& upper)
135{
136 return (lower.x() + upper.x()) / 2.0;
137}
138
139double 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
144double SinEqLine::newtonX(const Vector2D& pos) const
145{
146 return pos.x() - pos.y() / gradient(pos.x());
147}
148
149bool 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
185double 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 interval 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 interval.
Definition: SinEqLine.h:133
double getIntercept() const
Getter for the intercept.
Definition: SinEqLine.h:164
double computeExtremumXInHalfPeriod(int iHalfPeriod) const
Get the local extremum 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 extrema.
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 chosen consecutive lo...
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 interval 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 division of the interval.
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 interval.
Definition: SinEqLine.h:110
static bool changesSign(const Vector2D &lower, const Vector2D &upper)
Checks if the function changes sign in the interval.
Definition: SinEqLine.h:129
A two dimensional vector which is equipped with functions for correct handling of orientation relate...
Definition: Vector2D.h:32
void set(const double first, const double second)
Setter for both coordinate.
Definition: Vector2D.h:650
double x() const
Getter for the x coordinate.
Definition: Vector2D.h:595
void setY(const double y)
Setter for the y coordinate.
Definition: Vector2D.h:610
double y() const
Getter for the y coordinate.
Definition: Vector2D.h:605
void setX(const double x)
Setter for the x coordinate.
Definition: Vector2D.h:600
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.