35 template<
size_t Order, std::
intmax_t num, std::
intmax_t denom,
class PolyVar>
62 template<
size_t Order,
class Coeff_t,
class PolyVar>
65 typedef std::array<Coeff_t, Order+1> Base;
68 using Base::operator[];
87 if (_list.size() > Order+1)
88 throw std::length_error(
"initializer list too long");
91 for (
auto it = _list.begin(); it != _list.end(); ++i, ++it)
92 Base::operator[](i) = *it;
94 for (; i <= Order; ++i)
95 Base::operator[](i) =
empty_sum(Coeff_t());
98 template<
class InputIt>
102 for (; (it != last) && (i <= Order); ++i, ++it)
103 Base::operator[](i) = *it;
106 stator_throw() <<
"Polynomial type too short to hold this range of coefficients";
108 for (; i <= Order; ++i)
109 Base::operator[](i) =
empty_sum(Coeff_t());
115 template<
size_t N,
class Coeff_t2,
class PolyVar2,
116 typename =
typename std::enable_if<(N <= Order) && variable_in<PolyVar, PolyVar2>::value >::type>
120 Base::operator[](i) = poly[i];
121 for (; i <= Order; ++i)
122 Base::operator[](i) =
empty_sum(Coeff_t());
128 for (
size_t i(0); i <= Order; ++i)
129 retval[i] = -Base::operator[](i);
139 template<
size_t NewOrder,
size_t Order,
class Coeff_t,
class PolyVar>
144 std::copy(f.begin(), f.begin() + std::min(Order, NewOrder) + 1, retval.begin());
158 template<
size_t Order,
class Coeff_t,
class PolyVar>
178 template<
class Coeff_t,
size_t Order,
class Var1,
class Var2,
class ...VarArgs,
182 {
return Polynomial<Order, Coeff_t,
Var<VarArgs...> >(f.begin(), f.end()); }
186 template<
size_t Order,
class Coeff_t,
class PolyVar,
class SubVar,
200 template<
class Coeff_t,
size_t Order,
class PolyVar,
class SubVar,
class Coeff_t2,
201 typename =
typename std::enable_if<(std::is_arithmetic<Coeff_t2>::value
202 && !std::is_base_of<Eigen::EigenBase<Coeff_t>, Coeff_t>::value
203 && !std::is_base_of<Eigen::EigenBase<Coeff_t2>, Coeff_t2>::value)>::type,
205 decltype(
store(Coeff_t() * Coeff_t2()))
214 const auto & x = x_container.
_val;
216 if (std::numeric_limits<Coeff_t2>::has_infinity
217 && ((std::numeric_limits<Coeff_t2>::infinity() == x)
218 || (std::numeric_limits<Coeff_t2>::infinity() == -x))) {
221 for(
size_t i = Order; i > 0; --i)
229 return f[i] * std::numeric_limits<Coeff_t2>::infinity();
237 typedef decltype(
store(Coeff_t() * Coeff_t2())) RetType;
238 RetType sum = RetType();
239 for(
size_t i = Order; i > 0; --i)
240 sum = sum * x + f[i];
241 sum = sum * x + f[0];
249 template<
size_t Stage>
251 template<
size_t Order,
class PolyVar,
class Coeff_t,
class X>
263 template<
size_t Order,
class PolyVar,
class Coeff_t,
class X>
279 template<
class Coeff_t,
size_t Order,
class PolyVar,
class SubVar,
class Coeff_t2,
280 typename =
typename std::enable_if<!std::is_arithmetic<Coeff_t2>::value
281 || (std::is_base_of<Eigen::EigenBase<Coeff_t2>, Coeff_t2>::value && std::is_arithmetic<Coeff_t2>::value)
282 || (std::is_base_of<Eigen::EigenBase<Coeff_t>, Coeff_t>::value && std::is_arithmetic<Coeff_t2>::value)
295 template<
size_t D,
size_t Order, class Coeff_t, class PolyVar, class Coeff_t2>
296 std::array<Coeff_t, D+1> eval_derivatives(const
Polynomial<Order, Coeff_t, PolyVar>& f, const Coeff_t2& x)
298 std::array<Coeff_t, D+1> retval;
300 retval[0] = f[Order];
301 for (
size_t i(Order); i>0; --i) {
302 for (
size_t j = std::min(D, Order-(i-1)); j>0; --j)
303 retval[j] = retval[j] * x + retval[j-1];
304 retval[0] = retval[0] * x + f[i-1];
308 for (
size_t i(2); i <= D; ++i) {
337 template<
size_t Order1,
class Coeff_t,
class PolyVar1,
class PolyVar2,
size_t Order2,
342 static_assert(Order2 < Order1,
"Cannot perform division when the order of the denominator is larger than the numerator using this routine");
343 static_assert(Order2 > 0,
"Constant division fails with these loops");
347 if (g[Order2] == 0) {
348 auto lower_order_op =
gcd(f, change_order<Order2 - 1>(g));
349 return RetType(std::get<0>(lower_order_op), std::get<1>(lower_order_op));
358 for (
size_t k(Order1); k>=Order2; --k) {
360 q[k-Order2] = r[k] / g[Order2];
362 for (
size_t j(0); j <= Order2; j++)
363 r[k+j-Order2] -= q[k-Order2] * g[j];
366 return RetType(q, change_order<Order2 - 1>(r));
372 template<
size_t Order1,
class Coeff_t,
class PolyVar1,
class PolyVar2,
379 typedef std::tuple<FType, RType> RetType;
381 return RetType(FType{std::numeric_limits<Coeff_t>::infinity()}, RType{
empty_sum(Coeff_t())});
399 template<
class PolyVar,
class ...VarArgs,
class Coeff_t,
size_t N,
404 for (
size_t i(0); i <
N; ++i) {
405 retval[i] = f[i+1] * (i+1);
415 template<
class PolyVar,
class ...VarArgs,
class Coeff_t,
size_t N,
457 template<
size_t Order,
class Coeff_t,
class PolyVar>
461 if (t == 0)
return f;
464 retval[0] = f[Order];
465 for (
size_t i(Order); i>0; i--) {
466 for (
size_t j = Order-(i-1); j>0; j--)
467 retval[j] = retval[j] * t + retval[j-1];
468 retval[0] = retval[0] * t + f[i-1];
479 template<
size_t Order,
class Coeff_t,
class PolyVar>
482 retval[0] = f[Order];
483 for (
size_t i(Order); i>0; i--) {
484 for (
size_t j = Order-(i-1); j>0; j--)
485 retval[j] += retval[j-1];
529 template<
size_t Order,
class Coeff_t,
class PolyVar>
533 for (
size_t i(Order); i>0; i--) {
534 for (
size_t j = Order-(i-1); j>0; j--)
535 retval[j] += retval[j-1];
536 retval[0] += f[Order - (i-1)];
543 template<
size_t Order,
class Coeff_t,
class PolyVar>
546 for (
size_t i(1); i <= Order; i+=2)
554 template<
size_t Order,
class Coeff_t,
class PolyVar>
558 for (
size_t i(1); i <= Order; ++i)
559 g[i] *= (factor *= a);
578 template<
class Coeff_t,
size_t Order,
class Coeff_t2,
class PolyVar>
587 static_assert(std::is_floating_point<Coeff_t>::value,
"This has only been implemented for floating point types");
588 static_assert(std::numeric_limits<Coeff_t>::radix == 2,
"This has only been implemented for base-2 floating point types");
589 const int mantissa_digits = std::numeric_limits<Coeff_t>::digits;
590 const Coeff_t eps = 1.06 /
std::pow(2, mantissa_digits);
594 for(
size_t i = 1; i <= Order; ++i) {
595 sum += (2 * i + 1) *
std::abs(f[i]) * xn;
659 template<
size_t Order,
class Coeff_t,
class PolyVar>
661 if (root == Coeff_t())
667 b[Order-1] = a[Order];
668 b[0] = - a[0] / root;
670 size_t i_t = Order-2;
673 const Coeff_t d = root * b[i_t + 1];
675 b[i_b] = (b[i_b-1] - a[i_b]) / root;
678 b[i_t] = a[i_t+1] + d;
692 template<
size_t Order,
class Coeff_t,
class PolyVar>
695 std::copy(a.begin()+1, a.end(), b.begin());
704 template<
class PolyVar>
714 template<
class PolyVar>
729 template<
class PolyVar>
742 static const double maxSqrt = std::sqrt(std::numeric_limits<double>::max());
747 if (retval[0] > retval[1])
748 std::swap(retval[0], retval[1]);
752 const double arg = f[1] * f[1] - 4 * f[0];
763 const double root1 = -(f[1] + std::copysign(std::sqrt(arg), f[1])) * 0.5;
764 const double root2 = f[0] / root1;
767 std::swap(retval[0], retval[1]);
779 template<
size_t Order,
class Coeff_t,
class PolyVar>
785 for (
auto& root : roots)
791 roots.push_back(root);
792 std::sort(roots.begin(), roots.end());
804 template<
class PolyVar>
807 if (f_original[3] == 0)
810 if (f_original[0] == 0)
813 return deflate_and_solve_polynomial(f_original, 0.0);
816 auto f =
expand(f_original / f_original[3]);
818 if ((f[2] == 0) && (f[1] == 0))
822 static const double maxSqrt = std::sqrt(std::numeric_limits<double>::max());
824 if ((f[2] > maxSqrt) || (f[2] < -maxSqrt))
828 return deflate_and_solve_polynomial(f, -f[2]);
835 return deflate_and_solve_polynomial(f, -f[0] / f[1]);
839 return deflate_and_solve_polynomial(f, -std::sqrt(-f[1]));
841 if ((f[0] > maxSqrt) || (f[0] < -maxSqrt))
843 return deflate_and_solve_polynomial(f, -std::cbrt(f[0]));
845 const double v = f[0] + (2.0 * f[2] * f[2] / 9.0 - f[1]) * (f[2] / 3.0);
847 if ((v > maxSqrt) || (v < -maxSqrt))
848 return deflate_and_solve_polynomial(f, -f[2]);
850 const double uo3 = f[1] / 3.0 - f[2] * f[2] / 9.0;
851 const double u2o3 = uo3 + uo3;
853 if ((u2o3 > maxSqrt) || (u2o3 < -maxSqrt))
858 return deflate_and_solve_polynomial(f, -f[0] / f[1]);
861 return deflate_and_solve_polynomial(f, -std::sqrt(-f[1]));
863 return deflate_and_solve_polynomial(f, 0.0);
866 return deflate_and_solve_polynomial(f, -f[1] / f[2]);
869 const double uo3sq4 = u2o3 * u2o3;
870 if (uo3sq4 > maxSqrt)
875 return deflate_and_solve_polynomial(f, -f[0] / f[1]);
878 return deflate_and_solve_polynomial(f, -std::sqrt(-f[1]));
880 return deflate_and_solve_polynomial(f, 0.0);
883 return deflate_and_solve_polynomial(f, -f[1] / f[2]);
886 const double j = (uo3sq4 * uo3) + v * v;
894 const double w = std::sqrt(j);
897 root = std::cbrt(0.5*(w-v)) - (uo3) * std::cbrt(2.0 / (w-v)) - f[2] / 3.0;
899 root = uo3 * std::cbrt(2.0 / (w+v)) - std::cbrt(0.5*(w+v)) - f[2] / 3.0;
906 return deflate_and_solve_polynomial(f, root);
913 const double muo3 = - uo3;
918 if (f[2] > 0) s = -s;
921 const double scube = s * muo3;
925 double t = - v / (scube + scube);
928 t = std::min(std::max(t, -1.0), +1.0);
929 const double k = std::acos(t) / 3.0;
934 const double sinsqk = 1.0 - cosk * cosk;
938 double rt3sink = std::sqrt(3.0) * std::sqrt(sinsqk);
939 roots.push_back(s * (-cosk + rt3sink) - f[2] / 3.0);
940 roots.push_back(s * (-cosk - rt3sink) - f[2] / 3.0);
949 std::sort(roots.begin(), roots.end());
957 template<
size_t Order,
class Coeff_t,
class PolyVar>
962 std::tie(std::ignore, rem) =
gcd(f, g);
968 template<
size_t Order,
class Coeff_t,
class PolyVar>
974 _p_n(p_n), _p_nminus1(p_n,
derivative(p_n, PolyVar()))
981 _p_n(p_n), _p_nminus1(p_n,
mrem(p_nplus1, p_n))
998 return _p_nminus1.get(i-1);
1007 template<
class Coeff_t2>
1009 return sign_change_helper(0, x);
1012 template<
class Coeff_t2>
1013 size_t roots(
const Coeff_t2& a,
const Coeff_t2& b)
const {
1014 return std::abs(
int(sign_changes(a)) -
int(sign_changes(b)));
1028 template<
class Coeff_t2>
1030 const Coeff_t currentx =
sub(_p_n, PolyVar() = x);
1031 const int current_sign = (currentx != 0) * (1 - 2 * std::signbit(currentx));
1032 const bool sign_change = (current_sign != 0) && (last_sign != 0) && (current_sign != last_sign);
1034 const int next_sign = (current_sign != 0) ? current_sign : last_sign;
1035 return _p_nminus1.sign_change_helper(next_sign, x) + sign_change;
1039 os <<
",\n p_" << max_order - Order <<
"=" << _p_n;
1040 _p_nminus1.output_helper(os, max_order);
1047 template<
class Coeff_t,
class PolyVar>
1068 template<
class Coeff_t2>
1075 template<
class Coeff_t2>
1077 const Coeff_t currentx =
sub(_p_n, PolyVar() = x);
1078 const int current_sign = (currentx != 0) * (1 - 2 * std::signbit(currentx));
1079 const bool sign_change = (current_sign != 0) && (last_sign != 0) && (current_sign != last_sign);
1084 os <<
",\n p_" << max_order <<
"=" << _p_n;
1145 template<
size_t Order,
class Coeff_t,
class PolyVar>
1160 template<
size_t Order,
class Coeff_t,
class PolyVar>
1163 size_t sign_changes(0);
1165 for (
size_t i(0); i <= Order; ++i) {
1166 const int current_sign = (f[i] != 0) * (1 - 2 * std::signbit(f[i]));
1167 sign_changes += (current_sign != 0) && (last_sign != 0) && (current_sign != last_sign);
1168 last_sign = (current_sign != 0) ? current_sign : last_sign;
1170 return sign_changes;
1197 template<
size_t Order,
class Coeff_t,
class PolyVar>
1212 template<
size_t Order,
class Coeff_t,
class PolyVar>
1226 template<
class Coeff_t,
size_t Order,
class PolyVar>
1228 std::array<size_t, Order+1> times_used;
1230 Coeff_t ub = Coeff_t();
1232 size_t real_order = Order;
1233 while ((real_order > 0) && (f[real_order] == 0))
1236 for (
int m(real_order-1); m >= 0; --m)
1237 if (std::signbit(f[m]) != std::signbit(f[real_order])) {
1238 Coeff_t tempub = std::numeric_limits<Coeff_t>::infinity();
1239 for (
int k(real_order); k > m; --k)
1240 if (std::signbit(f[k]) != std::signbit(f[m]))
1242 Coeff_t temp =
std::pow(-(1 << times_used[k]) * f[m] / f[k], 1.0 / (k - m));
1244 tempub = std::min(temp, tempub);
1246 ub = std::max(tempub, ub);
1268 template<
class Coeff_t,
size_t Order,
class PolyVar>
1278 template<
class Coeff_t,
class PolyVar>
1288 template<
class Coeff_t,
class PolyVar>
1300 template<
size_t Order,
class Coeff_t,
class PolyVar>
1307 return StackVector<std::pair<Coeff_t,Coeff_t>, Order>();
1310 return StackVector<std::pair<Coeff_t,Coeff_t>, Order>{std::make_pair(Coeff_t(0), Coeff_t(1))};
1322 for (
size_t i(0); i <= Order; ++i)
1323 p1[i] *= (1 << (Order-i));
1340 for (
auto& root_bound : retval) {
1341 root_bound.first /= 2;
1342 root_bound.second /= 2;
1347 for (
auto& root_bound : second_range)
1348 retval.push_back(std::make_pair(root_bound.first / 2 + 0.5, root_bound.second / 2 + 0.5));
1363 template<
size_t Order,
class Coeff_t,
class PolyVar>
1364 StackVector<std::pair<Coeff_t,Coeff_t>, Order>
1369 if (upper_bound == 0)
1370 return StackVector<std::pair<Coeff_t,Coeff_t>, Order>();
1377 for (
auto& bound : bounds) {
1378 bound.first *= upper_bound;
1379 bound.second *= upper_bound;
1401 template<
class Coeff_t>
1403 typedef std::array<Coeff_t, 4>
Base;
1415 if (((*
this)[0] == 0) && ((*
this)[2] == 0))
1416 return (*
this)[1] / (*this)[3];
1419 if (std::isinf(x) && ((*
this)[0] != 0) && ((*
this)[2] != 0))
1420 return (*
this)[0] / (*this)[2];
1423 Coeff_t numerator = (*this)[1];
1424 if ((*
this)[0] != 0)
1425 numerator += x * (*this)[0];
1427 Coeff_t denominator = (*this)[3];
1428 if ((*
this)[2] != 0)
1429 denominator += x * (*this)[2];
1431 return numerator / denominator;
1438 (*this)[1] += (*this)[0] * x;
1439 (*this)[3] += (*this)[2] * x;
1454 Base::operator=(std::array<Coeff_t, 4>{{(*this)[1], (*this)[0] + (*this)[1], (*this)[3], (*this)[2] + (*this)[3]}});
1469 template<
size_t Order,
class Coeff_t,
class PolyVar>
1470 StackVector<std::pair<Coeff_t,Coeff_t>, Order>
1479 if (sign_changes == 0)
1481 return StackVector<std::pair<Coeff_t,Coeff_t>, Order>();
1483 if (sign_changes == 1)
1485 return StackVector<std::pair<Coeff_t,Coeff_t>, Order>{std::make_pair(M.
eval(0), M.
eval(HUGE_VAL))};
1520 const Coeff_t scale = 2.0;
1527 StackVector<std::pair<Coeff_t,Coeff_t>, Order> retval;
1538 for (
const auto& bound: first_range)
1546 for (
const auto& bound: second_range)
1553 template<
class Coeff_t,
class PolyVar>
1554 StackVector<std::pair<Coeff_t,Coeff_t>, 1>
1556 return StackVector<std::pair<Coeff_t,Coeff_t>, 1>();
1567 template<
size_t Order,
class Coeff_t,
class PolyVar>
1568 StackVector<std::pair<Coeff_t,Coeff_t>, Order>
1573 if (upper_bound == 0)
1574 return StackVector<std::pair<Coeff_t,Coeff_t>, Order>();
1577 for (
auto& bound: bounds) {
1579 if (bound.first > bound.second)
1580 std::swap(bound.first, bound.second);
1582 if (std::isinf(bound.second))
1583 bound.second = upper_bound;
1610 template<
size_t Order,
class Coeff_t,
class PolyVar1,
class PolyVar2 = PolyVar1,
1611 typename =
typename std::enable_if<(Order > 2)>::type,
1617 if (f[Order] == Coeff_t())
1620 Eigen::Matrix<Coeff_t, 2, 1> dGuess{0, 0};
1622 for (
size_t it(0); it < 20; ++it) {
1626 std::tie(p1, rem1) =
gcd(f, guess);
1631 std::tie(std::ignore, rem2) =
gcd(p1, guess);
1634 Eigen::Matrix<Coeff_t, 2, 1> F;
1635 F << rem1[0] , rem1[1];
1636 Eigen::Matrix<Coeff_t, 2, 2> J;
1637 J << -rem2[0], guess[0] * rem2[1], -rem2[1], guess[1] * rem2[1] - rem2[0];
1640 dGuess = J.inverse() * (-F);
1641 guess[0] = guess[0] + dGuess[0];
1642 guess[1] = guess[1] + dGuess[1];
1644 if (dGuess.squaredNorm() <= tolerance*tolerance)
1648 throw std::runtime_error(
"Iteration count exceeded");
1657 template<
class Coeff_t,
class PolyVar1,
class PolyVar2 = PolyVar1,
size_t Order,
1658 typename =
typename std::enable_if<(Order <= 2)>::type,
1669 template<
class Coeff_t,
size_t Order,
class PolyVar>
1685 const Coeff_t eps = std::max(Coeff_t(std::ldexp(1.0, 1-tol_bits)), Coeff_t(2*std::numeric_limits<Coeff_t>::epsilon()));
1687 bool try_bisection =
true;
1689 auto f_bisection = [&](Coeff_t x) {
return sub(f, PolyVar() = x); };
1691 while(!regions.empty()) {
1692 auto range = regions.pop_back();
1693 const Coeff_t xmin = std::get<0>(range);
1694 const Coeff_t xmax = std::get<1>(range);
1695 const size_t roots = std::get<2>(range);
1697 Coeff_t xmid = (xmin + xmax) / 2;
1701 for (
size_t i(0); i < roots; ++i)
1702 retval.push_back(xmid);
1703 try_bisection =
true;
1707 size_t rootsa = chain.roots(xmin, xmid);
1708 size_t rootsb = chain.roots(xmid, xmax);
1710 if ((rootsa + rootsb) != roots) {
1716 xmid = (xmid + xmax) / 2;
1717 rootsa = chain.roots(xmin, xmid);
1718 rootsb = chain.roots(xmid, xmax);
1719 if ((rootsa + rootsb) != roots) {
1729 regions.push_back(std::make_tuple(xmin, xmid, rootsa));
1730 else if (rootsa == 1) {
1731 if (try_bisection) {
1735 retval.push_back(root);
1737 regions.push_back(std::make_tuple(xmin, xmid, rootsa));
1740 regions.push_back(std::make_tuple(xmin, xmid, rootsa));
1743 regions.push_back(std::make_tuple(xmid, xmax, rootsb));
1744 else if (rootsb == 1) {
1745 if (try_bisection) {
1749 retval.push_back(root);
1751 regions.push_back(std::make_tuple(xmid, xmax, rootsb));
1754 regions.push_back(std::make_tuple(xmid, xmax, rootsa));
1767 template<PolyRootBounder BoundMode, PolyRootBisector BisectionMode,
size_t Order,
class Coeff_t,
class PolyVar>
1770 StackVector<std::pair<Coeff_t,Coeff_t>, Order> bounds;
1772 switch (BoundMode) {
1781 auto f_bisection = [&](Coeff_t x) {
return sub(f, PolyVar() = x); };
1782 for (
const auto& bound : bounds) {
1783 const Coeff_t& a = bound.first;
1784 const Coeff_t& b = bound.second;
1785 switch(BisectionMode) {
1786 case PolyRootBisector::BISECTION:
1798 std::sort(retval.begin(), retval.
end());
1812 template<PolyRootBounder BoundMode = PolyRootBounder::STURM, PolyRootBisector BisectionMode = PolyRootBisector::BISECTION,
size_t Order,
class Coeff_t,
class PolyVar>
1817 if (f[0] == Coeff_t())
1822 if (f[Order] == Coeff_t())
1825 auto roots = solve_real_positive_roots_poly<BoundMode, BisectionMode, Order, Coeff_t, PolyVar>(f);
1826 auto neg_roots = solve_real_positive_roots_poly<BoundMode, BisectionMode, Order, Coeff_t, PolyVar>(
reflect_poly(f));
1829 for (
const auto& root: neg_roots)
1830 roots.push_back(-root);
1832 std::sort(roots.begin(), roots.end());
1837 template<
size_t Order,
class Coeff_t,
class PolyVar>
1838 std::ostream& operator<<(std::ostream& os, const SturmChain<Order, Coeff_t, PolyVar>& c) {
1839 os <<
"SturmChain{p_0=" << c._p_n;
1840 c._p_nminus1.output_helper(os, Order);
size_t budan_01_test(const Polynomial< Order, Coeff_t, PolyVar > &f)
Budan's upper bound estimate for the number of real roots in a Polynomial over the range ...
size_t sign_change_helper(const int last_sign, const Coeff_t2 &x) const
StackVector< double, 0 > solve_real_roots(const Polynomial< 0, double, PolyVar > &f)
Specialisation for no roots of a 0th order Polynomial.
detail::SturmChain< Order, Coeff_t, PolyVar > sturm_chain(const Polynomial< Order, Coeff_t, PolyVar > &f)
Helper function to generate a SturmChain from a Polynomial.
Coeff_t LMQ_lower_bound(const Polynomial< 0, Coeff_t, PolyVar > &f)
Specialisation of Local-max Quadratic lower-bound estimation for real roots of a Polynomial, where the Polynomial is a constant.
Polynomial< 2, Coeff_t, PolyVar1 > LinBairstowSolve(Polynomial< Order, Coeff_t, PolyVar1 > f, Coeff_t tolerance, Polynomial< 2, Coeff_t, PolyVar2 > guess={0, 0, 1})
Solve for a quadratic factor of the passed Polynomial using the LinBairstow method.
Polynomial(std::initializer_list< Coeff_t > _list)
List initializer for simple Polynomial construction.
StackVector< std::pair< Coeff_t, Coeff_t >, Order > VAS_real_root_bounds(const Polynomial< Order, Coeff_t, PolyVar > &f)
Calculate bounds on all of the positive real roots of a Polynomial.
Symbolic representation of a variable.
C< 0 > Null
A symbolic representation of zero.
Coeff_t precision(const Polynomial< Order, Coeff_t, PolyVar > &f, const Coeff_t2 &x)
Calculate a maximum error estimate for the evaluation of the polynomial at .
auto N(const T &a) -> STATOR_AUTORETURN(simplify< NConfig >(a))
A variant of simplify that converts compile time symbols into numbers.
size_t alesina_galuzzi_test(const Polynomial< Order, Coeff_t, PolyVar > &f, const Coeff_t &a, const Coeff_t &b)
Alesina-Galuzzi upper bound estimate for the numer of real roots in a Polynomial over a specified ran...
Base::iterator end()
Returns an iterator pointing to the end of the container.
void output_helper(std::ostream &os, const size_t max_order) const
std::tuple< Polynomial< Order1, Coeff_t, typename variable_combine< PolyVar1, PolyVar2 >::type >, Polynomial< Order2 - 1, Coeff_t, typename variable_combine< PolyVar1, PolyVar2 >::type > > gcd(const Polynomial< Order1, Coeff_t, PolyVar1 > &f, const Polynomial< Order2, Coeff_t, PolyVar2 > &g)
Perform Euclidean division of a polynomial.
Polynomial< Order, Coeff_t, Var< VarArgs... > > sub(const Polynomial< Order, Coeff_t, Var1 > &f, const Relation< Var2, Var< VarArgs... > > &x_container)
Optimised Polynomial substitution which performs an exchange of the Polynomial Var.
constexpr Polynomial< Order, Coeff_t, PolyVar > empty_sum(const Polynomial< Order, Coeff_t, PolyVar > &)
Returns the empty sum of a Polynomial.
size_t sign_changes(const Coeff_t2 &x) const
Polynomial operator-() const
Unary negative operator to change the sign of a Polynomial.
Coeff_t LMQ_lower_bound(const Polynomial< Order, Coeff_t, PolyVar > &f)
Local-max Quadratic lower bound estimate for the real roots of a Polynomial.
Polynomial< Order, Coeff_t, PolyVar > scale_poly(const Polynomial< Order, Coeff_t, PolyVar > &f, const Coeff_t &a)
Returns a polynomial where is the scaling factor.
auto cos(const C< num, den > &a) -> STATOR_AUTORETURN(cos_Cimpl(a, detail::select_overload
size_t descartes_rule_of_signs(const Polynomial< Order, Coeff_t, PolyVar > &f)
Calculates an upper bound estimate for the number of positive real roots of a Polynomial (including m...
bool bisection(const F &f, Real &x, Real low_bound, Real high_bound, size_t iterations=0, int digits=std::numeric_limits< Real >::digits/2)
Polynomial< Order, double, PolyVar > shift_function(const Polynomial< Order, Coeff_t, PolyVar > &f, const double t)
Returns a polynomial .
Polynomial< N-1, Coeff_t, typename variable_combine< PolyVar, Var< VarArgs... > >::type > derivative(const Polynomial< N, Coeff_t, PolyVar > &f, Var< VarArgs... >)
Derivatives of Polynomial types.
Fundamental typedef's and macros for stator.
Stack-allocated equivalent of std::vector.
Polynomial< Order, Coeff_t, PolyVar > _p_n
Worker class for symbolically evaluating a substitution on a Polynomial.
A class representing a compile-time rational constant (i.e., std::ratio).
Coeff_t sub(const Polynomial< Order, Coeff_t, PolyVar > &f, const Relation< SubVar, Null > &)
Optimised Polynomial substitution for Null insertions.
StackVector< Coeff_t, Order > solve_real_positive_roots_poly(const Polynomial< Order, Coeff_t, PolyVar > &f)
Iterative solver for the real roots of a square-free Polynomial.
size_t roots(const Coeff_t2 &a, const Coeff_t2 &b) const
auto expand(const T &a) -> STATOR_AUTORETURN(simplify< ExpandConfig >(a))
A variant of simplify that expands into Polynomial types aggressively.
SturmChain(const Polynomial< 0, Coeff_t, PolyVar > &p_n)
Constructor is the first and last Polynomial in the chain.
Polynomial< 0, Coeff_t, PolyVar > _p_n
SturmChain< Order-1, Coeff_t, PolyVar > _p_nminus1
StackVector< std::pair< Coeff_t, Coeff_t >, Order > VCA_real_root_bounds_worker(const Polynomial< Order, Coeff_t, PolyVar > &f)
Calculate interval bounds on all of the positive real roots between of a squarefree Polynomial...
StackVector< double, 3 > solve_real_roots(const Polynomial< 3, double, PolyVar > &f_original)
Calculate the real roots of a 3rd order Polynomial using radicals.
Polynomial(const Polynomial< N, Coeff_t2, PolyVar2 > &poly)
Constructor for constructing higher-order Polynomial types from lower order Polynomial types...
std::tuple< Polynomial< Order1, Coeff_t, typename variable_combine< PolyVar1, PolyVar2 >::type >, Polynomial< 0, Coeff_t, typename variable_combine< PolyVar1, PolyVar2 >::type > > gcd(const Polynomial< Order1, Coeff_t, PolyVar1 > &f, const Polynomial< 0, Coeff_t, PolyVar2 > &g)
Specialisation for division by a constant.
Polynomial< Order-2, Coeff_t, PolyVar > mrem(const Polynomial< Order, Coeff_t, PolyVar > &f, const Polynomial< Order-1, Coeff_t, PolyVar > &g)
Calculates the negative of the remainder of the division of by .
void push_back(const T &val)
Add an element to the end of the container.
Polynomial< NewOrder, Coeff_t, PolyVar > change_order(const Polynomial< Order, Coeff_t, PolyVar > &f)
Change the order of a Polynomial.
C< 1 > Unity
A symbolic representation of one.
Polynomial< 2, Coeff_t, typename variable_combine< PolyVar1, PolyVar2 >::type > LinBairstowSolve(Polynomial< Order, Coeff_t, PolyVar1 > f, Coeff_t tolerance, Polynomial< 2, Coeff_t, PolyVar2 > guess={0, 0, 1})
Solve for a quadratic factor of the passed Polynomial using the LinBairstow method.
PolyRootBounder
Enumeration of the types of root bounding methods we have for solve_real_roots.
Polynomial< Order, Coeff_t, PolyVar > shift_function(const Polynomial< Order, Coeff_t, PolyVar > &f, Unity)
Returns a polynomial .
Symbolic representation of a variable substitution.
bool halleys_method(const F &f, Real &x, Real low_bound=-HUGE_VAL, Real high_bound=+HUGE_VAL, size_t iterations=0, int digits=std::numeric_limits< Real >::digits/2)
Safeguarded Halley's method for detecting a root.
Coeff_t LMQ_upper_bound(const Polynomial< Order, Coeff_t, PolyVar > &f)
Local-max Quadratic upper bound estimate for the value of the real roots of a Polynomial.
Null derivative(const Polynomial< N, Coeff_t, PolyVar > &f, Var< VarArgs... >)
Derivatives of Polynomial types.
Polynomial< Order-1, Coeff_t, PolyVar > deflate_polynomial(const Polynomial< Order, Coeff_t, PolyVar > &a, Null)
A specialisation of deflation where the root is at zero.
auto sub(const Polynomial< Order, Coeff_t, PolyVar > &f, const Relation< SubVar, Coeff_t2 > &x_container) -> STATOR_AUTORETURN(detail::PolySubWorker< Order >::eval(f, x_container._val)) template< size_t D, size_t Order, class Coeff_t, class PolyVar, class Coeff_t2 > std::array< Coeff_t, D+1 > eval_derivatives(const Polynomial< Order, Coeff_t, PolyVar > &f, const Coeff_t2 &x)
Symbolically evaluates a Polynomial expression.
#define STATOR_AUTORETURN(EXPR)
A convenience Macro for defining auto return type functions.
The stator symbolic math library.
SturmChain(const Polynomial< Order, Coeff_t, PolyVar > &p_n)
Constructor if is the first Polynomial in the chain.
StackVector< double, 2 > solve_real_roots(Polynomial< 2, double, PolyVar > f)
Calcualte the real roots of a 2nd order Polynomial using radicals.
size_t sign_change_helper(const int last_sign, const Coeff_t2 &x) const
Helper function for calculating the sign changes in the Sturm chain.
PolyRootBisector
Enumeration of the types of bisection routines we have for solve_real_roots .
StackVector< Coeff_t, Order > solve_real_positive_roots_poly_sturm(const Polynomial< Order, Coeff_t, PolyVar > &f, const size_t tol_bits=56)
Determine the positive real roots of a polynomial using bisection and Sturm chains.
size_t addition_precision(const T f1, const T f2)
Calculate a "precision" for addition between two float types.
constexpr size_t max_order(size_t N, size_t M)
Polynomial< Order, Coeff_t, PolyVar > invert_taylor_shift(const Polynomial< Order, Coeff_t, PolyVar > &f)
Returns a polynomial .
constexpr C<(1 - 2 *(num< 0)) *num,(1 - 2 *(den< 0)) *den > abs(const C< num, den > &a)
auto pow(const LHS &l, const RHS &r) -> STATOR_AUTORETURN(std::pow(l, r))
void output_helper(std::ostream &os, const size_t max_order) const
A type trait to denote symbolic terms (i.e., one that is not yet immediately evaluable to a "normal" ...
Polynomial< Order-1, Coeff_t, PolyVar > deflate_polynomial(const Polynomial< Order, Coeff_t, PolyVar > &a, const double root)
Factors out a root of a polynomial and returns a lower-order polynomial with the remaining roots...
Polynomial< Order, Coeff_t, PolyVar > reflect_poly(const Polynomial< Order, Coeff_t, PolyVar > &f)
Returns a polynomial .
Polynomial()
Default constructor.
size_t sign_changes(const Coeff_t2 &x) const
Coeff_t LMQ_upper_bound(const Polynomial< 0, Coeff_t, PolyVar > &f)
Specialisation of Local-max Quadratic upper-bound estimation for real roots of a Polynomial, where the Polynomial is a constant.
SturmChain(const Polynomial< Order+1, Coeff_t, PolyVar > &p_nplus1, const Polynomial< Order, Coeff_t, PolyVar > &p_n)
Constructor if is an intermediate Polynomial in the chain.
Polynomial(InputIt first, InputIt last)
StackVector< std::pair< Coeff_t, Coeff_t >, Order > VCA_real_root_bounds(const Polynomial< Order, Coeff_t, PolyVar > &f)
Calculate bounds on all of the positive real roots of a Polynomial.
StackVector< double, 1 > solve_real_roots(const Polynomial< 1, double, PolyVar > &f)
Calculate the single real root (if it exists) of a 1st order Polynomial.
size_t subtraction_precision(const T f1, const T f2)
Calculate a "precision" for subtraction between two float types.
SturmChain(const Polynomial< 1, Coeff_t, PolyVar > &p_nplus1, const Polynomial< 0, Coeff_t, PolyVar > &p_n)
Constructor if this is the last Polynomial in the chain.
StackVector< std::pair< Coeff_t, Coeff_t >, Order > VAS_real_root_bounds_worker(Polynomial< Order, Coeff_t, PolyVar > f, MobiusTransform< Coeff_t > M)
Calculate bounds on all of the positive real roots in the range of a Polynomial.
auto store(const T &val) -> decltype(store_impl(val, select_overload
A collection of Polynomials which form a Sturm chain.
Array representation of Polynomial.