PolynomialSolvers.h
1 /*
2  * Medical Image Registration ToolKit (MIRTK)
3  *
4  * Copyright 2016 Imperial College London
5  * Copyright 2016 Andreas Schuh
6  *
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  * http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  */
19 
20 #ifndef MIRTK_PolynomialSolvers_H
21 #define MIRTK_PolynomialSolvers_H
22 
23 #include "mirtk/Assert.h"
24 
25 // Forward declaration of Boost polynomial argument such that this
26 // source file does not require itself the Boost library
27 namespace boost { namespace math { namespace tools {
28 template <class T> class polynomial;
29 } } } // namespace boost::math::tools
30 
31 
32 namespace mirtk {
33 
34 
35 // =============================================================================
36 // Root finding
37 // =============================================================================
38 
39 //------------------------------------------------------------------------------
40 /// Compute roots of cubic polynomial
41 ///
42 /// This function solves the equation
43 ///
44 /// \f$x^3 + a x^2 + b x + c = 0/f$
45 ///
46 /// \param[out] x Solutions to the cubic equation.
47 /// \param[in] a Quadratic coefficient.
48 /// \param[in] b Linear coefficient.
49 /// \param[in] c Constant coefficient.
50 ///
51 /// \returns Number of real solutions.
52 ///
53 /// \retval 1 x[0] contains real solution, and
54 /// x1[1] +/- i x[2] is pair of complex conjugated roots.
55 /// \retval 2 First two x array entries are the real solutions.
56 /// \retval 3 All three x array entries contain the solutions.
57 ///
58 /// \sa https://www.easycalculation.com/algebra/learn-cubic-equation.php
59 int SolveCubicEquation(double x[3], double a, double b, double c);
60 
61 //------------------------------------------------------------------------------
62 /// Compute roots of cubic polynomial
63 ///
64 /// This function solves the equation
65 ///
66 /// \f$a x^3 + b x^2 + c x + d = 0/f$
67 ///
68 /// \param[out] x Solutions to the cubic equation.
69 /// \param[in] a Cubic coefficient.
70 /// \param[in] b Quadratic coefficient.
71 /// \param[in] c Linear coefficient.
72 /// \param[in] d Constant coefficient.
73 ///
74 /// \returns Number of real solutions.
75 ///
76 /// \retval 1 x[0] contains real solution, and
77 /// x1[1] +/- i x[2] is pair of complex conjugated roots.
78 /// \retval 2 First two x array entries are the real solutions.
79 /// \retval 3 All three x array entries contain the solutions.
80 ///
81 /// \sa https://www.easycalculation.com/algebra/learn-cubic-equation.php
82 inline int SolveCubicEquation(double x[3], double a, double b, double c, double d)
83 {
84  mirtkAssert(a != 0., "cubic coefficient is non-zero");
85  return SolveCubicEquation(x, b / a, c / a, d / a);
86 }
87 
88 //------------------------------------------------------------------------------
89 /// Compute roots of cubic polynomial
90 ///
91 /// This function solves the equation
92 ///
93 /// \f$a x^3 + b x^2 + c x + d = 0/f$
94 ///
95 /// \param[out] x Solutions to the cubic equation.
96 /// \param[in] p Cubic polynomial.
97 ///
98 /// \returns Number of real solutions.
99 ///
100 /// \retval 1 x[0] contains real solution, and
101 /// x1[1] +/- i x[2] is pair of complex conjugated roots.
102 /// \retval 2 First two x array entries are the real solutions.
103 /// \retval 3 All three x array entries contain the solutions.
104 ///
105 /// \sa https://www.easycalculation.com/algebra/learn-cubic-equation.php
106 template <class T>
107 inline int SolveCubicEquation(double x[3], const boost::math::tools::polynomial<T> &p)
108 {
109  mirtkAssert(p.degree() == 3, "polynomial degree must be 3");
110  mirtkAssert(double(p[3]) != 0., "cubic coefficient is non-zero");
111  return SolveCubicEquation(x, p[3], p[2], p[1], p[0]);
112 }
113 
114 // =============================================================================
115 // Minimization
116 // =============================================================================
117 
118 //------------------------------------------------------------------------------
119 /// Find minimum of 4th degree polynomial
120 ///
121 /// This function minimizes the polynomial function
122 ///
123 /// \f$x^4 + a x^3 + b x^2 + c x + d/f$
124 ///
125 /// \param[in] a Cubic coefficient.
126 /// \param[in] b Quadratic coefficient.
127 /// \param[in] c Linear coefficient.
128 ///
129 /// \returns Value for which function attains its minimum value.
130 double MinimumOf4thDegreePolynomial(double a, double b, double c);
131 
132 //------------------------------------------------------------------------------
133 /// Find minimum of 4th degree polynomial
134 ///
135 /// This function minimizes the polynomial function
136 ///
137 /// \f$x^4 + a x^3 + b x^2 + c x + d/f$
138 ///
139 /// \param[in] a Cubic coefficient.
140 /// \param[in] b Quadratic coefficient.
141 /// \param[in] c Linear coefficient.
142 /// \param[in] d Constant coefficient.
143 ///
144 /// \returns Value for which function attains its minimum value.
145 inline double MinimumOf4thDegreePolynomial(double a, double b, double c, double)
146 {
147  return MinimumOf4thDegreePolynomial(a, b, c);
148 }
149 
150 //------------------------------------------------------------------------------
151 /// Find minimum of 4th degree polynomial
152 ///
153 /// This function minimizes the polynomial function
154 ///
155 /// \f$a x^4 + b x^3 + c x^2 + d x + e/f$
156 ///
157 /// \param[in] a Quartic coefficient.
158 /// \param[in] b Cubic coefficient.
159 /// \param[in] c Quadratic coefficient.
160 /// \param[in] d Linear coefficient.
161 /// \param[in] e Constant coefficient.
162 ///
163 /// \returns Value for which function attains its minimum value.
164 inline double MinimumOf4thDegreePolynomial(double a, double b, double c, double d, double)
165 {
166  mirtkAssert(a != 0., "quartic coefficient is non-zero");
167  return MinimumOf4thDegreePolynomial(b / a, c / a, d / a);
168 }
169 
170 //------------------------------------------------------------------------------
171 /// Find minimum of 4th degree polynomial
172 ///
173 /// This function minimizes the polynomial function
174 ///
175 /// \f$a x^4 + b x^3 + c x^2 + d x + e/f$
176 ///
177 /// \param[in] p Quartic polynomial.
178 ///
179 /// \returns Value for which function attains its minimum value.
180 template <class T>
181 inline double MinimumOf4thDegreePolynomial(const boost::math::tools::polynomial<T> &p)
182 {
183  mirtkAssert(p.degree() == 4, "polynomial degree must be 4");
184  return MinimumOf4thDegreePolynomial(p[4], p[3], p[2], p[1], p[0]);
185 }
186 
187 
188 } // namespace mirtk
189 
190 #endif // MIRTK_PolynomialSolvers_H
Definition: IOConfig.h:41