Quartic roots
Utilities for C++ programming
Loading...
Searching...
No Matches
PolynomialRoots.hh
Go to the documentation of this file.
1/*--------------------------------------------------------------------------*\
2 | |
3 | Copyright (C) 2014 |
4 | |
5 | , __ , __ |
6 | /|/ \ /|/ \ |
7 | | __/ _ ,_ | __/ _ ,_ |
8 | | \|/ / | | | | \|/ / | | | |
9 | |(__/|__/ |_/ \_/|/|(__/|__/ |_/ \_/|/ |
10 | /| /| |
11 | \| \| |
12 | |
13 | Enrico Bertolazzi |
14 | Dipartimento di Ingegneria Industriale |
15 | Università degli Studi di Trento |
16 | email: enrico.bertolazzi@unitn.it |
17 | |
18\*--------------------------------------------------------------------------*/
19
20#ifndef POLYNOMIAL_ROOTS_HH
21#define POLYNOMIAL_ROOTS_HH
22
23#include <cmath>
24#include <cfloat>
25#include <iostream>
26
27#include <complex>
28#include <cstdint>
29#include <format>
30#include <iomanip>
31#include <iosfwd>
32#include <limits>
33#include <sstream>
34#include <string>
35
56
57#if POLYNOMIAL_ROOTS_HAS_MULTIPRECISION
58 #include <boost/multiprecision/cpp_bin_float.hpp>
59 #include <boost/math/special_functions/cbrt.hpp>
60#endif
61
62namespace PolynomialRoots
63{
64
66 using real_type = double;
68 using integer = int;
70 using ostream_type = std::basic_ostream<char>;
72 using istream_type = std::basic_istream<char>;
73
75 inline constexpr integer MAXDEGREE = 100;
76
82 template <typename... Args> inline void root_assert( bool cond, std::format_string<Args...> fmt, Args &&... args )
83 {
84 if ( !cond ) std::runtime_error( std::format( fmt, std::forward<Args>( args )... ) );
85 }
86
87#if POLYNOMIAL_ROOTS_HAS_MULTIPRECISION
89 using quad_real = boost::multiprecision::cpp_bin_float_100;
90#endif
91
92} // namespace PolynomialRoots
93
94namespace std
95{
96
97#if POLYNOMIAL_ROOTS_HAS_MULTIPRECISION
98 template <>
99
100 struct formatter<PolynomialRoots::quad_real, char> : formatter<std::string, char>
101
102 {
103 auto format( PolynomialRoots::quad_real const & x, format_context & ctx ) const
104 {
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
108 : 36;
109 ss << std::setprecision( digits ) << x;
110 return formatter<std::string, char>::format( ss.str(), ctx );
111 }
112 };
113#endif
114} // namespace std
115
117
118namespace PolynomialRoots
119{
120 using std::isfinite;
121
123 template <typename T_real> T_real machepsiT();
125 template <typename T_real> T_real toleranceT();
126
133 template <typename T_real> T_real eval_poly( T_real const op[], integer Degree, T_real const & x );
134
142 template <typename T_real>
143 void eval_poly_Dpoly( T_real const op[], integer Degree, T_real const & x, T_real & p, T_real & dp );
144
151 template <typename T_real> bool Newton_step( T_real const op[], integer Degree, T_real & x );
152
159 template <typename T_real, typename T_complex>
160 T_complex eval_poly_complex( T_real const op[], integer Degree, T_complex const & x );
161
172 [[nodiscard]] int roots( real_type const * op, integer Degree, real_type * zeror, real_type * zeroi );
173
174 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
175 /*\
176 | ___ _ _ _
177 | / _ \ _ _ __ _ __| |_ __ __ _| |_(_) ___
178 | | | | | | | |/ _` |/ _` | '__/ _` | __| |/ __|
179 | | |_| | |_| | (_| | (_| | | | (_| | |_| | (__
180 | \__\_\\__,_|\__,_|\__,_|_| \__,_|\__|_|\___|
181 |
182 | A * x^2 + B * x + C
183 \*/
252 template <typename T_real, typename T_complex> class QuadraticT
253 {
254 T_real m_ABC[3]{ 0, 0, 0 };
255 T_real m_r0 = 0;
256 T_real m_r1 = 0;
257 integer m_nrts = 0;
258 bool m_cplx = false;
259 bool m_dblx = false;
260
261 void find_roots();
262
263 public:
264 using value_type = T_real;
265 using complex_type = T_complex;
266
268 QuadraticT() = default;
269
280 QuadraticT( T_real const & a, T_real const & b, T_real const & c )
281 {
282 m_ABC[0] = a;
283 m_ABC[1] = b;
284 m_ABC[2] = c;
285 // find roots only on finite values
287 isfinite( a ) && isfinite( b ) && isfinite( c ),
288 "QuadraticT( a={}, b={}, c={} ) arguments must be finite!",
289 a, b, c
290 );
291 find_roots();
292 }
293
303 void setup( T_real const & a, T_real const & b, T_real const & c )
304 {
305 m_ABC[0] = a;
306 m_ABC[1] = b;
307 m_ABC[2] = c;
308 find_roots();
309 }
310
321 integer num_roots() const { return m_nrts; }
322
324 integer numRoots() const { return m_nrts; }
325
329 bool complex_root() const { return m_cplx; }
330
332 bool complexRoot() const { return m_cplx; }
333
337 bool double_root() const { return m_dblx; }
338
340 bool doubleRoot() const { return m_dblx; }
341
348 integer get_real_roots( T_real r[] ) const;
349
351 integer getRealRoots( T_real r[] ) const { return get_real_roots( r ); }
352
359 integer get_positive_roots( T_real r[] ) const;
360
362 integer getPositiveRoots( T_real r[] ) const { return get_positive_roots( r ); }
363
370 integer get_negative_roots( T_real r[] ) const;
371
373 integer getNegativeRoots( T_real r[] ) const { return get_negative_roots( r ); }
374
383 integer get_roots_in_range( T_real const & a, T_real const & b, T_real r[] ) const;
384
386 integer getRootsInRange( T_real const & a, T_real const & b, T_real r[] ) const
387 { return get_roots_in_range( a, b, r ); }
388
397 integer get_roots_in_open_range( T_real const & a, T_real const & b, T_real r[] ) const;
398
400 integer getRootsInOpenRange( T_real const & a, T_real const & b, T_real r[] ) const
401 { return get_roots_in_open_range( a, b, r ); }
402
409 T_real real_root0() const { return m_r0; }
410
416 T_real real_root1() const { return m_r1; }
417
419 T_complex root0() const { return m_cplx ? T_complex( m_r0, m_r1 ) : T_complex( m_r0, 0 ); }
420
422 T_complex root1() const { return m_cplx ? T_complex( m_r0, -m_r1 ) : T_complex( m_r1, 0 ); }
423
430 void get_root0( T_real & re, T_real & im ) const
431 {
432 if ( m_cplx )
433 {
434 re = m_r0;
435 im = m_r1;
436 }
437 else
438 {
439 re = m_r0;
440 im = 0;
441 }
442 }
443
445 void getRoot0( T_real & re, T_real & im ) const { return get_root0( re, im ); }
446
452 void get_root0( T_complex & r ) const { r = m_cplx ? T_complex( m_r0, m_r1 ) : T_complex( m_r0, 0 ); }
453
455 void getRoot0( T_complex & r ) const { return get_root0( r ); }
456
463 void get_root1( T_real & re, T_real & im ) const
464 {
465 if ( m_cplx )
466 {
467 re = m_r0;
468 im = -m_r1;
469 }
470 else
471 {
472 re = m_r1;
473 im = 0;
474 }
475 }
476
478 void getRoot1( T_real & re, T_real & im ) const { return get_root1( re, im ); }
479
485 void get_root1( T_complex & r ) const { r = m_cplx ? T_complex( m_r0, -m_r1 ) : T_complex( m_r1, 0 ); }
486
488 void getRoot1( T_complex & r ) const { return get_root1( r ); }
489
494 T_complex root( integer const i ) const
495 {
496 switch ( i )
497 {
498 case 0: return root0();
499 case 1: return root1();
500 }
501 return 0;
502 }
503
509 void get_root( integer const i, T_real & re, T_real & im ) const
510 {
511 switch ( i )
512 {
513 case 0: return get_root0( re, im );
514 case 1: return get_root1( re, im );
515 }
516 }
517
524 T_real eval( T_real const & x ) const { return eval_poly<T_real>( m_ABC, 2, x ); }
525
530 T_complex eval( T_complex const & x ) const { return eval_poly_complex<T_real, T_complex>( m_ABC, 2, x ); }
531
539 void eval( T_real const & x, T_real & p, T_real & dp ) const { eval_poly_Dpoly<T_real>( m_ABC, 2, x, p, dp ); }
540
544 void info( ostream_type & s ) const;
545
549 [[nodiscard]] bool check( ostream_type & s ) const;
550 };
551
553#if POLYNOMIAL_ROOTS_HAS_MULTIPRECISION
554 using QuadraticHQ = QuadraticT<quad_real, quad_complex>;
555#endif
556
557 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
558 /*\
559 | ____ _ _
560 | / ___| _| |__ (_) ___
561 | | | | | | | '_ \| |/ __|
562 | | |__| |_| | |_) | | (__
563 | \____\__,_|_.__/|_|\___|
564 |
565 | A * x^3 + B * x^2 + C * x + D
566 \*/
641 template <typename T_real, typename T_complex> class CubicT
642 {
643 T_real m_ABCD[4]{ 0, 0, 0, 0 };
644 T_real m_r0 = 0;
645 T_real m_r1 = 0;
646 T_real m_r2 = 0;
647 integer m_nrts = 0;
648 integer m_iter = 0;
649 bool m_cplx = false; // complex root
650 bool m_dblx = false; // double root
651 bool m_trpx = false; // triple root
652
653 void find_roots();
654
655 public:
656 using value_type = T_real;
657 using complex_type = T_complex;
658
663 CubicT() = default;
664
674 CubicT( T_real const & a, T_real const & b, T_real const & c, T_real const & d )
675 {
676 m_ABCD[0] = a;
677 m_ABCD[1] = b;
678 m_ABCD[2] = c;
679 m_ABCD[3] = d;
680 // find roots only on finite values
682 isfinite( a ) && isfinite( b ) && isfinite( c ) && isfinite( d ),
683 "CubicT( a={}, b={}, c={}, d={} ) arguments must be finite!",
684 a, b, c, d
685 );
686 find_roots();
687 }
688
698 void setup( T_real const & a, T_real const & b, T_real const & c, T_real const & d )
699 {
700 m_ABCD[0] = a;
701 m_ABCD[1] = b;
702 m_ABCD[2] = c;
703 m_ABCD[3] = d;
704 m_nrts = 0;
705 m_iter = 0;
706 m_cplx = false; // complex root
707 m_dblx = false; // double root
708 m_trpx = false; // triple root
710 isfinite( a ) && isfinite( b ) && isfinite( c ) && isfinite( d ),
711 "CubicT::setup( a={}, b={}, c={}, d={} ) arguments must be finite!",
712 a, b, c, d
713 );
714 find_roots();
715 }
716
720 integer num_roots() const { return m_nrts; }
721
723 integer numRoots() const { return m_nrts; }
724
728 bool complex_root() const { return m_cplx; }
729
731 bool complexRoot() const { return m_cplx; }
732
736 bool double_root() const { return m_dblx; }
737
739 bool doubleRoot() const { return m_dblx; }
740
744 bool triple_root() const { return m_trpx; }
745
747 bool tripleRoot() const { return m_trpx; }
748
755 integer get_real_roots( T_real r[] ) const;
756
758 integer getRealRoots( T_real r[] ) const { return get_real_roots( r ); }
759
766 integer get_positive_roots( T_real r[] ) const;
767
769 integer getPositiveRoots( T_real r[] ) const { return get_positive_roots( r ); }
770
777 integer get_negative_roots( T_real r[] ) const;
778
780 integer getNegativeRoots( T_real r[] ) const { return get_negative_roots( r ); }
781
790 integer get_roots_in_range( T_real const & a, T_real const & b, T_real r[] ) const;
791
793 integer getRootsInRange( T_real const & a, T_real const & b, T_real r[] ) const
794 { return get_roots_in_range( a, b, r ); }
795
804 integer get_roots_in_open_range( T_real const & a, T_real const & b, T_real r[] ) const;
805
807 integer getRootsInOpenRange( T_real const & a, T_real const & b, T_real r[] ) const
808 { return get_roots_in_open_range( a, b, r ); }
809
816 T_real real_root0() const { return m_r0; }
817
822 T_real real_root1() const { return m_r1; }
823
825 T_real real_root2() const { return m_r2; }
826
830 T_complex root0() const { return m_cplx ? T_complex( m_r0, m_r1 ) : T_complex( m_r0, 0 ); }
831
835 T_complex root1() const { return m_cplx ? T_complex( m_r0, -m_r1 ) : T_complex( m_r1, 0 ); }
836
840 T_complex root2() const { return T_complex( m_r2, 0 ); }
841
845 void get_root0( T_real & re, T_real & im ) const
846 {
847 if ( m_cplx )
848 {
849 re = m_r0;
850 im = m_r1;
851 }
852 else
853 {
854 re = m_r0;
855 im = 0;
856 }
857 }
858
860 void getRoot0( T_real & re, T_real & im ) const { get_root0( re, im ); }
861
865 void get_root0( T_complex & r ) const { r = m_cplx ? T_complex( m_r0, m_r1 ) : T_complex( m_r0, 0 ); }
866
868 void getRoot0( T_complex & r ) const { get_root0( r ); }
869
873 void get_root1( T_real & re, T_real & im ) const
874 {
875 if ( m_cplx )
876 {
877 re = m_r0;
878 im = -m_r1;
879 }
880 else
881 {
882 re = m_r1;
883 im = 0;
884 }
885 }
886
888 void getRoot1( T_real & re, T_real & im ) const { get_root1( re, im ); }
889
893 void get_root1( T_complex & r ) const { r = m_cplx ? T_complex( m_r0, -m_r1 ) : T_complex( m_r1, 0 ); }
894
896 void getRoot1( T_complex & r ) const { get_root1( r ); }
897
901 void get_root2( T_real & re, T_real & im ) const
902 {
903 re = m_r2;
904 im = 0;
905 }
906
908 void getRoot2( T_real & re, T_real & im ) const { get_root2( re, im ); }
909
913 void get_root2( T_complex & r ) const { r = T_complex( m_r2, 0 ); }
914
916 void getRoot2( T_complex & r ) const { get_root2( r ); }
917
922 T_complex root( integer const i ) const
923 {
924 switch ( i )
925 {
926 case 0: return root0();
927 case 1: return root1();
928 case 2: return root2();
929 }
930 return 0;
931 }
932
938 void get_root( integer const i, T_real & re, T_real & im ) const
939 {
940 switch ( i )
941 {
942 case 0: return get_root0( re, im );
943 case 1: return get_root1( re, im );
944 case 2: return get_root2( re, im );
945 }
946 }
947
954 T_real eval( T_real const & x ) const { return eval_poly<T_real>( m_ABCD, 3, x ); }
955
960 T_complex eval( T_complex const & x ) const { return eval_poly_complex<T_real, T_complex>( m_ABCD, 3, x ); }
961
967 void eval( T_real const & x, T_real & p, T_real & dp ) const { eval_poly_Dpoly<T_real>( m_ABCD, 3, x, p, dp ); }
968
972 void info( ostream_type & s ) const;
973
977 [[nodiscard]] bool check( ostream_type & s ) const;
978 };
979
981#if POLYNOMIAL_ROOTS_HAS_MULTIPRECISION
982 using CubicHQ = CubicT<quad_real, quad_complex>;
983#endif
984
985 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
986 /*\
987 | ___ _ _
988 | / _ \ _ _ __ _ _ __| |_(_) ___
989 | | | | | | | |/ _` | '__| __| |/ __|
990 | | |_| | |_| | (_| | | | |_| | (__
991 | \__\_\\__,_|\__,_|_| \__|_|\___|
992 |
993 | A * x^4 + B * x^3 + C * x^2 + D * x + E
994 \*/
1073 template <typename T_real, typename T_complex> class QuarticT
1074 {
1075 T_real m_ABCDE[5]{ 0, 0, 0, 0, 0 };
1076 T_real m_r0 = 0;
1077 T_real m_r1 = 0;
1078 T_real m_r2 = 0;
1079 T_real m_r3 = 0;
1080 integer m_iter = 0;
1081 integer m_nreal = 0;
1082 integer m_ncplx = 0;
1083
1084 void find_roots();
1085
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; }
1090
1091 public:
1092 using value_type = T_real;
1093 using complex_type = T_complex;
1094
1096 QuarticT() = default;
1097
1105 QuarticT( T_real const & a, T_real const & b, T_real const & c, T_real const & d, T_real const & e )
1106 {
1107 m_ABCDE[0] = a;
1108 m_ABCDE[1] = b;
1109 m_ABCDE[2] = c;
1110 m_ABCDE[3] = d;
1111 m_ABCDE[4] = e;
1112 // find roots only on finite values
1114 isfinite( a ) && isfinite( b ) && isfinite( c ) && isfinite( d ) && isfinite( e ),
1115 "QuarticT( a={}, b={}, c={}, d={}, e={} ) arguments must be finite!",
1116 a, b, c, d, e
1117 );
1118 find_roots();
1119 }
1120
1131 void setup( T_real const & a, T_real const & b, T_real const & c, T_real const & d, T_real const & e )
1132 {
1133 m_ABCDE[0] = a;
1134 m_ABCDE[1] = b;
1135 m_ABCDE[2] = c;
1136 m_ABCDE[3] = d;
1137 m_ABCDE[4] = e;
1138 m_iter = 0;
1139 m_nreal = 0;
1140 m_ncplx = 0;
1141 // find roots only on finite values
1143 isfinite( a ) && isfinite( b ) && isfinite( c ) && isfinite( d ) && isfinite( e ),
1144 "QuarticT::setup( a={}, b={}, c={}, d={}, e={} ) arguments must be finite!",
1145 a, b, c, d, e
1146 );
1147 find_roots();
1148 }
1149
1153 integer num_roots() const { return m_nreal + m_ncplx; }
1154
1156 integer numRoots() const { return m_nreal + m_ncplx; }
1157
1161 integer num_real_roots() const { return m_nreal; }
1162
1164 integer numRealRoots() const { return m_nreal; }
1165
1169 integer num_complex_roots() const { return m_ncplx; }
1170
1172 integer numComplexRoots() const { return m_ncplx; }
1173
1180 integer get_real_roots( T_real r[] ) const;
1181
1183 integer getRealRoots( T_real r[] ) const { return get_real_roots( r ); }
1184
1191 integer get_positive_roots( T_real r[] ) const;
1192
1194 integer getPositiveRoots( T_real r[] ) const { return get_positive_roots( r ); }
1195
1202 integer get_negative_roots( T_real r[] ) const;
1203
1205 integer getNegativeRoots( T_real r[] ) const { return get_negative_roots( r ); }
1206
1215 integer get_roots_in_range( T_real const & a, T_real const & b, T_real r[] ) const;
1216
1218 integer getRootsInRange( T_real const & a, T_real const & b, T_real r[] ) const
1219 { return get_roots_in_range( a, b, r ); }
1220
1229 integer get_roots_in_open_range( T_real const & a, T_real const & b, T_real r[] ) const;
1230
1232 integer getRootsInOpenRange( T_real const & a, T_real const & b, T_real r[] ) const
1233 { return get_roots_in_open_range( a, b, r ); }
1234
1241 T_real real_root0() const { return m_r0; }
1242
1247 T_real real_root1() const { return m_r1; }
1248
1253 T_real real_root2() const { return m_r2; }
1254
1259 T_real real_root3() const { return m_r3; }
1260
1264 T_complex root0() const { return cplx0() ? T_complex( m_r0, m_r1 ) : T_complex( m_r0, 0 ); }
1265
1269 T_complex root1() const { return cplx1() ? T_complex( m_r0, -m_r1 ) : T_complex( m_r1, 0 ); }
1270
1274 T_complex root2() const { return cplx2() ? T_complex( m_r2, m_r3 ) : T_complex( m_r2, 0 ); }
1275
1279 T_complex root3() const { return cplx3() ? T_complex( m_r2, -m_r3 ) : T_complex( m_r3, 0 ); }
1280
1284 void get_root0( T_real & re, T_real & im ) const
1285 {
1286 if ( cplx0() )
1287 {
1288 re = m_r0;
1289 im = m_r1;
1290 }
1291 else
1292 {
1293 re = m_r0;
1294 im = 0;
1295 }
1296 }
1297
1299 void getRoot0( T_real & re, T_real & im ) const { get_root0( re, im ); }
1300
1304 void get_root0( T_complex & r ) const
1305 {
1306 if ( cplx0() )
1307 r = T_complex( m_r0, m_r1 );
1308 else
1309 r = T_complex( m_r0, 0 );
1310 }
1311
1313 void getRoot0( T_complex & r ) const { get_root0( r ); }
1314
1318 void get_root1( T_real & re, T_real & im ) const
1319 {
1320 if ( cplx1() )
1321 {
1322 re = m_r0;
1323 im = -m_r1;
1324 }
1325 else
1326 {
1327 re = m_r1;
1328 im = 0;
1329 }
1330 }
1331
1333 void getRoot1( T_real & re, T_real & im ) const { get_root1( re, im ); }
1334
1338 void get_root1( T_complex & r ) const
1339 {
1340 if ( cplx1() )
1341 r = T_complex( m_r0, -m_r1 );
1342 else
1343 r = T_complex( m_r1, 0 );
1344 }
1345
1347 void getRoot1( T_complex & r ) const { get_root1( r ); }
1348
1352 void get_root2( T_real & re, T_real & im ) const
1353 {
1354 if ( cplx2() )
1355 {
1356 re = m_r2;
1357 im = m_r3;
1358 }
1359 else
1360 {
1361 re = m_r2;
1362 im = 0;
1363 }
1364 }
1365
1367 void getRoot2( T_real & re, T_real & im ) const { get_root2( re, im ); }
1368
1372 void get_root2( T_complex & r ) const
1373 {
1374 if ( cplx2() )
1375 r = T_complex( m_r2, m_r3 );
1376 else
1377 r = T_complex( m_r2, 0 );
1378 }
1379
1381 void getRoot2( T_complex & r ) const { get_root2( r ); }
1382
1386 void get_root3( T_real & re, T_real & im ) const
1387 {
1388 if ( cplx3() )
1389 {
1390 re = m_r2;
1391 im = -m_r3;
1392 }
1393 else
1394 {
1395 re = m_r3;
1396 im = 0;
1397 }
1398 }
1399
1401 void getRoot3( T_real & re, T_real & im ) const { get_root3( re, im ); }
1402
1406 void get_root3( T_complex & r ) const
1407 {
1408 if ( cplx3() )
1409 r = T_complex( m_r2, -m_r3 );
1410 else
1411 r = T_complex( m_r3, 0 );
1412 }
1413
1415 void getRoot3( T_complex & r ) const { get_root3( r ); }
1416
1421 T_complex root( integer const i ) const
1422 {
1423 switch ( i )
1424 {
1425 case 0: return root0();
1426 case 1: return root1();
1427 case 2: return root2();
1428 case 3: return root3();
1429 }
1430 return 0;
1431 }
1432
1438 void get_root( integer const i, T_real & re, T_real & im ) const
1439 {
1440 switch ( i )
1441 {
1442 case 0: return get_root0( re, im );
1443 case 1: return get_root1( re, im );
1444 case 2: return get_root2( re, im );
1445 case 3: return get_root3( re, im );
1446 }
1447 }
1448
1455 T_real eval( T_real const & x ) const { return eval_poly<T_real>( m_ABCDE, 4, x ); }
1456
1461 T_complex eval( T_complex const & x ) const { return eval_poly_complex<T_real, T_complex>( m_ABCDE, 4, x ); }
1462
1468 void eval( T_real const & x, T_real & p, T_real & dp ) const { eval_poly_Dpoly<T_real>( m_ABCDE, 4, x, p, dp ); }
1469
1473 void info( ostream_type & s ) const;
1474
1478 [[nodiscard]] bool check( ostream_type & s ) const;
1479 };
1480
1482#if POLYNOMIAL_ROOTS_HAS_MULTIPRECISION
1483 using QuarticHQ = QuarticT<quad_real, quad_complex>;
1484#endif
1485
1486 /*\
1487 | _ _ _ _ _
1488 | | | | | |_(_) |___
1489 | | | | | __| | / __|
1490 | | |_| | |_| | \__ \
1491 | \___/ \__|_|_|___/
1492 \*/
1493
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 )
1503 {
1504 T_real p;
1505 p = x + a;
1506 p = p * x + b;
1507 p = p * x + c;
1508 return p;
1509 }
1510
1512 template <typename T_real> inline void evalMonicCubic(
1513 T_real const & x,
1514 T_real const & a,
1515 T_real const & b,
1516 T_real const & c,
1517 T_real & p,
1518 T_real & dp )
1519 {
1520 p = x + a;
1521 dp = x + p;
1522 p = p * x + b;
1523 dp = dp * x + p;
1524 p = p * x + c;
1525 }
1526
1528 template <typename T_real> inline void evalMonicCubic(
1529 T_real const & x,
1530 T_real const & a,
1531 T_real const & b,
1532 T_real const & c,
1533 T_real & p,
1534 T_real & dp,
1535 T_real & ddp )
1536 {
1537 p = x + a;
1538 dp = x + p; // 2*x + a
1539 p = p * x + b; // x^2 + a * x + b
1540 ddp = 2 * ( x + dp );
1541 dp = dp * x + p;
1542 p = p * x + c;
1543 }
1544
1546 template <typename T_real> inline T_real evalMonicQuartic(
1547 T_real const & x,
1548 T_real const & a,
1549 T_real const & b,
1550 T_real const & c,
1551 T_real const & d )
1552 {
1553 T_real p;
1554 p = x + a; // x + a
1555 p = p * x + b; // x^2+ a*x + b
1556 p = p * x + c; // x^3+ a*x^2 + b*x + c
1557 p = p * x + d; // x^4+ a*x^3 + b*x^2 + c*x + d
1558 return p;
1559 }
1560
1562 template <typename T_real> inline void evalMonicQuartic(
1563 T_real const & x,
1564 T_real const & a,
1565 T_real const & b,
1566 T_real const & c,
1567 T_real const & d,
1568 T_real & p,
1569 T_real & dp )
1570 {
1571 p = x + a; // x + a
1572 dp = x + p; // 2*x + a
1573 p = p * x + b; // x^2+ a*x + b
1574 dp = dp * x + p; // 3*x^2 + 2*a*x + b
1575 p = p * x + c; // x^3+ a*x^2 + b*x + c
1576 dp = dp * x + p; // 4*x^3 + 3*a*x^2 + 2*b*x + c
1577 p = p * x + d; // x^4+ a*x^3 + b*x^2 + c*x + d
1578 }
1579
1581 template <typename T_real> inline void evalMonicQuartic(
1582 T_real const & x,
1583 T_real const & a,
1584 T_real const & b,
1585 T_real const & c,
1586 T_real const & d,
1587 T_real & p,
1588 T_real & dp,
1589 T_real & ddp )
1590 {
1591 // p_{n+1}(x) = x * p_{n}(x) + b_{n}
1592 // p'_{n+1}(x) = x * p'_{n}(x) + p_{n}(x)
1593 // p''_{n+1}(x) = x * p''_{n}(x) + 2*p'_{n}(x)
1594 // ddp = 0;
1595 // dp = 1;
1596 p = x + a; // x + a
1597
1598 ddp = 2;
1599 dp = x + p;
1600 p = p * x + b;
1601
1602 ddp = ddp * x + 2 * dp;
1603 dp = dp * x + p;
1604 p = p * x + c;
1605
1606 ddp = ddp * x + 2 * dp;
1607 dp = dp * x + p;
1608 p = p * x + d;
1609 }
1610
1611} // namespace PolynomialRoots
1612
1613#endif
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