Basic Image AlgorithmS Library  2.8.0
 All Classes Namespaces Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
PolynomialSolve.hh
1 /*
2 This file is part of the BIAS library (Basic ImageAlgorithmS).
3 
4 Copyright (C) 2003-2009 (see file CONTACT for details)
5  Multimediale Systeme der Informationsverarbeitung
6  Institut fuer Informatik
7  Christian-Albrechts-Universitaet Kiel
8 
9 
10 BIAS is free software; you can redistribute it and/or modify
11 it under the terms of the GNU Lesser General Public License as published by
12 the Free Software Foundation; either version 2.1 of the License, or
13 (at your option) any later version.
14 
15 BIAS is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU Lesser General Public License for more details.
19 
20 You should have received a copy of the GNU Lesser General Public License
21 along with BIAS; if not, write to the Free Software
22 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23 */
24 
25 
26 #ifndef _BIAS_POLYNOMIALSOLVE_
27 #define _BIAS_POLYNOMIALSOLVE_
28 
29 #include <Base/Common/BIASpragmaStart.hh>
30 
31 #include <cfloat>
32 #include <vector>
33 #include <complex>
34 #include "Base/Debug/Debug.hh"
35 #include "Base/Debug/Error.hh"
36 
37 #define POLYNOMIALSOLVE_TYPE double
38 
39 #define D_PS_GSL 0x00000001
40 #define D_PS_NLREFINE 0x00000002
41 #define D_PS_COEFF 0x00000004
42 
43 namespace BIAS {
44 
45  /** @class PolynomialSolve
46  @ingroup g_mathalgo
47  @brief base class for solving polynomial equations
48 
49  @author koeser 10/2003, woelk 08/2004 */
50  class BIASMathAlgo_EXPORT PolynomialSolve : public Debug
51  {
52 
53  public:
54  PolynomialSolve() {PowellCoeff_=NULL; PowellCoeffNum_=0;};
56 
57  /** @brief solve polynomial of arbitrary order n
58  coeff[n]x^n+...+coeff[2]x^2+coeff[1]x+coeff[0]=0
59  coeff[n]!=0.0 is asserted
60  Uses analytical solution if n<=4
61  @return number of real solutions, negative value on error
62  @author koeser, woelk 08/2004 untested */
63  int Solve(const std::vector<POLYNOMIALSOLVE_TYPE>& coeff,
64  std::vector<POLYNOMIALSOLVE_TYPE>& sol);
65 
66  /** @brief solve polynomial of arbitrary order n
67  coeff[n]x^n+...+coeff[2]x^2+coeff[1]x+coeff[0]=0
68  coeff[n]!=0.0 is asserted.
69  Uses analytical solution if n<=3
70  @return number of solutions, negative value on error
71  @author woelk 08/2004 untested */
72  int Solve(const std::vector<POLYNOMIALSOLVE_TYPE>& coeff,
73  std::vector<std::complex<POLYNOMIALSOLVE_TYPE> >& sol);
74 
75  /** @brief solves polynomial of arbitrary order n numerically
76  coeff[n]x^n+...+coeff[2]x^2+coeff[1]x+coeff[0]=0
77  coeff[n]!=0.0 is asserted.
78  @return number of real solutions, negative value on error
79  @author woelk 08/2004 untested */
80  int Numeric(const std::vector<POLYNOMIALSOLVE_TYPE>& coeff,
81  std::vector<POLYNOMIALSOLVE_TYPE>& sol);
82  /** @brief solves polynomial of arbitrary order n numerically
83  coeff[n]x^n+...+coeff[2]x^2+coeff[1]x+coeff[0]=0
84  coeff[n]!=0.0 is asserted.
85  @return number of complex solutions, negative value on error
86  @author woelk 08/2004 untested */
87  int Numeric(const std::vector<POLYNOMIALSOLVE_TYPE>& coeff,
88  std::vector<std::complex<POLYNOMIALSOLVE_TYPE> >& sol);
89 
90  /** @brief solves polynomial of arbitrary order n<=4 analytically
91  coeff[n]x^n+...+coeff[2]x^2+coeff[1]x+coeff[0]=0
92  coeff[n]!=0.0 is asserted.
93  @return number of real solutions, negative value on error
94  @author woelk 08/2004 untested */
95  int Analytic(const std::vector<POLYNOMIALSOLVE_TYPE>& coeff,
96  std::vector<POLYNOMIALSOLVE_TYPE>& sol);
97  /** @brief solves polynomial of arbitrary order n<=3 analytically
98  coeff[n]x^n+...+coeff[2]x^2+coeff[1]x+coeff[0]=0
99  coeff[n]!=0.0 is asserted.
100  @return number of complex solutions, negative value on error
101  @author woelk 08/2004 untested */
102  int Analytic(const std::vector<POLYNOMIALSOLVE_TYPE>& coeff,
103  std::vector<std::complex<POLYNOMIALSOLVE_TYPE> >& sol);
104 
105  /** @brief solve a polynomial of degree 1
106  coeff[1]*x+coeff[0]=0
107  coeff[1] != 0.0 is asserted
108  returns the number of real solutions (always 1)
109  @author koeser, woelk 08/2004 */
110  int Linear(const std::vector<POLYNOMIALSOLVE_TYPE>& coeff,
111  std::vector<POLYNOMIALSOLVE_TYPE>& sol);
112  /** @brief solve a polynomial of degree 1
113  coeff[1]*x+coeff[0]=0
114  coeff[1] != 0.0 is asserted
115  returns the number of complex solutions (always 1)
116  @author woelk 08/2004 */
117  int Linear(const std::vector<POLYNOMIALSOLVE_TYPE>& coeff,
118  std::vector<std::complex<POLYNOMIALSOLVE_TYPE> >& sol);
119 
120  /** @brief solve a polynomial of degree 2
121  coeff[2]*x^2+coeff[1]*x+coeff[0]=0
122  coeff[2] != 0.0 is asserted
123  returns the number of real solutions (0, 1 or 2)
124  @author koeser, woelk 08/2004
125  */
126  int Quadratic(const std::vector<POLYNOMIALSOLVE_TYPE>& coeff,
127  std::vector<POLYNOMIALSOLVE_TYPE>& sol);
128  /** @brief solve a polynomial of degree 2
129  coeff[2]*x^2+coeff[1]*x+coeff[0]=0
130  coeff[2] != 0.0 is asserted
131  returns the number of complex solutions (alway 2)
132  @author woelk 08/2004 */
133  int Quadratic(const std::vector<POLYNOMIALSOLVE_TYPE>& coeff,
134  std::vector<std::complex<POLYNOMIALSOLVE_TYPE> >& sol);
135 
136  /** @brief solve a polynomial of degree 3
137  coeff[3]*x^3+coeff[2]*x^2+coeff[1]*x+coeff[0]=0
138  coeff[3] != 0.0 is asserted
139  returns the number of real solutions
140  @author koeser, woelk 08/2004 */
141  int Cubic(const std::vector<POLYNOMIALSOLVE_TYPE>& coeff,
142  std::vector<POLYNOMIALSOLVE_TYPE>& sol);
143  /** @brief solve a polynomial of degree 3
144  coeff[3]*x^3+coeff[2]*x^2+coeff[1]*x+coeff[0]=0
145  coeff[3] != 0.0 is asserted
146  returns the number of real solutions
147  @author woelk 08/2004 */
148  int Cubic(const std::vector<POLYNOMIALSOLVE_TYPE>& coeff,
149  std::vector<std::complex<POLYNOMIALSOLVE_TYPE> >& sol);
150 
151  /** @brief solve a polynomial of degree 4
152  coeff[4]*x^4+coeff[3]*x^3+coeff[2]*x^2+coeff[1]*x+coeff[0]=0
153  coeff[4] != 0.0 is asserted
154  returns the number of real solutions
155  @author koeser, woelk 08/2004
156  ATTENTION: under certain circumstances Quartic() doesn't seem to work
157  correctly and does not return any solutions.
158  EXAMPLE : for the following polynom
159  coeff[0]=-5.3812376413659608331840900064;
160  coeff[1]=21.5206398747126961268349987222;
161  coeff[2]=-32.2795617934279306382450158708;
162  coeff[3]=21.5221584472618552297262795037;
163  coeff[4]=-5.38199880981732103890635698917;
164 
165  Quartic() does not return any roots.
166  Expected roots are:
167  0.999231378314545 + 0.030940956057273i
168  0.999231378314545 - 0.030940956057273i
169  1.004259532432780 + 0.000000000000000i
170  0.996476651583676 + 0.000000000000000i
171  */
172  int Quartic(const std::vector<POLYNOMIALSOLVE_TYPE>& coeff,
173  std::vector<POLYNOMIALSOLVE_TYPE>& sol);
174 
175  /** @brief removes leading zeros in coefficients
176  @author woelk 08/2004 */
177  void CheckCoefficients(std::vector<POLYNOMIALSOLVE_TYPE>& coeff,
178  double eps=DBL_EPSILON);
179 
180 
181  /** @brief inverse function, calculates coefficients from the solutions
182  @author woelk 08/2004 */
183  void CalCoefficients(const std::vector<POLYNOMIALSOLVE_TYPE>& sol,
184  std::vector<POLYNOMIALSOLVE_TYPE>& coeff);
185 
186  /** @brief numerically robust way to evaluate a polynomial at position x,
187  uses Horner scheme (same principle as in gsl_poly_eval)
188  @author koeser */
189  inline POLYNOMIALSOLVE_TYPE
190  EvaluatePolynomial(const POLYNOMIALSOLVE_TYPE x,
191  const std::vector<POLYNOMIALSOLVE_TYPE>& coeff) const;
192 
193  /** @brief determine number of real solutions of polynomial */
194  int GetNumberOfRealSolutions(const std::vector<POLYNOMIALSOLVE_TYPE>&
195  coeff);
196 
197  /** @brief determine whether the polynomial has a solution in IR */
198  bool HasRealSolution(const std::vector<POLYNOMIALSOLVE_TYPE>& coeff)
199  { return (GetNumberOfRealSolutions(coeff)>0); }
200 
201 
202  /** @brief does a non linear refinement using Powel from minpack
203  for real roots (non imaginary) only
204  @author woelk, koeser 08/2004 */
205  int NonLinearRefine(const std::vector<POLYNOMIALSOLVE_TYPE>& coeff,
206  std::vector<std::complex<POLYNOMIALSOLVE_TYPE> >& sol);
207 
208  /** @brief does a non linear refinement using Powel from minpack
209  for real roots (non imaginary) only
210  @author woelk, koeser 11/2007 */
211  int NonLinearRefine(const std::vector<POLYNOMIALSOLVE_TYPE>& coeff,
212  std::vector<POLYNOMIALSOLVE_TYPE>& sol);
213 
214  /** @brief given locations x and measurements y=f(x) approximate f by a
215  * polynomial of arbitrary degree and return coefficients
216  *
217  * least squares approximation of parameters a_i of a polynomial
218  * which minimizes (a_0 + a_1x + a_2x^2 + ... + a_degree x^degree - y)^2
219  * summed over all pairs (x;y), where i runs from 0 to degree
220  * @return 0 on success, <0 for degenerate situation, >0 optimizer error
221  * @author koeser 04/2007 */
222  int FitPolynomial(const unsigned int degree,
223  const std::vector<double>& x,
224  const std::vector<double>& y,
225  std::vector<double> &coefficients);
226 
227  public:
229  double *PowellCoeff_;
230 
231  protected:
232  /** helper function for CalCoefficients
233  @author woelk 08/2004 */
234  POLYNOMIALSOLVE_TYPE
235  _GetCoeff(int order, int b, const std::vector<POLYNOMIALSOLVE_TYPE>& sol);
236 
237  };
238 
239  //////////////////////////////////////////////////////////////////////
240  // inline implementation
241  //////////////////////////////////////////////////////////////////////
242 
243  inline POLYNOMIALSOLVE_TYPE
244  PolynomialSolve::EvaluatePolynomial(const POLYNOMIALSOLVE_TYPE x, const
245  std::vector<POLYNOMIALSOLVE_TYPE>& coeff) const
246  {
247  register int n = (int)coeff.size() - 1;
248  POLYNOMIALSOLVE_TYPE result = coeff[n--];
249  while (n>=0) result = result*x + coeff[n--];
250  return result;
251  }
252 
253 
254 } // end namespace
255 
256 #include <Base/Common/BIASpragmaEnd.hh>
257 
258 #endif
259 
260 
base class for solving polynomial equations
POLYNOMIALSOLVE_TYPE EvaluatePolynomial(const POLYNOMIALSOLVE_TYPE x, const std::vector< POLYNOMIALSOLVE_TYPE > &coeff) const
numerically robust way to evaluate a polynomial at position x, uses Horner scheme (same principle as ...
bool HasRealSolution(const std::vector< POLYNOMIALSOLVE_TYPE > &coeff)
determine whether the polynomial has a solution in IR