Skip to content

Commit 162c758

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 162c758

File tree

2 files changed

+54
-67
lines changed

2 files changed

+54
-67
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: 51 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -147,27 +147,24 @@ 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) );
167+
roots.push_back(std::complex<double>(r, 0.0));
171168
}
172169
// quadratic equations
173170
else if (n == 2 ) {
@@ -177,10 +174,10 @@ const std::vector< std::complex <double> > & Polynomial::FindRoots(){
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]) );
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]));
184181
}
185182
// cubic equations
186183
else if (n == 3 ) {
@@ -195,12 +192,11 @@ 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]) );
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]));
204200
}
205201
// quartic equations
206202
else if (n == 4 ) {
@@ -217,60 +213,56 @@ 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]) );
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]));
226222
}
227223
else {
228-
// for higher order polynomial use numerical fRoots
229-
FindNumRoots();
224+
// for higher order polynomial use numerical roots
225+
return FindNumRoots();
230226
}
231227

232-
return fRoots;
233-
234-
}
228+
return roots;
229+
}
235230

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

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;
239+
return realRoots;
246240
}
247-
const std::vector< std::complex <double> > & Polynomial::FindNumRoots(){
248-
241+
std::vector<std::complex<double>> Polynomial::FindNumRoots() const
242+
{
249243

250-
// check if order is correct
251-
unsigned int n = fOrder;
252-
while ( Parameters()[n] == 0 ) {
244+
// check if order is correct
245+
unsigned int n = fOrder;
246+
while (Parameters()[n] == 0) {
253247
n--;
254-
}
255-
fRoots.clear();
256-
fRoots.reserve(n);
257-
248+
}
258249

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

263255
gsl_poly_complex_workspace * w = gsl_poly_complex_workspace_alloc( n + 1);
264256
std::vector<double> z(2*n);
265257
int status = gsl_poly_complex_solve ( Parameters(), n+1, w, &z.front() );
266258
gsl_poly_complex_workspace_free(w);
267-
if (status != GSL_SUCCESS) return fRoots;
259+
if (status != GSL_SUCCESS)
260+
return roots;
268261
for (unsigned int i = 0; i < n; ++i)
269-
fRoots.push_back(std::complex<double> (z[2*i],z[2*i+1] ) );
262+
roots.push_back(std::complex<double>(z[2 * i], z[2 * i + 1]));
270263

271-
return fRoots;
264+
return roots;
272265
}
273266

274-
275267
} // namespace Math
276268
} // namespace ROOT

0 commit comments

Comments
 (0)