20#ifndef POLYNOMIAL_ROOTS_HH
21#define POLYNOMIAL_ROOTS_HH
57#if POLYNOMIAL_ROOTS_HAS_MULTIPRECISION
58 #include <boost/multiprecision/cpp_bin_float.hpp>
59 #include <boost/math/special_functions/cbrt.hpp>
82 template <
typename... Args>
inline void root_assert(
bool cond, std::format_string<Args...> fmt, Args &&... args )
84 if ( !cond ) std::runtime_error( std::format( fmt, std::forward<Args>( args )... ) );
87#if POLYNOMIAL_ROOTS_HAS_MULTIPRECISION
89 using quad_real = boost::multiprecision::cpp_bin_float_100;
97#if POLYNOMIAL_ROOTS_HAS_MULTIPRECISION
100 struct formatter<
PolynomialRoots::quad_real, char> : formatter<std::string, char>
103 auto format( PolynomialRoots::quad_real
const & x, format_context & ctx )
const
105 std::ostringstream ss;
106 constexpr int digits = std::numeric_limits<PolynomialRoots::quad_real>::max_digits10 > 0
107 ? std::numeric_limits<PolynomialRoots::quad_real>::max_digits10
109 ss << std::setprecision( digits ) << x;
110 return formatter<std::string, char>::format( ss.str(), ctx );
133 template <
typename T_real> T_real
eval_poly( T_real
const op[],
integer Degree, T_real
const & x );
142 template <
typename T_real>
151 template <
typename T_real>
bool Newton_step( T_real
const op[],
integer Degree, T_real & x );
159 template <
typename T_real,
typename T_complex>
252 template <
typename T_real,
typename T_complex>
class QuadraticT
254 T_real m_ABC[3]{ 0, 0, 0 };
280 QuadraticT( T_real
const & a, T_real
const & b, T_real
const & c )
287 isfinite( a ) && isfinite( b ) && isfinite( c ),
288 "QuadraticT( a={}, b={}, c={} ) arguments must be finite!",
303 void setup( T_real
const & a, T_real
const & b, T_real
const & c )
419 T_complex
root0()
const {
return m_cplx ? T_complex( m_r0, m_r1 ) : T_complex( m_r0, 0 ); }
422 T_complex
root1()
const {
return m_cplx ? T_complex( m_r0, -m_r1 ) : T_complex( m_r1, 0 ); }
452 void get_root0( T_complex & r )
const { r = m_cplx ? T_complex( m_r0, m_r1 ) : T_complex( m_r0, 0 ); }
485 void get_root1( T_complex & r )
const { r = m_cplx ? T_complex( m_r0, -m_r1 ) : T_complex( m_r1, 0 ); }
498 case 0:
return root0();
499 case 1:
return root1();
553#if POLYNOMIAL_ROOTS_HAS_MULTIPRECISION
641 template <
typename T_real,
typename T_complex>
class CubicT
643 T_real m_ABCD[4]{ 0, 0, 0, 0 };
674 CubicT( T_real
const & a, T_real
const & b, T_real
const & c, T_real
const & d )
682 isfinite( a ) && isfinite( b ) && isfinite( c ) && isfinite( d ),
683 "CubicT( a={}, b={}, c={}, d={} ) arguments must be finite!",
698 void setup( T_real
const & a, T_real
const & b, T_real
const & c, T_real
const & d )
710 isfinite( a ) && isfinite( b ) && isfinite( c ) && isfinite( d ),
711 "CubicT::setup( a={}, b={}, c={}, d={} ) arguments must be finite!",
830 T_complex
root0()
const {
return m_cplx ? T_complex( m_r0, m_r1 ) : T_complex( m_r0, 0 ); }
835 T_complex
root1()
const {
return m_cplx ? T_complex( m_r0, -m_r1 ) : T_complex( m_r1, 0 ); }
840 T_complex
root2()
const {
return T_complex( m_r2, 0 ); }
865 void get_root0( T_complex & r )
const { r = m_cplx ? T_complex( m_r0, m_r1 ) : T_complex( m_r0, 0 ); }
893 void get_root1( T_complex & r )
const { r = m_cplx ? T_complex( m_r0, -m_r1 ) : T_complex( m_r1, 0 ); }
913 void get_root2( T_complex & r )
const { r = T_complex( m_r2, 0 ); }
926 case 0:
return root0();
927 case 1:
return root1();
928 case 2:
return root2();
981#if POLYNOMIAL_ROOTS_HAS_MULTIPRECISION
1073 template <
typename T_real,
typename T_complex>
class QuarticT
1075 T_real m_ABCDE[5]{ 0, 0, 0, 0, 0 };
1086 bool cplx0()
const {
return m_ncplx > 0; }
1087 bool cplx1()
const {
return m_ncplx > 0; }
1088 bool cplx2()
const {
return m_ncplx > 2; }
1089 bool cplx3()
const {
return m_ncplx > 2; }
1105 QuarticT( T_real
const & a, T_real
const & b, T_real
const & c, T_real
const & d, T_real
const & e )
1114 isfinite( a ) && isfinite( b ) && isfinite( c ) && isfinite( d ) && isfinite( e ),
1115 "QuarticT( a={}, b={}, c={}, d={}, e={} ) arguments must be finite!",
1131 void setup( T_real
const & a, T_real
const & b, T_real
const & c, T_real
const & d, T_real
const & e )
1143 isfinite( a ) && isfinite( b ) && isfinite( c ) && isfinite( d ) && isfinite( e ),
1144 "QuarticT::setup( a={}, b={}, c={}, d={}, e={} ) arguments must be finite!",
1264 T_complex
root0()
const {
return cplx0() ? T_complex( m_r0, m_r1 ) : T_complex( m_r0, 0 ); }
1269 T_complex
root1()
const {
return cplx1() ? T_complex( m_r0, -m_r1 ) : T_complex( m_r1, 0 ); }
1274 T_complex
root2()
const {
return cplx2() ? T_complex( m_r2, m_r3 ) : T_complex( m_r2, 0 ); }
1279 T_complex
root3()
const {
return cplx3() ? T_complex( m_r2, -m_r3 ) : T_complex( m_r3, 0 ); }
1307 r = T_complex( m_r0, m_r1 );
1309 r = T_complex( m_r0, 0 );
1341 r = T_complex( m_r0, -m_r1 );
1343 r = T_complex( m_r1, 0 );
1375 r = T_complex( m_r2, m_r3 );
1377 r = T_complex( m_r2, 0 );
1409 r = T_complex( m_r2, -m_r3 );
1411 r = T_complex( m_r3, 0 );
1425 case 0:
return root0();
1426 case 1:
return root1();
1427 case 2:
return root2();
1428 case 3:
return root3();
1482#if POLYNOMIAL_ROOTS_HAS_MULTIPRECISION
1501 template <
typename T_real>
1502 inline T_real
evalMonicCubic( T_real
const & x, T_real
const & a, T_real
const & b, T_real
const & c )
1540 ddp = 2 * ( x + dp );
1602 ddp = ddp * x + 2 * dp;
1606 ddp = ddp * x + 2 * dp;
Definition PolynomialRoots.hh:642
integer getNegativeRoots(T_real r[]) const
Alias of get_negative_roots().
Definition PolynomialRoots.hh:780
void getRoot2(T_real &re, T_real &im) const
Alias of get_root2().
Definition PolynomialRoots.hh:908
T_complex root0() const
Definition PolynomialRoots.hh:830
void get_root2(T_complex &r) const
Definition PolynomialRoots.hh:913
void setup(T_real const &a, T_real const &b, T_real const &c, T_real const &d)
Definition PolynomialRoots.hh:698
bool triple_root() const
Definition PolynomialRoots.hh:744
T_complex root(integer const i) const
Definition PolynomialRoots.hh:922
T_real eval(T_real const &x) const
Definition PolynomialRoots.hh:954
void get_root(integer const i, T_real &re, T_real &im) const
Definition PolynomialRoots.hh:938
void getRoot1(T_complex &r) const
Alias of get_root1().
Definition PolynomialRoots.hh:896
integer get_negative_roots(T_real r[]) const
Definition PolynomialRoots-2-Cubic.cc:72
bool complexRoot() const
Alias of complex_root().
Definition PolynomialRoots.hh:731
T_complex eval(T_complex const &x) const
Definition PolynomialRoots.hh:960
void getRoot0(T_complex &r) const
Alias of get_root0().
Definition PolynomialRoots.hh:868
void getRoot0(T_real &re, T_real &im) const
Alias of get_root0().
Definition PolynomialRoots.hh:860
T_real real_root2() const
Return the third stored real root.
Definition PolynomialRoots.hh:825
void get_root0(T_real &re, T_real &im) const
Definition PolynomialRoots.hh:845
void getRoot1(T_real &re, T_real &im) const
Alias of get_root1().
Definition PolynomialRoots.hh:888
void get_root1(T_real &re, T_real &im) const
Definition PolynomialRoots.hh:873
integer get_positive_roots(T_real r[]) const
Definition PolynomialRoots-2-Cubic.cc:55
void get_root2(T_real &re, T_real &im) const
Definition PolynomialRoots.hh:901
CubicT(T_real const &a, T_real const &b, T_real const &c, T_real const &d)
Definition PolynomialRoots.hh:674
void get_root0(T_complex &r) const
Definition PolynomialRoots.hh:865
void eval(T_real const &x, T_real &p, T_real &dp) const
Definition PolynomialRoots.hh:967
bool doubleRoot() const
Alias of double_root().
Definition PolynomialRoots.hh:739
integer getRootsInOpenRange(T_real const &a, T_real const &b, T_real r[]) const
Alias of get_roots_in_open_range().
Definition PolynomialRoots.hh:807
T_complex complex_type
Definition PolynomialRoots.hh:657
T_complex root2() const
Definition PolynomialRoots.hh:840
integer getRealRoots(T_real r[]) const
Alias of get_real_roots().
Definition PolynomialRoots.hh:758
integer numRoots() const
Alias of num_roots().
Definition PolynomialRoots.hh:723
void getRoot2(T_complex &r) const
Alias of get_root2().
Definition PolynomialRoots.hh:916
T_real value_type
Definition PolynomialRoots.hh:656
integer get_roots_in_open_range(T_real const &a, T_real const &b, T_real r[]) const
Definition PolynomialRoots-2-Cubic.cc:106
integer getPositiveRoots(T_real r[]) const
Alias of get_positive_roots().
Definition PolynomialRoots.hh:769
T_real real_root1() const
Definition PolynomialRoots.hh:822
integer get_roots_in_range(T_real const &a, T_real const &b, T_real r[]) const
Definition PolynomialRoots-2-Cubic.cc:89
bool complex_root() const
Definition PolynomialRoots.hh:728
integer num_roots() const
Definition PolynomialRoots.hh:720
T_real real_root0() const
Definition PolynomialRoots.hh:816
T_complex root1() const
Definition PolynomialRoots.hh:835
integer get_real_roots(T_real r[]) const
Definition PolynomialRoots-2-Cubic.cc:38
integer getRootsInRange(T_real const &a, T_real const &b, T_real r[]) const
Alias of get_roots_in_range().
Definition PolynomialRoots.hh:793
void info(ostream_type &s) const
Definition PolynomialRoots-2-Cubic.cc:538
bool double_root() const
Definition PolynomialRoots.hh:736
void get_root1(T_complex &r) const
Definition PolynomialRoots.hh:893
bool check(ostream_type &s) const
Definition PolynomialRoots-2-Cubic.cc:578
bool tripleRoot() const
Alias of triple_root().
Definition PolynomialRoots.hh:747
Definition PolynomialRoots.hh:253
void get_root0(T_real &re, T_real &im) const
Definition PolynomialRoots.hh:430
void get_root(integer const i, T_real &re, T_real &im) const
Definition PolynomialRoots.hh:509
integer getRealRoots(T_real r[]) const
Alias of get_real_roots().
Definition PolynomialRoots.hh:351
T_real value_type
Definition PolynomialRoots.hh:264
void get_root1(T_complex &r) const
Definition PolynomialRoots.hh:485
integer getRootsInRange(T_real const &a, T_real const &b, T_real r[]) const
Alias of get_roots_in_range().
Definition PolynomialRoots.hh:386
QuadraticT()=default
Build an empty quadratic solver instance.
integer get_negative_roots(T_real r[]) const
Definition PolynomialRoots-1-Quadratic.cc:53
void getRoot0(T_real &re, T_real &im) const
Alias of get_root0().
Definition PolynomialRoots.hh:445
void get_root0(T_complex &r) const
Definition PolynomialRoots.hh:452
void setup(T_real const &a, T_real const &b, T_real const &c)
Definition PolynomialRoots.hh:303
T_real eval(T_real const &x) const
Definition PolynomialRoots.hh:524
void getRoot0(T_complex &r) const
Alias of get_root0().
Definition PolynomialRoots.hh:455
integer numRoots() const
Alias of num_roots().
Definition PolynomialRoots.hh:324
bool complexRoot() const
Alias of complex_root().
Definition PolynomialRoots.hh:332
void getRoot1(T_real &re, T_real &im) const
Alias of get_root1().
Definition PolynomialRoots.hh:478
bool doubleRoot() const
Alias of double_root().
Definition PolynomialRoots.hh:340
T_real real_root0() const
Definition PolynomialRoots.hh:409
bool complex_root() const
Definition PolynomialRoots.hh:329
T_complex eval(T_complex const &x) const
Definition PolynomialRoots.hh:530
integer get_positive_roots(T_real r[]) const
Definition PolynomialRoots-1-Quadratic.cc:41
T_real real_root1() const
Definition PolynomialRoots.hh:416
integer getNegativeRoots(T_real r[]) const
Alias of get_negative_roots().
Definition PolynomialRoots.hh:373
integer get_roots_in_range(T_real const &a, T_real const &b, T_real r[]) const
Definition PolynomialRoots-1-Quadratic.cc:65
integer getPositiveRoots(T_real r[]) const
Alias of get_positive_roots().
Definition PolynomialRoots.hh:362
integer num_roots() const
Definition PolynomialRoots.hh:321
T_complex root1() const
Return the second root as a complex value.
Definition PolynomialRoots.hh:422
void get_root1(T_real &re, T_real &im) const
Definition PolynomialRoots.hh:463
integer get_real_roots(T_real r[]) const
Definition PolynomialRoots-1-Quadratic.cc:29
T_complex complex_type
Definition PolynomialRoots.hh:265
bool double_root() const
Definition PolynomialRoots.hh:337
integer get_roots_in_open_range(T_real const &a, T_real const &b, T_real r[]) const
Definition PolynomialRoots-1-Quadratic.cc:77
integer getRootsInOpenRange(T_real const &a, T_real const &b, T_real r[]) const
Alias of get_roots_in_open_range().
Definition PolynomialRoots.hh:400
bool check(ostream_type &s) const
Definition PolynomialRoots-1-Quadratic.cc:204
void getRoot1(T_complex &r) const
Alias of get_root1().
Definition PolynomialRoots.hh:488
T_complex root0() const
Return the first root as a complex value.
Definition PolynomialRoots.hh:419
QuadraticT(T_real const &a, T_real const &b, T_real const &c)
Definition PolynomialRoots.hh:280
T_complex root(integer const i) const
Definition PolynomialRoots.hh:494
void info(ostream_type &s) const
Definition PolynomialRoots-1-Quadratic.cc:168
void eval(T_real const &x, T_real &p, T_real &dp) const
Definition PolynomialRoots.hh:539
Definition PolynomialRoots.hh:1074
integer num_roots() const
Definition PolynomialRoots.hh:1153
QuarticT(T_real const &a, T_real const &b, T_real const &c, T_real const &d, T_real const &e)
Definition PolynomialRoots.hh:1105
void eval(T_real const &x, T_real &p, T_real &dp) const
Definition PolynomialRoots.hh:1468
integer get_roots_in_range(T_real const &a, T_real const &b, T_real r[]) const
Definition PolynomialRoots-3-Quartic.cc:65
void getRoot1(T_complex &r) const
Alias of get_root1().
Definition PolynomialRoots.hh:1347
integer get_negative_roots(T_real r[]) const
Definition PolynomialRoots-3-Quartic.cc:54
integer numRoots() const
Alias of num_roots().
Definition PolynomialRoots.hh:1156
void getRoot2(T_complex &r) const
Alias of get_root2().
Definition PolynomialRoots.hh:1381
void getRoot0(T_complex &r) const
Alias of get_root0().
Definition PolynomialRoots.hh:1313
integer getPositiveRoots(T_real r[]) const
Alias of get_positive_roots().
Definition PolynomialRoots.hh:1194
integer get_roots_in_open_range(T_real const &a, T_real const &b, T_real r[]) const
Definition PolynomialRoots-3-Quartic.cc:76
void get_root3(T_complex &r) const
Definition PolynomialRoots.hh:1406
T_complex complex_type
Definition PolynomialRoots.hh:1093
integer getRealRoots(T_real r[]) const
Alias of get_real_roots().
Definition PolynomialRoots.hh:1183
T_complex root3() const
Definition PolynomialRoots.hh:1279
void setup(T_real const &a, T_real const &b, T_real const &c, T_real const &d, T_real const &e)
Definition PolynomialRoots.hh:1131
void getRoot2(T_real &re, T_real &im) const
Alias of get_root2().
Definition PolynomialRoots.hh:1367
T_real real_root2() const
Definition PolynomialRoots.hh:1253
void getRoot3(T_real &re, T_real &im) const
Alias of get_root3().
Definition PolynomialRoots.hh:1401
void get_root1(T_complex &r) const
Definition PolynomialRoots.hh:1338
integer get_real_roots(T_real r[]) const
Definition PolynomialRoots-3-Quartic.cc:32
integer getRootsInRange(T_real const &a, T_real const &b, T_real r[]) const
Alias of get_roots_in_range().
Definition PolynomialRoots.hh:1218
integer numComplexRoots() const
Alias of num_complex_roots().
Definition PolynomialRoots.hh:1172
QuarticT()=default
Build an empty quartic solver instance.
integer num_real_roots() const
Definition PolynomialRoots.hh:1161
integer numRealRoots() const
Alias of num_real_roots().
Definition PolynomialRoots.hh:1164
T_real value_type
Definition PolynomialRoots.hh:1092
void get_root3(T_real &re, T_real &im) const
Definition PolynomialRoots.hh:1386
void getRoot0(T_real &re, T_real &im) const
Alias of get_root0().
Definition PolynomialRoots.hh:1299
T_complex root1() const
Definition PolynomialRoots.hh:1269
integer num_complex_roots() const
Definition PolynomialRoots.hh:1169
T_real real_root3() const
Definition PolynomialRoots.hh:1259
void getRoot1(T_real &re, T_real &im) const
Alias of get_root1().
Definition PolynomialRoots.hh:1333
T_complex eval(T_complex const &x) const
Definition PolynomialRoots.hh:1461
integer getNegativeRoots(T_real r[]) const
Alias of get_negative_roots().
Definition PolynomialRoots.hh:1205
T_complex root0() const
Definition PolynomialRoots.hh:1264
void get_root2(T_real &re, T_real &im) const
Definition PolynomialRoots.hh:1352
bool check(ostream_type &s) const
Definition PolynomialRoots-3-Quartic.cc:894
T_real real_root0() const
Definition PolynomialRoots.hh:1241
void get_root0(T_complex &r) const
Definition PolynomialRoots.hh:1304
integer get_positive_roots(T_real r[]) const
Definition PolynomialRoots-3-Quartic.cc:43
void getRoot3(T_complex &r) const
Alias of get_root3().
Definition PolynomialRoots.hh:1415
T_complex root2() const
Definition PolynomialRoots.hh:1274
integer getRootsInOpenRange(T_real const &a, T_real const &b, T_real r[]) const
Alias of get_roots_in_open_range().
Definition PolynomialRoots.hh:1232
void get_root0(T_real &re, T_real &im) const
Definition PolynomialRoots.hh:1284
T_real eval(T_real const &x) const
Definition PolynomialRoots.hh:1455
void get_root(integer const i, T_real &re, T_real &im) const
Definition PolynomialRoots.hh:1438
void get_root2(T_complex &r) const
Definition PolynomialRoots.hh:1372
T_complex root(integer const i) const
Definition PolynomialRoots.hh:1421
void get_root1(T_real &re, T_real &im) const
Definition PolynomialRoots.hh:1318
void info(ostream_type &s) const
Definition PolynomialRoots-3-Quartic.cc:847
T_real real_root1() const
Definition PolynomialRoots.hh:1247
Definition PolynomialRoots-1-Quadratic.cc:23
void root_assert(bool cond, std::format_string< Args... > fmt, Args &&... args)
Definition PolynomialRoots.hh:82
T_complex eval_poly_complex(T_real const op[], integer const Degree, T_complex const &x)
Definition PolynomialRoots-Utils.cc:184
int integer
Integer type used for degrees, counts and indices.
Definition PolynomialRoots.hh:68
T_real eval_poly(T_real const op[], integer const Degree, T_real const &x)
Definition PolynomialRoots-Utils.cc:44
constexpr integer MAXDEGREE
Maximum degree accepted by the Jenkins-Traub entry point.
Definition PolynomialRoots.hh:75
QuadraticT< real_type, real_complex > Quadratic
Definition PolynomialRoots.hh:552
std::basic_ostream< char > ostream_type
Output stream type used by diagnostic methods.
Definition PolynomialRoots.hh:70
real_type machepsiT()
Definition PolynomialRoots-Utils.cc:25
bool Newton_step(T_real const op[], integer const Degree, T_real &x)
Definition PolynomialRoots-Utils.cc:80
void eval_poly_Dpoly(T_real const op[], integer const Degree, T_real const &x, T_real &p, T_real &dp)
Definition PolynomialRoots-Utils.cc:136
CubicT< real_type, real_complex > Cubic
Definition PolynomialRoots.hh:980
T_real evalMonicCubic(T_real const &x, T_real const &a, T_real const &b, T_real const &c)
Definition PolynomialRoots.hh:1502
std::basic_istream< char > istream_type
Input stream type reserved for formatted input helpers.
Definition PolynomialRoots.hh:72
QuarticT< real_type, real_complex > Quartic
Definition PolynomialRoots.hh:1481
T_real evalMonicQuartic(T_real const &x, T_real const &a, T_real const &b, T_real const &c, T_real const &d)
Evaluate a monic quartic polynomial.
Definition PolynomialRoots.hh:1546
double real_type
Scalar type used by the standard-precision API.
Definition PolynomialRoots.hh:66
int roots(real_type const *op, integer const Degree, real_type *zeror, real_type *zeroi)
Definition PolynomialRoots-Jenkins-Traub.cc:703
real_type toleranceT()
Definition PolynomialRoots-Utils.cc:29
Definition PolynomialRoots.hh:95