Belle II Software development
SinEqLine Class Reference

Helper class to calculate roots for the function f(x) = sin x - slope * x - intercept. More...

#include <SinEqLine.h>

Public Member Functions

 SinEqLine ()
 Default constructor initializing slope and intercept to zero.
 
 SinEqLine (const Line2D &line2D)
 Constructor taking the line that shall be superimposed with the sin curve.
 
 SinEqLine (const double slope, const double intercept)
 Constructor taking the slope and intercept of the line that shall be superimposed with the sin curve.
 
double map (const double x) const
 Interpreting as the function f this method carries out the translation from x to y coordinates.
 
double gradient (const double x) const
 Interpreting as the function f this method calculates the gradient as need in Newtons algorithms.
 
int getIHalfPeriod (const double x) const
 Returns the half period index in which the x position is located.
 
double computeSmallestPositiveRoot (int maxIHalfPeriod=5) const
 
double computeRootLargerThanExtemumInHalfPeriod (int iHalfPeriod) const
 Computes the solution that is addressed by the given half period index.
 
double computeRootForLargeSlope () const
 Compute single solution in the case that fabs(slope) >= 1.
 
double computeRootInInterval (double lowerX, double upperX) const
 Computes the solution in between the given x values. The x values are generally chosen consecutive local extremes.
 
double computeExtremumXInHalfPeriod (int iHalfPeriod) const
 Get the local extremum that is located in the half period indicated by the given index.
 
bool hasLargeSlope () const
 Indicates that the slope is so large such that the function has no local extrema.
 
double getSlope () const
 Getter for the slope.
 
double getIntercept () const
 Getter for the intercept.
 

Static Public Member Functions

static bool changesSign (const Vector2D &lower, const Vector2D &upper)
 Checks if the function changes sign in the interval.
 
static EIncDec getEIncDec (const Vector2D &lower, const Vector2D &upper)
 Determines if the function is increasing or decreasing in the interval.
 
static int getIPeriodFromIHalfPeriod (int iHalfPeriod)
 Helper function to translate the index of the half period to index of the containing period.
 

Private Member Functions

double newtonX (const Vector2D &pos) const
 Shrinking method of the newton algorithm return the next candidate root.
 

Static Private Member Functions

static double secantX (const Vector2D &lower, const Vector2D &upper)
 Fall back shrinking method to the secant algorithm.
 
static double middleX (const Vector2D &lower, const Vector2D &upper)
 Simple fall back shrinking method using trivial division of the interval.
 
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 interval. Returns true on success.
 
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.
 
static bool isConverged (const Vector2D &lower, const Vector2D &upper)
 Check if the interval has shrunk close enough to the solution.
 
static double getConvergedBound (const Vector2D &lower, const Vector2D &upper)
 Returns the better solution x from the bounds of the interval.
 

Private Attributes

double m_slope
 Memory for the slope.
 
double m_intercept
 Memory for the intercept.
 

Detailed Description

Helper class to calculate roots for the function f(x) = sin x - slope * x - intercept.

Solves the equation sin x = slope * x + intercept by Newton's method on the function f(x) = sin x - slope * x - intercept. There can be zero, infinitely many solutions and anything in-between depending on the value of slope and intercept. To find solutions we exploit that the local extrema of the function f(x) can be found easily and that maximally one solutions can be found between consecutive extrema. There is exactly one local extremum in each half period of sin(x) and local extrema are therefore addressed by there half period index. Each possible solution of the equation is than addressed by the index of the closest smaller local extrema. However only a range of indices corresponds to realized solutions. For non existent solutions NAN is returned. Note that for fabs(slope) >= 1 there are no more local maxima. In this case only a single solution exists, which is always returned for any index.

Definition at line 36 of file SinEqLine.h.

Constructor & Destructor Documentation

◆ SinEqLine() [1/3]

SinEqLine ( )
inline

Default constructor initializing slope and intercept to zero.

Definition at line 40 of file SinEqLine.h.

40 :
41 m_slope(0.0),
42 m_intercept(0.0)
43 {}
double m_intercept
Memory for the intercept.
Definition: SinEqLine.h:172
double m_slope
Memory for the slope.
Definition: SinEqLine.h:169

◆ SinEqLine() [2/3]

SinEqLine ( const Line2D line2D)
inlineexplicit

Constructor taking the line that shall be superimposed with the sin curve.

Definition at line 47 of file SinEqLine.h.

47 :
48 m_slope(line2D.slope()),
49 m_intercept(line2D.intercept())
50 {}

◆ SinEqLine() [3/3]

SinEqLine ( const double  slope,
const double  intercept 
)
inline

Constructor taking the slope and intercept of the line that shall be superimposed with the sin curve.

Definition at line 53 of file SinEqLine.h.

53 :
54 m_slope(slope),
55 m_intercept(intercept)
56 {}

Member Function Documentation

◆ changesSign()

static bool changesSign ( const Vector2D lower,
const Vector2D upper 
)
inlinestatic

Checks if the function changes sign in the interval.

Definition at line 129 of file SinEqLine.h.

130 { return (lower.y() > 0 and upper.y() < 0) or (lower.y() < 0 and upper.y() > 0); }

◆ computeExtremumXInHalfPeriod()

double computeExtremumXInHalfPeriod ( int  iHalfPeriod) const

Get the local extremum that is located in the half period indicated by the given index.

Definition at line 185 of file SinEqLine.cc.

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}
double getSlope() const
Getter for the slope.
Definition: SinEqLine.h:160
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

◆ computeRootForLargeSlope()

double computeRootForLargeSlope ( ) const

Compute single solution in the case that fabs(slope) >= 1.

Definition at line 50 of file SinEqLine.cc.

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}
double getIntercept() const
Getter for the intercept.
Definition: SinEqLine.h:164
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

◆ computeRootInInterval()

double computeRootInInterval ( double  lowerX,
double  upperX 
) const

Computes the solution in between the given x values. The x values are generally chosen consecutive local extremes.

Checks if convergence criterium has been met. For instance if one bound is already exactly at the root.

Checks if the function changes sign in the interval

Definition at line 67 of file SinEqLine.cc.

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}
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
static double secantX(const Vector2D &lower, const Vector2D &upper)
Fall back shrinking method to the secant algorithm.
Definition: SinEqLine.cc:139
double newtonX(const Vector2D &pos) const
Shrinking method of the newton algorithm return the next candidate root.
Definition: SinEqLine.cc:144
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 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
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
void setX(const double x)
Setter for the x coordinate.
Definition: Vector2D.h:600

◆ computeRootLargerThanExtemumInHalfPeriod()

double computeRootLargerThanExtemumInHalfPeriod ( int  iHalfPeriod) const

Computes the solution that is addressed by the given half period index.

Definition at line 38 of file SinEqLine.cc.

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}
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
double computeRootForLargeSlope() const
Compute single solution in the case that fabs(slope) >= 1.
Definition: SinEqLine.cc:50

◆ computeSmallestPositiveRoot()

double computeSmallestPositiveRoot ( int  maxIHalfPeriod = 5) const

Smallest positive root might before the first positive extremum

Most of the time to should be sufficient to look for the root in the first two half periods. So we spell out this case explicitly.

Check if the solution returned is positive, that implies that it is not NAN.

Definition at line 17 of file SinEqLine.cc.

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}
double computeRootLargerThanExtemumInHalfPeriod(int iHalfPeriod) const
Computes the solution that is addressed by the given half period index.
Definition: SinEqLine.cc:38

◆ getConvergedBound()

static double getConvergedBound ( const Vector2D lower,
const Vector2D upper 
)
inlinestaticprivate

Returns the better solution x from the bounds of the interval.

Definition at line 110 of file SinEqLine.h.

111 {
112 if (not std::isfinite(lower.y()) or not std::isfinite(upper.y())) {
113 return NAN;
114 }
115
116 if (fabs(lower.y()) <= fabs(upper.y())) {
117 return lower.x();
118 }
119
120 if (fabs(lower.y()) > fabs(upper.y())) {
121 return upper.x();
122 }
123
124 return NAN;
125 }

◆ getEIncDec()

static EIncDec getEIncDec ( const Vector2D lower,
const Vector2D upper 
)
inlinestatic

Determines if the function is increasing or decreasing in the interval.

Definition at line 133 of file SinEqLine.h.

134 {
135 if (lower.y() < upper.y()) {
136 return EIncDec::c_Increasing;
137 } else if (lower.y() > upper.y()) {
138 return EIncDec::c_Decreasing;
139 } else if (lower.y() == upper.y()) {
140 return EIncDec::c_Constant;
141 } else {
142 return EIncDec::c_Invalid;
143 }
144 }

◆ getIHalfPeriod()

int getIHalfPeriod ( const double  x) const
inline

Returns the half period index in which the x position is located.

Definition at line 68 of file SinEqLine.h.

69 { return floor(x / M_PI); }

◆ getIntercept()

double getIntercept ( ) const
inline

Getter for the intercept.

Definition at line 164 of file SinEqLine.h.

165 { return m_intercept; }

◆ getIPeriodFromIHalfPeriod()

static int getIPeriodFromIHalfPeriod ( int  iHalfPeriod)
inlinestatic

Helper function to translate the index of the half period to index of the containing period.

Definition at line 151 of file SinEqLine.h.

152 { return isEven(iHalfPeriod) ? iHalfPeriod / 2 : (iHalfPeriod - 1) / 2; }

◆ getSlope()

double getSlope ( ) const
inline

Getter for the slope.

Definition at line 160 of file SinEqLine.h.

161 { return m_slope; }

◆ gradient()

double gradient ( const double  x) const
inline

Interpreting as the function f this method calculates the gradient as need in Newtons algorithms.

Definition at line 64 of file SinEqLine.h.

65 { return cos(x) - getSlope(); }

◆ hasLargeSlope()

bool hasLargeSlope ( ) const
inline

Indicates that the slope is so large such that the function has no local extrema.

Definition at line 156 of file SinEqLine.h.

157 { return fabs(getSlope()) >= 1; }

◆ isBetween()

static bool isBetween ( const Vector2D lower,
const Vector2D next,
const Vector2D upper 
)
inlinestaticprivate

Check is next position is within the interval given by lower and upper.

Definition at line 100 of file SinEqLine.h.

101 { return lower.x() < next.x() and next.x() < upper.x(); }

◆ isConverged()

static bool isConverged ( const Vector2D lower,
const Vector2D upper 
)
inlinestaticprivate

Check if the interval has shrunk close enough to the solution.

Definition at line 104 of file SinEqLine.h.

105 {
106 return fabs(lower.y()) < 10e-7 or fabs(upper.y()) < 10e-7;
107 }

◆ map()

double map ( const double  x) const
inline

Interpreting as the function f this method carries out the translation from x to y coordinates.

Definition at line 60 of file SinEqLine.h.

61 { return sin(x) - getSlope() * x - getIntercept(); }

◆ middleX()

double middleX ( const Vector2D lower,
const Vector2D upper 
)
staticprivate

Simple fall back shrinking method using trivial division of the interval.

Definition at line 134 of file SinEqLine.cc.

135{
136 return (lower.x() + upper.x()) / 2.0;
137}

◆ newtonX()

double newtonX ( const Vector2D pos) const
private

Shrinking method of the newton algorithm return the next candidate root.

Definition at line 144 of file SinEqLine.cc.

145{
146 return pos.x() - pos.y() / gradient(pos.x());
147}
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

◆ secantX()

double secantX ( const Vector2D lower,
const Vector2D upper 
)
staticprivate

Fall back shrinking method to the secant algorithm.

Definition at line 139 of file SinEqLine.cc.

140{
141 return (lower.x() * upper.y() - upper.x() * lower.y()) / (upper.y() - lower.y());
142}
double y() const
Getter for the y coordinate.
Definition: Vector2D.h:605

◆ updateBounds()

bool updateBounds ( Vector2D lower,
Vector2D upper,
const Vector2D next 
)
staticprivate

Replaces the lower or upper bound inplace if the next candidate position is valid and within the interval. Returns true on success.

Only update if the next point is in-between the lower and upper bound

Definition at line 149 of file SinEqLine.cc.

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}
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
void set(const double first, const double second)
Setter for both coordinate.
Definition: Vector2D.h:650
EIncDec
Enumeration to represent the distinct possibilities of the right left passage information.
Definition: EIncDec.h:25

Member Data Documentation

◆ m_intercept

double m_intercept
private

Memory for the intercept.

Definition at line 172 of file SinEqLine.h.

◆ m_slope

double m_slope
private

Memory for the slope.

Definition at line 169 of file SinEqLine.h.


The documentation for this class was generated from the following files: