Skip to content

Commit 81dc8f0

Browse files
committed
[MathMore] allow using several methods of Polynomial.h in const context
- Remove unused `fRoots` data member (it was cleared before each root computation and provided no persistent state). - Return polynomial roots by value instead of via internal storage. - Mark the affected query/utility methods as `const` to make the class usable in const contexts. - Apply clang-format to the modified sections.
1 parent 4ac2999 commit 81dc8f0

File tree

2 files changed

+67
-81
lines changed

2 files changed

+67
-81
lines changed

math/mathmore/inc/Math/Polynomial.h

Lines changed: 3 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -116,20 +116,20 @@ class Polynomial : public ParamFunction<IParamGradFunction>,
116116
equation is very small. In that case it might be more robust to use the numerical method, by calling directly FindNumRoots()
117117
118118
*/
119-
const std::vector<std::complex <double> > & FindRoots();
119+
std::vector<std::complex<double>> FindRoots() const;
120120

121121
/**
122122
Find the only the real polynomial roots.
123123
For n <= 4, the roots are found analytically while for larger order an iterative numerical method is used
124124
The numerical method used is from GSL (see <A HREF="https://www.gnu.org/software/gsl/doc/html/poly.html">documentation</A> )
125125
*/
126-
std::vector<double > FindRealRoots();
126+
std::vector<double> FindRealRoots() const;
127127

128128
/**
129129
Find the polynomial roots using always an iterative numerical methods
130130
The numerical method used is from GSL (see <A HREF="https://www.gnu.org/software/gsl/doc/html/poly.html">documentation</A> )
131131
*/
132-
const std::vector<std::complex <double> > & FindNumRoots();
132+
std::vector<std::complex<double>> FindNumRoots() const;
133133

134134
/**
135135
Order of Polynomial
@@ -164,11 +164,6 @@ class Polynomial : public ParamFunction<IParamGradFunction>,
164164

165165
// cache Parameters for Gradient
166166
mutable std::vector<double> fDerived_params;
167-
168-
// roots
169-
170-
std::vector< std::complex < double > > fRoots;
171-
172167
};
173168

174169
} // namespace Math

math/mathmore/src/Polynomial.cxx

Lines changed: 64 additions & 73 deletions
Original file line numberDiff line numberDiff line change
@@ -147,43 +147,40 @@ IGenFunction * Polynomial::Clone() const {
147147
return f;
148148
}
149149

150+
std::vector<std::complex<double>> Polynomial::FindRoots() const
151+
{
150152

151-
const std::vector< std::complex <double> > & Polynomial::FindRoots(){
152-
153-
154-
// check if order is correct
155-
unsigned int n = fOrder;
156-
while ( Parameters()[n] == 0 ) {
153+
// check if order is correct
154+
unsigned int n = fOrder;
155+
while (Parameters()[n] == 0) {
157156
n--;
158-
}
157+
}
159158

160-
fRoots.clear();
161-
fRoots.reserve(n);
159+
std::vector<std::complex<double>> roots;
162160

163-
164-
if (n == 0) {
165-
return fRoots;
166-
}
167-
else if (n == 1 ) {
168-
if ( Parameters()[1] == 0) return fRoots;
161+
if (n == 0) {
162+
return roots;
163+
} else if (n == 1) {
164+
if (Parameters()[1] == 0)
165+
return roots;
169166
double r = - Parameters()[0]/ Parameters()[1];
170-
fRoots.push_back( std::complex<double> ( r, 0.0) );
171-
}
172-
// quadratic equations
173-
else if (n == 2 ) {
167+
roots.push_back(std::complex<double>(r, 0.0));
168+
}
169+
// quadratic equations
170+
else if (n == 2) {
174171
gsl_complex z1, z2;
175172
int nr = gsl_poly_complex_solve_quadratic(Parameters()[2], Parameters()[1], Parameters()[0], &z1, &z2);
176173
if ( nr != 2) {
177174
#ifdef DEBUG
178175
std::cout << "Polynomial quadratic ::- FAILED to find roots" << std::endl;
179176
#endif
180-
return fRoots;
177+
return roots;
181178
}
182-
fRoots.push_back(std::complex<double>(z1.dat[0],z1.dat[1]) );
183-
fRoots.push_back(std::complex<double>(z2.dat[0],z2.dat[1]) );
184-
}
185-
// cubic equations
186-
else if (n == 3 ) {
179+
roots.push_back(std::complex<double>(z1.dat[0], z1.dat[1]));
180+
roots.push_back(std::complex<double>(z2.dat[0], z2.dat[1]));
181+
}
182+
// cubic equations
183+
else if (n == 3) {
187184
gsl_complex z1, z2, z3;
188185
// renormmalize params in this case
189186
double w = Parameters()[3];
@@ -195,15 +192,14 @@ const std::vector< std::complex <double> > & Polynomial::FindRoots(){
195192
#ifdef DEBUG
196193
std::cout << "Polynomial cubic::- FAILED to find roots" << std::endl;
197194
#endif
198-
return fRoots;
199-
195+
return roots;
200196
}
201-
fRoots.push_back(std::complex<double> (z1.dat[0],z1.dat[1]) );
202-
fRoots.push_back(std::complex<double> (z2.dat[0],z2.dat[1]) );
203-
fRoots.push_back(std::complex<double> (z3.dat[0],z3.dat[1]) );
204-
}
205-
// quartic equations
206-
else if (n == 4 ) {
197+
roots.push_back(std::complex<double>(z1.dat[0], z1.dat[1]));
198+
roots.push_back(std::complex<double>(z2.dat[0], z2.dat[1]));
199+
roots.push_back(std::complex<double>(z3.dat[0], z3.dat[1]));
200+
}
201+
// quartic equations
202+
else if (n == 4) {
207203
// quartic eq.
208204
gsl_complex z1, z2, z3, z4;
209205
// renormalize params in this case
@@ -217,60 +213,55 @@ const std::vector< std::complex <double> > & Polynomial::FindRoots(){
217213
#ifdef DEBUG
218214
std::cout << "Polynomial quartic ::- FAILED to find roots" << std::endl;
219215
#endif
220-
return fRoots;
216+
return roots;
221217
}
222-
fRoots.push_back(std::complex<double> (z1.dat[0],z1.dat[1]) );
223-
fRoots.push_back(std::complex<double> (z2.dat[0],z2.dat[1]) );
224-
fRoots.push_back(std::complex<double> (z3.dat[0],z3.dat[1]) );
225-
fRoots.push_back(std::complex<double> (z4.dat[0],z4.dat[1]) );
226-
}
227-
else {
228-
// for higher order polynomial use numerical fRoots
229-
FindNumRoots();
230-
}
231-
232-
return fRoots;
233-
234-
}
235-
236-
237-
std::vector< double > Polynomial::FindRealRoots(){
238-
FindRoots();
239-
std::vector<double> roots;
240-
roots.reserve(fOrder);
241-
for (unsigned int i = 0; i < fOrder; ++i) {
242-
if (fRoots[i].imag() == 0)
243-
roots.push_back( fRoots[i].real() );
244-
}
245-
return roots;
218+
roots.push_back(std::complex<double>(z1.dat[0], z1.dat[1]));
219+
roots.push_back(std::complex<double>(z2.dat[0], z2.dat[1]));
220+
roots.push_back(std::complex<double>(z3.dat[0], z3.dat[1]));
221+
roots.push_back(std::complex<double>(z4.dat[0], z4.dat[1]));
222+
} else {
223+
// for higher order polynomial use numerical roots
224+
return FindNumRoots();
225+
}
226+
227+
return roots;
246228
}
247-
const std::vector< std::complex <double> > & Polynomial::FindNumRoots(){
248229

230+
std::vector<double> Polynomial::FindRealRoots() const
231+
{
232+
auto roots = FindRoots();
233+
std::vector<double> realRoots;
234+
for (const auto &r : roots)
235+
if (std::abs(r.imag()) < std::numeric_limits<double>::epsilon())
236+
realRoots.push_back(r.real());
249237

250-
// check if order is correct
251-
unsigned int n = fOrder;
252-
while ( Parameters()[n] == 0 ) {
253-
n--;
254-
}
255-
fRoots.clear();
256-
fRoots.reserve(n);
238+
return realRoots;
239+
}
240+
std::vector<std::complex<double>> Polynomial::FindNumRoots() const
241+
{
257242

243+
// check if order is correct
244+
unsigned int n = fOrder;
245+
while (Parameters()[n] == 0) {
246+
n--;
247+
}
258248

259-
if (n == 0) {
260-
return fRoots;
261-
}
249+
std::vector<std::complex<double>> roots;
250+
if (n == 0) {
251+
return roots;
252+
}
262253

263254
gsl_poly_complex_workspace * w = gsl_poly_complex_workspace_alloc( n + 1);
264255
std::vector<double> z(2*n);
265256
int status = gsl_poly_complex_solve ( Parameters(), n+1, w, &z.front() );
266257
gsl_poly_complex_workspace_free(w);
267-
if (status != GSL_SUCCESS) return fRoots;
258+
if (status != GSL_SUCCESS)
259+
return roots;
268260
for (unsigned int i = 0; i < n; ++i)
269-
fRoots.push_back(std::complex<double> (z[2*i],z[2*i+1] ) );
261+
roots.push_back(std::complex<double>(z[2 * i], z[2 * i + 1]));
270262

271-
return fRoots;
263+
return roots;
272264
}
273265

274-
275266
} // namespace Math
276267
} // namespace ROOT

0 commit comments

Comments
 (0)