vnl_rpoly_roots.cxx
Go to the documentation of this file.
1 // This is core/vnl/algo/vnl_rpoly_roots.cxx
2 //:
3 // \file
4 //
5 // \author Andrew W. Fitzgibbon, Oxford RRG
6 // \date 06 Aug 96
7 //
8 //-----------------------------------------------------------------------------
9 
10 #include <cmath>
11 #include <iostream>
12 #include <complex>
13 #include "vnl_rpoly_roots.h"
14 
15 #include <vnl/algo/vnl_netlib.h> // rpoly_()
17 
18 // - The constructor calculates the roots. This is the most efficient interface
19 // as all the result variables are initialized to the correct size.
20 // The polynomial is $ a[0] x^d + a[1] x^{d-1} + \cdots + a[d] = 0 $.
21 // Note that if the routine fails, not all roots will be found. In this case,
22 // the "realroots" and "roots" functions will return fewer than n roots.
24  : coeffs_(a), r_(coeffs_.size()-1), i_(coeffs_.size()-1)
25 {
26  // fsm : if the coefficients are NaNs then rpoly_ gets stuck in an
27  // infinite loop. of course, the caller shouldn't pass in NaNs, but
28  // it would be nice to get an error message instead of hanging.
29  a.assert_finite();
30 
31  compute();
32 }
33 
35  : coeffs_(poly.coefficients()), r_(poly.degree()), i_(poly.degree())
36 {
37  poly.coefficients().assert_finite();
38 
39  compute();
40 }
41 
42 // - Complex vector of all roots.
44 {
46  for (int i = 0; i < num_roots_found_; ++i)
47  ret[i] = std::complex<double>(r_[i], i_[i]);
48  return ret;
49 }
50 
51 // - Return real roots only. Roots are real if the absolute value
52 // of their imaginary part is less than the optional argument TOL.
53 // TOL defaults to 1e-12 [untested]
55 {
56  int c = 0;
57  for (int i = 0; i < num_roots_found_; ++i)
58  if (std::fabs(i_[i]) < tol)
59  ++c;
60 
61  vnl_vector<double> ret(c);
62  c = 0;
63  {for (int i = 0; i < num_roots_found_; ++i)
64  if (std::fabs(i_[i]) < tol)
65  ret[c++] = r_[i];}
66 
67  return ret;
68 }
69 
70 //: Compute roots using Jenkins-Traub algorithm.
71 // Calls rpoly and interprets failure codes.
73 {
74  long fail = 0;
75  long n = coeffs_.size() - 1;
76  v3p_netlib_rpoly_global_t rpoly_global;
77  v3p_netlib_rpoly_(coeffs_.data_block(), &n,
78  r_.data_block(), i_.data_block(), &fail, &rpoly_global);
79 
80  if (!fail) {
81  num_roots_found_ = n;
82  return true;
83  }
84 
85  num_roots_found_ = n;
86 
87  if (coeffs_[0] == 0.0)
88  std::cerr << "vnl_rpoly_roots: Leading coefficient is zero. Not allowed.\n";
89  else
90  std::cerr << "vnl_rpoly_roots: Calculation failed, only " << n << " roots found\n";
91 
92  return false;
93 }
vnl_vector< double > i_
size_t size() const
Return the length, number of elements, dimension of this vector.
Definition: vnl_vector.h:126
T const * data_block() const
Access the contiguous block storing the elements in the vector. O(1).
Definition: vnl_vector.h:230
vnl_rpoly_roots(const vnl_vector< double > &a)
The constructor calculates the roots.
vnl_vector< double > coeffs_
const vnl_vector< double > & coefficients() const
Return the vector of coefficients.
Evaluation of real polynomials at real and complex points.
Declare in a central place the list of symbols from netlib.
vnl_vector< double > r_
void assert_finite() const
Check that this is finite if not, abort();.
Definition: vnl_vector.h:355
Finds roots of a real polynomial.
vnl_vector< double > realroots(double tol=1e-12) const
Return real roots only.
bool compute()
Compute roots using Jenkins-Traub algorithm.
vnl_vector< std::complex< double > > roots() const
Complex vector of all roots.
Evaluation of real polynomials.