mxlib
c++ tools for analyzing astronomical data and other tasks by Jared R. Males. [git repo]
roots.hpp
Go to the documentation of this file.
1 /** \file roots.hpp
2  * \author Jared R. Males (jaredmales@gmail.com)
3  * \brief Declares and defines functions for finding roots
4  * \ingroup gen_math_files
5  *
6  */
7 
8 //***********************************************************************//
9 // Copyright 2015, 2016, 2017 Jared R. Males (jaredmales@gmail.com)
10 //
11 // This file is part of mxlib.
12 //
13 // mxlib is free software: you can redistribute it and/or modify
14 // it under the terms of the GNU General Public License as published by
15 // the Free Software Foundation, either version 3 of the License, or
16 // (at your option) any later version.
17 //
18 // mxlib is distributed in the hope that it will be useful,
19 // but WITHOUT ANY WARRANTY; without even the implied warranty of
20 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 // GNU General Public License for more details.
22 //
23 // You should have received a copy of the GNU General Public License
24 // along with mxlib. If not, see <http://www.gnu.org/licenses/>.
25 //***********************************************************************//
26 
27 #ifndef math_roots_hpp
28 #define math_roots_hpp
29 
30 #include <vector>
31 #include <complex>
32 #include <cmath>
33 
34 namespace mx
35 {
36 namespace math
37 {
38 
39  /// Calculate the descriminant for the general cubic
40 /**
41  * \returns the descriminant
42  */
43 template<typename realT>
44 realT cubicDescriminant( const realT & a, ///< [in] the 3rd order coefficient of the general cubic
45  const realT & b, ///< [in] the 2nd order coefficient of the general cubic
46  const realT & c, ///< [in] the 1st order coefficient of the general cubic
47  const realT & d ///< [in] the 0th order coefficient of the general cubic
48  )
49 {
50  return 18*a*b*c*d
51  - 4*b*b*b*d
52  + b*b*c*c
53  - 4*a*c*c*c
54  - 27*a*a*d*d;
55 }
56 
57 /// Calculate the descriminant for the depressed cubic
58 /**
59  * \returns the descriminant
60  */
61 template<typename realT>
62 realT cubicDescriminant( const realT & p, ///< [in] the 0th order coefficient of the depressed cubic
63  const realT & q ///< [in] the 0th order coefficient of the depressed cubic
64  )
65 {
66  return -1*(4*p*p*p + 27*q*q);
67 }
68 
69 /// Convert a general cubic equation to depressed form
70 /** The general cubic is
71  * \f[
72  * ax^3 + bx^2 + cx + d = 0
73  * \f]
74  * which can be converted to compressed form
75  * \f[
76  * t^3 + pt + q = 0
77  * \f]
78  *
79  */
80 template<typename realT>
81 void cubicDepressed( realT & p, ///< [out] the 1st order coefficient of the depressed cubic
82  realT & q, ///< [out] the 0th order coefficient of the depressed cubic
83  const realT & a, ///< [in] the 3rd order coefficient of the general cubic
84  const realT & b, ///< [in] the 2nd order coefficient of the general cubic
85  const realT & c, ///< [in] the 1st order coefficient of the general cubic
86  const realT & d ///< [in] the 0th order coefficient of the general cubic
87  )
88 {
89  p = (3*a*c-b*b)/(3*a*a);
90  q = (2*b*b*b-9*a*b*c+27*a*a*d)/(27*a*a*a);
91 }
92 
93 /// Calculate the real root for a depressed cubic with negative descriminant
94 /**
95  * \returns the real root for a depressed cubic defined by \p p and \p q
96  *
97  * \throws std::runtime_error if there are 3 real roots
98  *
99  */
100 template<typename realT>
101 realT cubicRealRoot( const realT & p, ///< [in] the 1st order coefficient of the depressed cubic
102  const realT & q ///< [in] the 0th order coefficient of the depressed cubic
103  )
104 {
105  realT D = q*q/4 + p*p*p/27;
106 
107  if(D < 0) throw std::runtime_error("cannot apply Cardano's formula, find roots using....");
108 
109  D = sqrt(D);
110 
111  realT u1 = -q/2 + D;
112  realT u2 = -q/2 - D;
113 
114  return std::cbrt(u1) + std::cbrt(u2);
115 }
116 
117 /// Find the roots of the general quartic equation
118 /** Finds the roots of
119  * \f[
120  f(x) = a x^4 + b x^3 + c x^2 + d x + e
121  \f]
122  * using the general formula for quartic roots. See https://en.wikipedia.org/wiki/Quartic_function.
123  *
124  * \tparam realT is the floating point type used for calculations.
125  *
126  * \ingroup gen_math
127  */
128 template<typename realT>
129 void quarticRoots( std::vector<std::complex<realT> > & x, ///< [out] On exit contains the 4 roots, is resized to length 4.
130  realT a, ///< [in] the coefficient of the \f$x^4\f$ term.
131  realT b, ///< [in] the coefficient of the \f$x^3\f$ term.
132  realT c, ///< [in] the coefficient of the \f$x^2\f$ term.
133  realT d, ///< [in] the coefficient of the \f$x^1\f$ term.
134  realT e ///< [in] the coefficient of the \f$x^0\f$ term.
135  )
136 {
137  std::complex<realT> p, q, S, Q, Delta0, Delta1;
138 
139  p = (8.0*a*c - 3.0*b*b)/(8.0*a*a);
140 
141  q = (b*b*b - 4.0*a*b*c + 8.0*a*a*d)/(8.0*a*a*a);
142 
143  Delta0 = c*c - 3.0*b*d + 12.0*a*e;
144  Delta1 = 2.0*c*c*c - 9.0*b*c*d + 27.0*b*b*e + 27.0*a*d*d - 72.0*a*c*e;
145 
146  Q = pow( static_cast<realT>(0.5)* (Delta1 + sqrt( Delta1*Delta1 - static_cast<realT>(4)*Delta0*Delta0*Delta0)), 1./3.);
147 
148  S = static_cast<realT>(0.5)*sqrt( - static_cast<realT>(2.0/3.0)*p + static_cast<realT>(1.0/(3.0*a))*(Q + Delta0/Q));
149 
150  x.resize(4);
151 
152  x[0] = -b/(4*a) - S + static_cast<realT>(0.5)*sqrt( static_cast<realT>(-4)*S*S - static_cast<realT>(2)*p + q/S);
153  x[1] = -b/(4*a) - S - static_cast<realT>(0.5)*sqrt( static_cast<realT>(-4)*S*S - static_cast<realT>(2)*p + q/S);
154  x[2] = -b/(4*a) + S + static_cast<realT>(0.5)*sqrt( static_cast<realT>(-4)*S*S - static_cast<realT>(2)*p - q/S);
155  x[3] = -b/(4*a) + S - static_cast<realT>(0.5)*sqrt( static_cast<realT>(-4)*S*S - static_cast<realT>(2)*p - q/S);
156 
157 } //quarticRoots
158 
159 } //namespace math
160 } //namespace mx
161 
162 #endif //math_roots_hpp
constexpr units::realT c()
The speed of light.
Definition: constants.hpp:60
void quarticRoots(std::vector< std::complex< realT > > &x, realT a, realT b, realT c, realT d, realT e)
Find the roots of the general quartic equation.
Definition: roots.hpp:129
The mxlib c++ namespace.
Definition: mxError.hpp:107
realT cubicRealRoot(const realT &p, const realT &q)
Calculate the real root for a depressed cubic with negative descriminant.
Definition: roots.hpp:101
realT cubicDescriminant(const realT &a, const realT &b, const realT &c, const realT &d)
Calculate the descriminant for the general cubic.
Definition: roots.hpp:44
void cubicDepressed(realT &p, realT &q, const realT &a, const realT &b, const realT &c, const realT &d)
Convert a general cubic equation to depressed form.
Definition: roots.hpp:81