1 |
|
#pragma once |
2 |
|
|
3 |
|
#include <iosfwd> |
4 |
|
#include <utility> |
5 |
|
#include <vector> |
6 |
|
|
7 |
|
#include "../integer.h" |
8 |
|
#include "../upolynomial.h" |
9 |
|
#include "dyadic_rational.h" |
10 |
|
#include "integer.h" |
11 |
|
#include "integer_ring.h" |
12 |
|
#include "rational.h" |
13 |
|
#include "variable.h" |
14 |
|
|
15 |
|
namespace poly { |
16 |
|
|
17 |
|
/** |
18 |
|
* Implements a wrapper for lp_upolynomial_t. |
19 |
|
*/ |
20 |
25 |
class UPolynomial { |
21 |
|
/** The actual univariate polynomial. */ |
22 |
|
deleting_unique_ptr<lp_upolynomial_t> mPoly; |
23 |
|
|
24 |
|
public: |
25 |
|
/** Create from a lp_upolynomial_t pointer, claiming it's ownership. */ |
26 |
|
explicit UPolynomial(lp_upolynomial_t* poly); |
27 |
|
/** Copy from an internal lp_upolynomial_t pointer. */ |
28 |
|
explicit UPolynomial(const lp_upolynomial_t* poly); |
29 |
|
|
30 |
|
/** Create the zero polynomial. */ |
31 |
|
explicit UPolynomial(); |
32 |
|
/** Create a constant polynomial. */ |
33 |
|
explicit UPolynomial(const Integer& i); |
34 |
|
/** Create a constant polynomial. */ |
35 |
|
explicit UPolynomial(long i); |
36 |
|
|
37 |
|
/** Create from integer coefficients. */ |
38 |
|
explicit UPolynomial(const std::vector<Integer>& coefficients); |
39 |
|
/** Create from integer coefficients into the given integer ring. */ |
40 |
|
UPolynomial(const IntegerRing& ir, |
41 |
|
const std::vector<Integer>& coefficients); |
42 |
|
/** Create from integer coefficients. */ |
43 |
|
explicit UPolynomial(const std::vector<long>& coefficients); |
44 |
|
/** Create from integer coefficients into the given integer ring. */ |
45 |
|
UPolynomial(const IntegerRing& ir, const std::vector<long>& coefficients); |
46 |
|
|
47 |
|
/** Create from integer coefficients. */ |
48 |
|
explicit UPolynomial(std::initializer_list<long> coefficients); |
49 |
|
/** Create from integer coefficients into the given integer ring. */ |
50 |
|
UPolynomial(const IntegerRing& ir, |
51 |
|
std::initializer_list<long> coefficients); |
52 |
|
|
53 |
|
/** Construct c * x^degree. */ |
54 |
|
UPolynomial(std::size_t degree, long c); |
55 |
|
/** Construct c * x^degree into the given integer ring. */ |
56 |
|
UPolynomial(const IntegerRing& ir, std::size_t degree, long c); |
57 |
|
|
58 |
|
/** Copy from a polynomial. */ |
59 |
|
UPolynomial(const UPolynomial& poly); |
60 |
|
/** Move from a polynomial. */ |
61 |
|
UPolynomial(UPolynomial&& poly); |
62 |
|
/** Copy from a polynomial into the given integer ring. */ |
63 |
|
UPolynomial(const IntegerRing& ir, const UPolynomial& poly); |
64 |
|
|
65 |
|
/** Copy from a polynomial. */ |
66 |
|
UPolynomial& operator=(const UPolynomial& poly); |
67 |
|
/** Move from a polynomial. */ |
68 |
|
UPolynomial& operator=(UPolynomial&& poly); |
69 |
|
/** Assign from and take ownership of an internal lp_upolynomial_t pointer. |
70 |
|
*/ |
71 |
|
UPolynomial& operator=(lp_upolynomial_t* poly); |
72 |
|
|
73 |
|
/** Get a non-const pointer to the internal lp_upolynomial_t. Handle with |
74 |
|
* care! */ |
75 |
|
lp_upolynomial_t* get_internal(); |
76 |
|
/** Get a const pointer to the internal lp_upolynomial_t. */ |
77 |
|
const lp_upolynomial_t* get_internal() const; |
78 |
|
/** Release the lp_upolynomial_t pointer. This yields ownership of the |
79 |
|
* returned pointer. */ |
80 |
|
lp_upolynomial_t* release(); |
81 |
|
}; |
82 |
|
|
83 |
|
/** Return the degree of a polynomial. */ |
84 |
|
std::size_t degree(const UPolynomial& p); |
85 |
|
|
86 |
|
/** Get the leading coefficient. */ |
87 |
|
const Integer& leading_coefficient(const UPolynomial& p); |
88 |
|
/** Get the constant coefficient. */ |
89 |
|
const Integer& constant_coefficient(const UPolynomial& p); |
90 |
|
|
91 |
|
/** Get all coefficients. */ |
92 |
|
std::vector<Integer> coefficients(const UPolynomial& p); |
93 |
|
|
94 |
|
/** Stream the given UPolynomial to an output stream. */ |
95 |
|
std::ostream& operator<<(std::ostream& os, const UPolynomial& p); |
96 |
|
|
97 |
|
/** Check if the polynomial is zero. */ |
98 |
|
bool is_zero(const UPolynomial& p); |
99 |
|
/** Check if the polynomial is one. */ |
100 |
|
bool is_one(const UPolynomial& p); |
101 |
|
/** Check if the polynomial is monic. |
102 |
|
* A polynomial is monic if its leading coefficient is one. |
103 |
|
*/ |
104 |
|
bool is_monic(const UPolynomial& p); |
105 |
|
/** Check if the polynomial is primitive. |
106 |
|
* A polynomial is primitive if the gcd of all coefficients is one and the |
107 |
|
* leading coefficient is positive. |
108 |
|
*/ |
109 |
|
bool is_primitive(const UPolynomial& p); |
110 |
|
|
111 |
|
/** Evaluate a polynomial at an integer. */ |
112 |
|
Integer evaluate_at(const UPolynomial& p, const Integer& i); |
113 |
|
/** Evaluate a polynomial at a rational. */ |
114 |
|
Rational evaluate_at(const UPolynomial& p, const Rational& r); |
115 |
|
/** Evaluate a polynomial at a dyadic rational. */ |
116 |
|
DyadicRational evaluate_at(const UPolynomial& p, const DyadicRational& dr); |
117 |
|
|
118 |
|
/** Determine the sign of a polynomial at an integer. */ |
119 |
|
int sign_at(const UPolynomial& p, const Integer& i); |
120 |
|
/** Determine the sign of a polynomial at a rational. */ |
121 |
|
int sign_at(const UPolynomial& p, const Rational& r); |
122 |
|
/** Determine the sign of a polynomial at a dyadic rational. */ |
123 |
|
int sign_at(const UPolynomial& p, const DyadicRational& dr); |
124 |
|
|
125 |
|
/** Compares two polynomials (using a lexicographic order on the |
126 |
|
* coefficients). */ |
127 |
|
bool operator==(const UPolynomial& lhs, const UPolynomial& rhs); |
128 |
|
/** Compares two polynomials (using a lexicographic order on the |
129 |
|
* coefficients). */ |
130 |
|
bool operator!=(const UPolynomial& lhs, const UPolynomial& rhs); |
131 |
|
/** Compares two polynomials (using a lexicographic order on the |
132 |
|
* coefficients). */ |
133 |
|
bool operator<(const UPolynomial& lhs, const UPolynomial& rhs); |
134 |
|
/** Compares two polynomials (using a lexicographic order on the |
135 |
|
* coefficients). */ |
136 |
|
bool operator<=(const UPolynomial& lhs, const UPolynomial& rhs); |
137 |
|
/** Compares two polynomials (using a lexicographic order on the |
138 |
|
* coefficients). */ |
139 |
|
bool operator>(const UPolynomial& lhs, const UPolynomial& rhs); |
140 |
|
/** Compares two polynomials (using a lexicographic order on the |
141 |
|
* coefficients). */ |
142 |
|
bool operator>=(const UPolynomial& lhs, const UPolynomial& rhs); |
143 |
|
|
144 |
|
/** Compute p(-x). */ |
145 |
|
UPolynomial subst_x_neg(const UPolynomial& p); |
146 |
|
/** Compute -p. */ |
147 |
|
UPolynomial operator-(const UPolynomial& p); |
148 |
|
/** Negate a polynomial in place. */ |
149 |
|
void neg(UPolynomial& p); |
150 |
|
|
151 |
|
/** Add two polynomials. */ |
152 |
|
UPolynomial operator+(const UPolynomial& lhs, const UPolynomial& rhs); |
153 |
|
/** Subtract two polynomials. */ |
154 |
|
UPolynomial operator-(const UPolynomial& lhs, const UPolynomial& rhs); |
155 |
|
/** Multiply two polynomials. */ |
156 |
|
UPolynomial operator*(const UPolynomial& lhs, const UPolynomial& rhs); |
157 |
|
/** Multiply a polynomial and an integer. */ |
158 |
|
UPolynomial operator*(const UPolynomial& lhs, const Integer& rhs); |
159 |
|
/** Multiply an integer and a polynomial. */ |
160 |
|
UPolynomial operator*(const Integer& lhs, const UPolynomial& rhs); |
161 |
|
|
162 |
|
/** Compute lhs^rhs. */ |
163 |
|
UPolynomial pow(const UPolynomial& lhs, long rhs); |
164 |
|
|
165 |
|
/** Compute the first derivative. */ |
166 |
|
UPolynomial derivative(const UPolynomial& p); |
167 |
|
|
168 |
|
/** Check whether lhs divides rhs. */ |
169 |
|
bool divides(const UPolynomial& lhs, const UPolynomial& rhs); |
170 |
|
|
171 |
|
/** Divide all degrees within lhs by rhs. All degrees (with non-zero |
172 |
|
* coefficients) must be divisible by rhs. */ |
173 |
|
UPolynomial div_degrees(const UPolynomial& lhs, long rhs); |
174 |
|
|
175 |
|
/** Divides two polynomials, assuming all necessary inverses can be computed. |
176 |
|
*/ |
177 |
|
UPolynomial div_exact(const UPolynomial& lhs, const UPolynomial& rhs); |
178 |
|
/** Divides a polynomial by an integer, assuming that all coefficients are |
179 |
|
* divisible by rhs. */ |
180 |
|
UPolynomial div_exact(const UPolynomial& lhs, const Integer& rhs); |
181 |
|
/** Computes the remainder of two polynomials, assuming all necessary inverses |
182 |
|
* can be computed. */ |
183 |
|
UPolynomial rem_exact(const UPolynomial& lhs, const UPolynomial& rhs); |
184 |
|
/** Computes the quotient and the remainder of two polynomials, assuming all |
185 |
|
* necessary inverses can be computed. */ |
186 |
|
std::pair<UPolynomial, UPolynomial> div_rem_exact(const UPolynomial& lhs, |
187 |
|
const UPolynomial& rhs); |
188 |
|
/** Performs pseudo-division such that |
189 |
|
* lc(rhs)^(lhs_deg - rhs_deg + 1) * lhs = div * rhs + rem |
190 |
|
* and returns (div, rem). |
191 |
|
*/ |
192 |
|
std::pair<UPolynomial, UPolynomial> div_rem_pseudo(const UPolynomial& lhs, |
193 |
|
const UPolynomial& rhs); |
194 |
|
|
195 |
|
/** Computes the content of a polynomial. |
196 |
|
* The content is the gcd of all coefficients with the sign of the leading |
197 |
|
* coefficient. |
198 |
|
*/ |
199 |
|
Integer content(const UPolynomial& p); |
200 |
|
/** Makes a polynomial primitive in place. |
201 |
|
* A polynomial is primitive if its content is one. |
202 |
|
*/ |
203 |
|
void make_primitive(UPolynomial& p); |
204 |
|
/** Computes the primitive part, that is p / content(p). */ |
205 |
|
UPolynomial primitive_part(const UPolynomial& p); |
206 |
|
|
207 |
|
/** Compute the greatest common divisor. */ |
208 |
|
UPolynomial gcd(const UPolynomial& lhs, const UPolynomial& rhs); |
209 |
|
/** Compute the extended greatest common divisor. */ |
210 |
|
UPolynomial extended_gcd(const UPolynomial& lhs, const UPolynomial& rhs, |
211 |
|
UPolynomial& u, UPolynomial& v); |
212 |
|
/** Solves the equations |
213 |
|
* u * p + v * q = r |
214 |
|
* assuming that gcd(p,q) divides r. |
215 |
|
*/ |
216 |
|
void solve_bezout(const UPolynomial& p, const UPolynomial& q, |
217 |
|
const UPolynomial& r, UPolynomial& u, UPolynomial& v); |
218 |
|
|
219 |
|
/** Compute a square-free factorization of a polynomial. */ |
220 |
|
std::vector<UPolynomial> square_free_factors(const UPolynomial& p, |
221 |
|
bool with_constant = false); |
222 |
|
|
223 |
|
/** Compute the sturm sequence of a polynomial. */ |
224 |
|
std::vector<UPolynomial> sturm_sequence(const UPolynomial& p); |
225 |
|
|
226 |
|
class AlgebraicNumber; |
227 |
|
class RationalInterval; |
228 |
|
|
229 |
|
/** Count the real roots of a polynomial within a rational interval.*/ |
230 |
|
std::size_t count_real_roots(const UPolynomial& p, |
231 |
|
const RationalInterval& ri); |
232 |
|
|
233 |
|
/** Isolate the real roots of a UPolynomial, returning them as algebraic |
234 |
|
* numbers. The roots are sorted in increasing numerical order. |
235 |
|
*/ |
236 |
|
std::vector<AlgebraicNumber> isolate_real_roots(const UPolynomial& p); |
237 |
|
|
238 |
|
} // namespace poly |