1 /*++
2 Copyright (c) 2011 Microsoft Corporation
3 
4 Module Name:
5 
6     upolynomial.cpp
7 
8 Abstract:
9 
10     Goodies for creating and handling univariate polynomials.
11 
12 Author:
13 
14     Leonardo (leonardo) 2011-12-01
15 
16 Notes:
17 
18 --*/
19 #include "math/polynomial/upolynomial.h"
20 #include "util/timeit.h"
21 #include "util/rlimit.h"
22 
tst1()23 static void tst1() {
24     reslimit rl;
25     polynomial::numeral_manager nm;
26     polynomial::manager m(rl, nm);
27     upolynomial::manager um(rl, nm);
28     polynomial_ref x(m);
29     x = m.mk_polynomial(m.mk_var());
30     // create univariate polynomial using multivariate polynomial package
31     polynomial_ref p(m);
32     p = (x - 1)*(x + 1)*(x + 2)*(x + 3)*(x - 3);
33     std::cout << "p: " << p << "\n";
34     // convert p into an univariate polynomial
35     upolynomial::scoped_numeral_vector q(um);
36     um.to_numeral_vector(p, q);
37     std::cout << "q: "; um.display(std::cout, q); std::cout << "\n";
38 
39     std::cout << "degree(q): " << um.degree(q) << "\n";
40 
41     // display coefficients of q
42     std::cout << "expanded q: ";
43     for (unsigned i = 0; i < q.size(); i++)
44         std::cout << nm.to_string(q[i]) << " ";
45     std::cout << "\n";
46 
47     // traverse coefficients of q adding 1
48     for (unsigned i = 0; i < q.size(); i++) {
49         nm.add(q[i], mpz(1), q[i]);
50     }
51     // All operations in upolynomial::manager assume the leading coefficient of q is not zero.
52     // So, if we perform destructive operations on these coefficients, we must execute the "trim" operation
53     // before invoking another operation of upolynomial::manager
54     um.trim(q);
55 
56     // q after adding 1 to all coefficients
57     std::cout << "new q: "; um.display(std::cout, q); std::cout << "\n";
58 
59     // q^2
60     um.mul(q.size(), q.data(), q.size(), q.data(), q);
61     std::cout << "new q^2: "; um.display(std::cout, q); std::cout << "\n";
62 
63     // using pw for (q^2)^3
64     um.pw(q.size(), q.data(), 3, q);
65     std::cout << "new (q^2)^3: "; um.display(std::cout, q); std::cout << "\n";
66 }
67 
tst_isolate_roots(polynomial_ref const & p,unsigned prec,mpbq_manager & bqm,mpbq_vector & roots,mpbq_vector & lowers,mpbq_vector & uppers)68 static void tst_isolate_roots(polynomial_ref const & p, unsigned prec, mpbq_manager & bqm, mpbq_vector & roots, mpbq_vector & lowers, mpbq_vector & uppers) {
69     reslimit rl;
70     upolynomial::manager um(rl, p.m().m());
71     upolynomial::scoped_numeral_vector q(um);
72     um.to_numeral_vector(p, q);
73     std::cout << "isolating roots of: "; um.display(std::cout, q); std::cout << "\n";
74     {
75         timeit timer(true, "isolate time");
76         um.isolate_roots(q.size(), q.data(), bqm, roots, lowers, uppers);
77     }
78 
79     upolynomial::scoped_upolynomial_sequence sseq(um), fseq(um);
80     {
81         timeit timer(true, "sturm time");
82         um.sturm_seq(q.size(), q.data(), sseq);
83         // um.display(std::cout, sseq); std::cout << "\n";
84     }
85 
86     // Fourier sequence is sensitive to repeated roots... we remove them by taking the square free component.
87     upolynomial::scoped_numeral_vector q_sqf(um);
88     {
89         timeit timer(true, "sqf time");
90         um.square_free(q.size(), q.data(), q_sqf);
91         std::cout << "square free part: "; um.display(std::cout, q_sqf); std::cout << "\n";
92     }
93 
94     {
95         timeit timer(true, "fourier time");
96         um.fourier_seq(q_sqf.size(), q_sqf.data(), fseq);
97     }
98 
99     // um.display(std::cout, fseq);
100 
101     std::cout << "num. roots: " << roots.size() + lowers.size() << "\n";
102     std::cout << "sign var(-oo): " << um.sign_variations_at_minus_inf(sseq) << "\n";
103     std::cout << "sign var(+oo): " << um.sign_variations_at_plus_inf(sseq) << "\n";
104     ENSURE(roots.size() + lowers.size() == um.sign_variations_at_minus_inf(sseq) - um.sign_variations_at_plus_inf(sseq));
105     std::cout << "roots:";
106     for (unsigned i = 0; i < roots.size(); i++) {
107         ENSURE(um.eval_sign_at(q.size(), q.data(), roots[i]) == 0);
108         std::cout << " "; bqm.display_decimal(std::cout, roots[i], prec);
109     }
110     {
111         timeit timer(true, "interval check");
112         std::cout << "\n";
113         std::cout << "intervals:";
114         for (unsigned i = 0; i < lowers.size(); i++) {
115             std::cout << " (";
116             bqm.display_decimal(std::cout, lowers[i], prec);
117             std::cout << ", ";
118             bqm.display_decimal(std::cout, uppers[i], prec);
119             std::cout << ")";
120             // Check interval with Sturm sequence. Small detail: Sturm sequence is for close intervals.
121             ENSURE(um.eval_sign_at(q.size(), q.data(), lowers[i]) == 0 ||
122                     um.eval_sign_at(q.size(), q.data(), uppers[i]) == 0 ||
123                     um.sign_variations_at(sseq, lowers[i]) - um.sign_variations_at(sseq, uppers[i]) == 1);
124             // Fourier sequence may also be used to check if the interval is isolating
125             TRACE("upolynomial",
126                   tout << "lowers[i]: " << bqm.to_string(lowers[i]) << "\n";
127                   tout << "uppers[i]: " << bqm.to_string(uppers[i]) << "\n";
128                   tout << "fourier lower: " << um.sign_variations_at(fseq, lowers[i]) << "\n";
129                   tout << "fourier upper: " << um.sign_variations_at(fseq, uppers[i]) << "\n";);
130             unsigned fsv_lower = um.sign_variations_at(fseq, lowers[i]);
131             unsigned fsv_upper = um.sign_variations_at(fseq, uppers[i]);
132             VERIFY(um.eval_sign_at(q.size(), q.data(), lowers[i]) == 0 ||
133                    um.eval_sign_at(q.size(), q.data(), uppers[i]) == 0 ||
134                     // fsv_lower - fsv_upper is an upper bound for the number of roots in the interval
135                     // fsv_upper - fsv_upper - num_roots is even
136                     // Recall that num_roots == 1 in the interval.
137                    (fsv_lower - fsv_upper >= 1 && (fsv_lower - fsv_upper - 1) % 2 == 0));
138 
139             // Double checking using Descartes bounds for the interval
140             // Must use square free component.
141             unsigned dab = um.descartes_bound_a_b(q_sqf.size(), q_sqf.data(), bqm, lowers[i], uppers[i]);
142             TRACE("upolynomial", tout << "Descartes bound: " << dab << "\n";);
143             VERIFY(dab == 1);
144         }
145     }
146     std::cout << "\n";
147 }
148 
tst_isolate_roots(polynomial_ref const & p,unsigned prec=5)149 static void tst_isolate_roots(polynomial_ref const & p, unsigned prec = 5) {
150     mpbq_manager bqm(p.m().m());
151     scoped_mpbq_vector roots(bqm);
152     scoped_mpbq_vector lowers(bqm);
153     scoped_mpbq_vector uppers(bqm);
154     tst_isolate_roots(p, prec, bqm, roots, lowers, uppers);
155 }
156 
check_roots(mpbq_vector const & roots,mpbq_vector const & lowers,mpbq_vector const & uppers,unsigned expected_sz,rational const * expected_roots)157 static void check_roots(mpbq_vector const & roots, mpbq_vector const & lowers, mpbq_vector const & uppers, unsigned expected_sz, rational const * expected_roots) {
158     ENSURE(expected_sz == roots.size() + lowers.size());
159     bool_vector visited;
160     visited.resize(expected_sz, false);
161     for (unsigned i = 0; i < expected_sz; i++) {
162         rational const & r = expected_roots[i];
163         bool found = false;
164         for (unsigned j = 0; j < roots.size(); j++) {
165             if (to_rational(roots[j]) == r) {
166                 ENSURE(!visited[j]);
167                 VERIFY(!found);
168                 found = true;
169                 visited[j] = true;
170             }
171         }
172         for (unsigned j = 0; j < lowers.size(); j++) {
173             unsigned j_prime = j + roots.size();
174             if (to_rational(lowers[j]) < r && r < to_rational(uppers[j])) {
175                 VERIFY(!found);
176                 ENSURE(!visited[j_prime]);
177                 found = true;
178                 visited[j_prime] = true;
179             }
180         }
181         ENSURE(found);
182     }
183 }
184 
tst_isolate_roots(polynomial_ref const & p,unsigned expected_sz,rational const * expected_roots,unsigned prec=5)185 static void tst_isolate_roots(polynomial_ref const & p, unsigned expected_sz, rational const * expected_roots, unsigned prec = 5) {
186     mpbq_manager bqm(p.m().m());
187     scoped_mpbq_vector roots(bqm);
188     scoped_mpbq_vector lowers(bqm);
189     scoped_mpbq_vector uppers(bqm);
190     tst_isolate_roots(p, prec, bqm, roots, lowers, uppers);
191     check_roots(roots, lowers, uppers, expected_sz, expected_roots);
192 }
193 
tst_isolate_roots()194 static void tst_isolate_roots() {
195     reslimit rl;
196     polynomial::numeral_manager nm;
197     polynomial::manager m(rl, nm);
198     polynomial_ref x(m);
199     x = m.mk_polynomial(m.mk_var());
200     // create univariate polynomial using multivariate polynomial package
201     polynomial_ref p(m);
202     p = (x-1)*(x-2);
203     {
204         rational ex[2] = { rational(1), rational(2) };
205         tst_isolate_roots(p, 2, ex);
206     }
207     p = (x-1)*(x-1)*x*x*x;
208     {
209         rational ex[2] = { rational(1), rational(0) };
210         tst_isolate_roots(p, 2, ex);
211     }
212     p = (x^5) - x - 1;
213     {
214         rational ex[1] = { rational(11673039, 10000000) }; // approximated root
215         tst_isolate_roots(p, 1, ex);
216     }
217     p = (x - 1)*(x + 1)*(x + 2)*(x + 3)*((x - 3)^2);
218     {
219         rational ex[5] = { rational(1), rational(-1), rational(-2), rational(-3), rational(3) };
220         tst_isolate_roots(p, 5, ex);
221     }
222     p = (10000*x - 31)*(10000*x - 32);
223     {
224         rational ex[2] = { rational(31, 10000), rational(32, 10000) };
225         tst_isolate_roots(p, 2, ex, 10);
226     }
227     p = (10000*x - 31)*(10000*x - 32)*(10000*x - 33);
228     {
229         rational ex[3] = { rational(31, 10000), rational(32, 10000), rational(33, 10000) };
230         tst_isolate_roots(p, 3, ex, 10);
231     }
232     p = ((x^5) - x - 1)*((x^5) + x - 1)*(1000*x - 1167);
233     {
234         rational ex[3] = { rational(11673039, 10000000), // approximated
235                            rational(75487766, 100000000), // approximated
236                            rational(1167, 1000) };
237         tst_isolate_roots(p, 3, ex, 10);
238     }
239     p = (x - 2)*(x - 4)*(x - 8)*(x - 16)*(x - 32)*(x - 64)*(2*x - 1)*(4*x - 1)*(8*x - 1)*(16*x - 1)*(32*x - 1);
240     {
241         rational ex[11] = { rational(2), rational(4), rational(8), rational(16), rational(32), rational(64),
242                             rational(1, 2), rational(1, 4), rational(1, 8), rational(1, 16), rational(1, 32) };
243         tst_isolate_roots(p, 11, ex, 10);
244     }
245     p = ((x^5) - x - 1)*((x^5) + x - 1)*(1000*x - 1167)*((x^5) - x - 1)*((x^5) + x - 1)*(1000*x - 1167);
246     {
247         rational ex[3] = { rational(11673039, 10000000), // approximated
248                            rational(75487766, 100000000), // approximated
249                            rational(1167, 1000) };
250         tst_isolate_roots(p, 3, ex, 10);
251     }
252     p = (x^17) + 5*(x^16) + 3*(x^15) + 10*(x^13) + 13*(x^10) + (x^9) + 8*(x^5) + 3*(x^2) + 7;
253     {
254         rational ex[3] = { rational(-413582, 100000), // approximated
255                            rational(-170309, 100000), // approximated
256                            rational(-109968, 100000), // approximated
257         };
258         tst_isolate_roots(p, 3, ex, 10);
259     }
260     p = ((x^17) + 5*(x^16) + 3*(x^15) + 10*(x^13) + 13*(x^10) + (x^9) + 8*(x^5) + 3*(x^2) + 7)*(((x^5) - x - 1)^2)*(((x^3) - 2)^2);
261     {
262         rational ex[5] = { rational(-413582, 100000), // approximated
263                            rational(-170309, 100000), // approximated
264                            rational(-109968, 100000), // approximated
265                            rational(11673039, 10000000), // approximated
266                            rational(125992, 100000)  // approximated
267         };
268         tst_isolate_roots(p, 5, ex, 10);
269     }
270     p = (((x^5) - 1000000000)^3)*((3*x - 10000000)^2)*((10*x - 632)^2);
271     {
272         rational ex[3] = { rational(630957, 10000), // approximated
273                            rational(10000000, 3),
274                            rational(632, 10)
275         };
276         tst_isolate_roots(p, 3, ex, 10);
277     }
278 
279 }
280 
tst_remove_one_half()281 static void tst_remove_one_half() {
282     reslimit rl;
283     polynomial::numeral_manager nm;
284     polynomial::manager m(rl, nm);
285     polynomial_ref x(m);
286     x = m.mk_polynomial(m.mk_var());
287     // create univariate polynomial using multivariate polynomial package
288     polynomial_ref p(m), r(m);
289     p = 4*(x^3) - 12*(x^2) - x + 3;
290     r = 16*(x^2) - 40*x - 24;
291     upolynomial::manager um(rl, nm);
292     upolynomial::scoped_numeral_vector _p(um), _q(um), _r(um);
293     um.to_numeral_vector(p, _p);
294     um.to_numeral_vector(r, _r);
295     ENSURE(um.has_one_half_root(_p.size(), _p.data()));
296     um.remove_one_half_root(_p.size(), _p.data(), _q);
297     ENSURE(!um.has_one_half_root(_q.size(), _q.data()));
298     std::cout << "_p: "; um.display(std::cout, _p); std::cout << "\n";
299     std::cout << "_r: "; um.display(std::cout, _r); std::cout << "\n";
300     std::cout << "_q: "; um.display(std::cout, _q); std::cout << "\n";
301     ENSURE(um.eq(_q, _r));
302 
303     p = (((x^5) - 1000000000)^3)*((3*x - 10000000)^2)*((10*x - 632)^2);
304     um.to_numeral_vector(p, _p);
305     ENSURE(!um.has_one_half_root(_p.size(), _p.data()));
306 
307     p = (x - 2)*(x - 4)*(x - 8)*(x - 16)*(x - 32)*(x - 64)*(2*x - 1)*(4*x - 1)*(8*x - 1)*(16*x - 1)*(32*x - 1);
308     um.to_numeral_vector(p, _p);
309     ENSURE(um.has_one_half_root(_p.size(), _p.data()));
310 }
311 
312 template<typename pmanager>
tst_gcd(polynomial_ref const & p,polynomial_ref const & q,pmanager & um)313 static void tst_gcd(polynomial_ref const & p, polynomial_ref const & q, pmanager & um) {
314     typename pmanager::scoped_numeral_vector _p(um.m()), _q(um.m()), _r(um.m());
315     um.to_numeral_vector(p, _p);
316     um.to_numeral_vector(q, _q);
317     std::cout << "_p:  "; um.display(std::cout, _p); std::cout << "\n";
318     std::cout << "_q:  "; um.display(std::cout, _q); std::cout << std::endl;
319     um.gcd(_p.size(), _p.data(), _q.size(), _q.data(), _r);
320     std::cout << "gcd: "; um.display(std::cout, _r); std::cout << "\n";
321     um.subresultant_gcd(_p.size(), _p.data(), _q.size(), _q.data(), _r);
322     std::cout << "_p:  "; um.display(std::cout, _p); std::cout << "\n";
323     std::cout << "_q:  "; um.display(std::cout, _q); std::cout << "\n";
324     std::cout << "subresultant_gcd: "; um.display(std::cout, _r); std::cout << "\n";
325 }
326 
tst_gcd()327 static void tst_gcd() {
328     std::cout << "\n\nTesting GCD\n";
329     reslimit rl;
330     polynomial::numeral_manager nm;
331     polynomial::manager m(rl, nm);
332     polynomial_ref x(m);
333     x = m.mk_polynomial(m.mk_var());
334     // create univariate polynomial using multivariate polynomial package
335     polynomial_ref p(m);
336     polynomial_ref q(m);
337 
338     upolynomial::manager um(rl, nm);
339 
340     p = 13*((x - 3)^6)*((x - 5)^5)*((x - 11)^7);
341     q = derivative(p, 0);
342     tst_gcd(p, q, um);
343 
344     return;
345 
346     p = (x^8) + (x^6) - 3*(x^4) - 3*(x^3) + 8*(x^2) + 2*x - 5;
347     q = 3*(x^6) + 5*(x^4) - 4*(x^2) - 9*x + 21;
348 
349     tst_gcd(p, q, um);
350 
351     p = ((x - 1)^2)*(x - 3)*(x + 2)*((x - 5)^3);
352     q = (x + 1)*(x-1)*((x-3)^2)*(x + 3)*(x - 5);
353     tst_gcd(p, q, um);
354     std::cout << "expected: " << ((x - 1)*(x-3)*(x-5)) << "\n";
355 
356 }
357 
tst_zp()358 static void tst_zp() {
359     std::cout << "\n\nTesting Z_p\n";
360     reslimit rl;
361     polynomial::numeral_manager nm;
362     polynomial::manager m(rl, nm);
363     polynomial_ref x(m);
364     x = m.mk_polynomial(m.mk_var());
365     // create univariate polynomial using multivariate polynomial package
366     polynomial_ref p(m);
367     polynomial_ref q(m);
368     p = (x^4) + 2*(x^3) + 2*(x^2) + x;
369     q = (x^3) + x + 1;
370 
371     // Computing GCD of p an q in Z[x]
372     std::cout << "GCD in Z[x]\n";
373     upolynomial::manager um(rl, nm);
374     tst_gcd(p, q, um);
375 
376     // Computing GCD of p an q in Z_3[x]
377     std::cout << "GCD in Z_3[x]\n";
378     upolynomial::zp_manager um3(rl, nm);
379     um3.set_zp(3);
380     tst_gcd(p, q, um3);
381 }
382 
tst_zp2()383 static void tst_zp2() {
384     std::cout << "\n\nTesting Z_p\n";
385     reslimit rl;
386     polynomial::numeral_manager nm;
387     polynomial::manager m(rl, nm);
388     polynomial_ref x(m);
389     x = m.mk_polynomial(m.mk_var());
390     // create univariate polynomial using multivariate polynomial package
391     polynomial_ref u(m);
392     polynomial_ref v(m);
393     v = (x^6) + 5*(x^5) + 9*(x^4) + 5*(x^2) + 5*x;
394     u = (x^8) + (x^6) + 10*(x^4) + 10*(x^3) + 8*(x^2) + 2*x + 8;
395 
396     // Computing GCD of p an q in Z[x]
397     std::cout << "GCD in Z[x]\n";
398     upolynomial::manager um(rl, nm);
399     tst_gcd(u, v, um);
400 
401     // Computing GCD of p an q in Z_3[x]
402     std::cout << "GCD in Z_13[x]\n";
403     upolynomial::zp_manager um13(rl, nm);
404     um13.set_zp(13);
405     tst_gcd(u, v, um13);
406 }
407 
tst_ext_gcd()408 static void tst_ext_gcd() {
409     std::cout << "\nExtended GCD\n";
410     reslimit rl;
411     polynomial::numeral_manager nm;
412     polynomial::manager m(rl, nm);
413     polynomial_ref x(m);
414     x = m.mk_polynomial(m.mk_var());
415     // create univariate polynomial using multivariate polynomial package
416     polynomial_ref a(m);
417     polynomial_ref b(m);
418     a = (x^6) + 5*(x^5) + 9*(x^4) + 5*(x^2) + 5*x;
419     b = (x^8) + (x^6) + 10*(x^4) + 10*(x^3) + 8*(x^2) + 2*x + 8;
420 
421     // Computing GCD of p an q in Z_3[x]
422     std::cout << "GCD in Z_13[x]\n";
423     upolynomial::zp_manager um(rl, nm);
424     um.set_zp(13);
425     mpzzp_manager & z13 = um.m();
426     upolynomial::zp_manager::scoped_numeral_vector A(z13), B(z13), U(z13), V(z13), D(z13);
427     um.to_numeral_vector(a, A);
428     um.to_numeral_vector(b, B);
429     um.ext_gcd(A.size(), A.data(), B.size(), B.data(), U, V, D);
430     std::cout << "A: "; um.display(std::cout, A); std::cout << "\n";
431     std::cout << "B: "; um.display(std::cout, B); std::cout << "\n";
432     std::cout << "U: "; um.display(std::cout, U); std::cout << "\n";
433     std::cout << "V: "; um.display(std::cout, V); std::cout << "\n";
434     std::cout << "D: "; um.display(std::cout, D); std::cout << "\n";
435 }
436 
tst_ext_gcd_z7()437 static void tst_ext_gcd_z7() {
438     std::cout << "\nExtended GCD in Z_7\n";
439     reslimit rl;
440     polynomial::numeral_manager nm;
441     polynomial::manager m(rl, nm);
442     polynomial_ref x(m);
443     x = m.mk_polynomial(m.mk_var());
444     // create univariate polynomial using multivariate polynomial package
445     polynomial_ref a(m);
446     polynomial_ref b(m);
447 
448     a = (x^3) + 2;
449     b = 6*(x^2) + 6;
450 
451     // Computing GCD of a and b in Z_3[x]
452     // expecting: D = 1, U = 3*x + 6, V = 3*x^2 + 6*x + 4
453     std::cout << "GCD in Z_7[x]\n";
454     upolynomial::zp_manager um(rl, nm);
455     um.set_zp(7);
456     mpzzp_manager & z7 = um.m();
457     upolynomial::zp_manager::scoped_numeral_vector A(z7), B(z7), U(z7), V(z7), D(z7);
458     um.to_numeral_vector(a, A);
459     um.to_numeral_vector(b, B);
460     um.ext_gcd(A.size(), A.data(), B.size(), B.data(), U, V, D);
461     std::cout << "A: "; um.display(std::cout, A); std::cout << "\n";
462     std::cout << "B: "; um.display(std::cout, B); std::cout << "\n";
463     std::cout << "U: "; um.display(std::cout, U); std::cout << "\n";
464     std::cout << "V: "; um.display(std::cout, V); std::cout << "\n";
465     std::cout << "D: "; um.display(std::cout, D); std::cout << "\n";
466 }
467 
tst_sturm()468 static void tst_sturm() {
469     std::cout << "\nSturm Seq\n";
470     reslimit rl;
471     polynomial::numeral_manager nm;
472     polynomial::manager m(rl, nm);
473     polynomial_ref x(m);
474     x = m.mk_polynomial(m.mk_var());
475     // create univariate polynomial using multivariate polynomial package
476     polynomial_ref p(m);
477     p = 7*(x^10) + 3*(x^9) + (x^8) + (x^6) + 10*(x^4) + 10*(x^3) + 8*(x^2) + 2*x + 8;
478     // p = ((x^17) + 5*(x^16) + 3*(x^15) + 10*(x^13) + 13*(x^10) + (x^9) + 8*(x^5) + 3*(x^2) + 7)*(((x^5) - x - 1)^2)*(((x^3) - 2)^2);
479     // p = ((x^17) + 5*(x^16) + 3*(x^15) + 10*(x^13) + 13*(x^10) + (x^9) + 8*(x^5) + 3*(x^2) + 7)*(((x^5) - x - 1))*(((x^3) - 2));
480 
481     upolynomial::manager um(rl, nm);
482     upolynomial::scoped_numeral_vector _p(um);
483     upolynomial::scoped_upolynomial_sequence seq2(um);
484     um.to_numeral_vector(p, _p);
485     um.sturm_seq(_p.size(), _p.data(), seq2);
486     std::cout << "upolynomial sturm seq...\n";
487     um.display(std::cout, seq2);
488 }
489 
490 
tst_refinable(polynomial_ref const & p,mpbq_manager & bqm,mpbq & a,mpbq & b)491 static void tst_refinable(polynomial_ref const & p, mpbq_manager & bqm, mpbq & a, mpbq & b) {
492     reslimit rl;
493     upolynomial::manager um(rl, p.m().m());
494     upolynomial::scoped_numeral_vector _p(um);
495     um.to_numeral_vector(p, _p);
496     std::cout << "before (" << bqm.to_string(a) << ", " << bqm.to_string(b) << ")\n";
497     bool r = um.isolating2refinable(_p.size(), _p.data(), bqm, a, b);
498     if (r) {
499         std::cout << "new (" << bqm.to_string(a) << ", " << bqm.to_string(b) << ")\n";
500         int sign_a = um.eval_sign_at(_p.size(), _p.data(), a);
501         int sign_b = um.eval_sign_at(_p.size(), _p.data(), b);
502         VERIFY(sign_a != 0 && sign_b != 0 && sign_a == -sign_b);
503     }
504     else {
505         std::cout << "new root: " << bqm.to_string(a) << "\n";
506         ENSURE(um.eval_sign_at(_p.size(), _p.data(), a) == 0);
507     }
508 }
509 
tst_refinable()510 static void tst_refinable() {
511     std::cout << "\nRefinable intervals\n";
512     reslimit rl;
513     polynomial::numeral_manager nm;
514     polynomial::manager m(rl, nm);
515     polynomial_ref x(m);
516     x = m.mk_polynomial(m.mk_var());
517     // create univariate polynomial using multivariate polynomial package
518     polynomial_ref p(m);
519     p = (x - 1)*(4*x - 11)*(x - 3);
520     std::cout << "p: " << p << "\n";
521     mpbq_manager bqm(nm);
522     mpbq a(1);
523     mpbq b(3);
524     tst_refinable(p, bqm, a, b);
525     bqm.set(a, 2);
526     bqm.set(b, 3);
527     tst_refinable(p, bqm, a, b);
528     bqm.set(a, 5, 1);
529     bqm.set(b, 3);
530     tst_refinable(p, bqm, a, b);
531 
532     p = (x - 1)*(5*x - 11)*(x - 3);
533     std::cout << "p: " << p << "\n";
534     bqm.set(a, 1);
535     bqm.set(b, 3);
536     tst_refinable(p, bqm, a, b);
537     bqm.set(a, 2);
538     bqm.set(b, 3);
539     tst_refinable(p, bqm, a, b);
540     bqm.set(a, 3, 1);
541     bqm.set(b, 3);
542     tst_refinable(p, bqm, a, b);
543     bqm.set(a, 1);
544     bqm.set(b, 5, 1);
545     tst_refinable(p, bqm, a, b);
546     bqm.set(a, 3, 1);
547     bqm.set(b, 5, 1);
548     tst_refinable(p, bqm, a, b);
549 
550     p = (x - 1)*(x - 2)*(x - 3);
551     std::cout << "p: " << p << "\n";
552     bqm.set(a, 1);
553     bqm.set(b, 3);
554     tst_refinable(p, bqm, a, b);
555 
556     bqm.del(a); bqm.del(b);
557 }
558 
tst_refine(polynomial_ref const & p,mpbq_manager & bqm,mpbq & a,mpbq & b,unsigned prec_k=100)559 static void tst_refine(polynomial_ref const & p, mpbq_manager & bqm, mpbq & a, mpbq & b, unsigned prec_k=100) {
560     reslimit rl; upolynomial::manager um(rl, p.m().m());
561     upolynomial::scoped_numeral_vector _p(um);
562     um.to_numeral_vector(p, _p);
563     std::cout << "before (" << bqm.to_string(a) << ", " << bqm.to_string(b) << ")\n";
564     bool r = um.refine(_p.size(), _p.data(), bqm, a, b, prec_k);
565     if (r) {
566         std::cout << "new (" << bqm.to_string(a) << ", " << bqm.to_string(b) << ")\n";
567         std::cout << "as decimal: "; bqm.display_decimal(std::cout, a, prec_k); std::cout << "\n";
568     }
569     else {
570         std::cout << "new root: " << bqm.to_string(a) << "\n";
571         std::cout << "as decimal: "; bqm.display_decimal(std::cout, a, prec_k); std::cout << "\n";
572     }
573 }
574 
tst_refine()575 static void tst_refine() {
576     std::cout << "\nRefining intervals\n";
577     reslimit rl;
578     polynomial::numeral_manager nm;
579     polynomial::manager m(rl, nm);
580     polynomial_ref x(m);
581     x = m.mk_polynomial(m.mk_var());
582     // create univariate polynomial using multivariate polynomial package
583     polynomial_ref p(m);
584     p = (x^5) - x - 1;
585     std::cout << "p: " << p << "\n";
586     mpbq_manager bqm(nm);
587     scoped_mpbq a(bqm), b(bqm);
588     a = 1;
589     b = 2;
590     tst_refine(p, bqm, a, b, 20);
591 
592     p = (x^2) - 2;
593     std::cout << "p: " << p << "\n";
594     a = 1;
595     b = 2;
596     tst_refine(p, bqm, a, b, 200);
597 }
598 
tst_translate_q()599 static void tst_translate_q() {
600     reslimit rl;
601     unsynch_mpq_manager nm;
602     polynomial::manager m(rl, nm);
603     polynomial_ref x(m);
604     x = m.mk_polynomial(m.mk_var());
605     // create univariate polynomial using multivariate polynomial package
606     polynomial_ref p(m);
607     p = (x-1)*(x-2)*(x-3)*(x-4);
608     upolynomial::manager um(rl, nm);
609     upolynomial::scoped_numeral_vector _p(um), _q(um);
610     um.to_numeral_vector(p, _p);
611     ENSURE(um.eval_sign_at(_p.size(), _p.data(), mpq(1)) == 0);
612     ENSURE(um.eval_sign_at(_p.size(), _p.data(), mpq(2)) == 0);
613     ENSURE(um.eval_sign_at(_p.size(), _p.data(), mpq(3)) == 0);
614     ENSURE(um.eval_sign_at(_p.size(), _p.data(), mpq(4)) == 0);
615     ENSURE(um.eval_sign_at(_p.size(), _p.data(), mpq(-1)) != 0);
616     ENSURE(um.eval_sign_at(_p.size(), _p.data(), mpq(5)) != 0);
617     ENSURE(um.eval_sign_at(_p.size(), _p.data(), mpq(-2)) != 0);
618     scoped_mpq c(nm);
619     nm.set(c, 1, 3);
620     scoped_mpq r1(nm);
621     r1 = 1;
622     r1 -= c;
623     scoped_mpq r2(nm);
624     r2 = 3;
625     r2 -= c;
626     ENSURE(um.eval_sign_at(_p.size(), _p.data(), r1) != 0);
627     ENSURE(um.eval_sign_at(_p.size(), _p.data(), r2) != 0);
628     std::cout << "p: "; um.display(std::cout, _p); std::cout << "\n";
629     um.translate_q(_p.size(), _p.data(), c, _q);
630     std::cout << "q: "; um.display(std::cout, _q); std::cout << "\n";
631     ENSURE(um.eval_sign_at(_q.size(), _q.data(), mpq(1)) != 0);
632     ENSURE(um.eval_sign_at(_q.size(), _q.data(), mpq(2)) != 0);
633     ENSURE(um.eval_sign_at(_q.size(), _q.data(), mpq(3)) != 0);
634     ENSURE(um.eval_sign_at(_q.size(), _q.data(), mpq(4)) != 0);
635     ENSURE(um.eval_sign_at(_q.size(), _q.data(), mpq(-1)) != 0);
636     ENSURE(um.eval_sign_at(_q.size(), _q.data(), mpq(5)) != 0);
637     ENSURE(um.eval_sign_at(_q.size(), _q.data(), mpq(-2)) != 0);
638     ENSURE(um.eval_sign_at(_q.size(), _q.data(), r1) == 0);
639     ENSURE(um.eval_sign_at(_q.size(), _q.data(), r2) == 0);
640     um.p_1_div_x(_p.size(), _p.data());
641     std::cout << "p: "; um.display(std::cout, _p); std::cout << "\n";
642     ENSURE(um.eval_sign_at(_p.size(), _p.data(), mpq(1)) == 0);
643     nm.set(c, 1, 2);
644     ENSURE(um.eval_sign_at(_p.size(), _p.data(), c) == 0);
645     nm.set(c, 1, 3);
646     ENSURE(um.eval_sign_at(_p.size(), _p.data(), c) == 0);
647     nm.set(c, 1, 4);
648     ENSURE(um.eval_sign_at(_p.size(), _p.data(), c) == 0);
649     ENSURE(um.eval_sign_at(_p.size(), _p.data(), mpq(2)) != 0);
650     ENSURE(um.eval_sign_at(_p.size(), _p.data(), mpq(3)) != 0);
651     ENSURE(um.eval_sign_at(_p.size(), _p.data(), mpq(4)) != 0);
652 }
653 
tst_convert_q2bq(unsynch_mpq_manager & m,polynomial_ref const & p,mpq const & a,mpq const & b)654 static void tst_convert_q2bq(unsynch_mpq_manager & m, polynomial_ref const & p, mpq const & a, mpq const & b) {
655     reslimit rl;
656     upolynomial::manager um(rl, m);
657     upolynomial::scoped_numeral_vector _p(um);
658     um.to_numeral_vector(p, _p);
659     std::cout << "\np: ";
660     um.display(std::cout, _p); std::cout << "\n";
661     std::cout << "before (" << m.to_string(a) << ", " << m.to_string(b) << ") (";
662     m.display_decimal(std::cout, a, 10); std::cout << ", "; m.display_decimal(std::cout, b, 10); std::cout << ")\n";
663     mpbq_manager bqm(m);
664     scoped_mpbq c(bqm);
665     scoped_mpbq d(bqm);
666     if (!um.convert_q2bq_interval(_p.size(), _p.data(), a, b, bqm, c, d)) {
667         std::cout << "found root: " << c << "\n";
668     }
669     else {
670         std::cout << "after (" << c << ", " << d << ")" << " (";
671         bqm.display_decimal(std::cout, c, 10); std::cout << ", "; bqm.display_decimal(std::cout, d, 10); std::cout << ")\n";
672     }
673 }
674 
tst_convert_q2bq()675 static void tst_convert_q2bq() {
676     reslimit rl;
677     unsynch_mpq_manager nm;
678     polynomial::manager m(rl, nm);
679     polynomial_ref x(m);
680     x = m.mk_polynomial(m.mk_var());
681     // create univariate polynomial using multivariate polynomial package
682     polynomial_ref p(m);
683     p = (x-1)*(x-2)*(x-3)*(x-4);
684     scoped_mpq a(nm), b(nm);
685 
686     nm.set(a, 1, 3);
687     nm.set(b, 7, 5);
688     tst_convert_q2bq(nm, p, a, b);
689 
690     nm.set(a, 1, 2);
691     nm.set(b, 7, 5);
692     tst_convert_q2bq(nm, p, a, b);
693 
694     nm.set(a, 3, 7);
695     nm.set(b, 3, 2);
696     tst_convert_q2bq(nm, p, a, b);
697 
698     nm.set(a, 0);
699     nm.set(b, 3, 2);
700     tst_convert_q2bq(nm, p, a, b);
701 
702     nm.set(a, 0);
703     nm.set(b, 23, 21);
704     tst_convert_q2bq(nm, p, a, b);
705 
706     nm.set(a, 7, 2);
707     nm.set(b, 5);
708     tst_convert_q2bq(nm, p, a, b);
709 
710     nm.set(a, 999,  1000);
711     nm.set(b, 1001, 1000);
712     tst_convert_q2bq(nm, p, a, b);
713 
714     nm.set(a, 9999,  10000);
715     nm.set(b, 10001, 10000);
716     tst_convert_q2bq(nm, p, a, b);
717 
718     nm.set(a, 39999,  10000);
719     nm.set(b, 40001,  10000);
720     tst_convert_q2bq(nm, p, a, b);
721 }
722 
tst_sturm2()723 static void tst_sturm2() {
724     reslimit rl;
725     polynomial::numeral_manager nm;
726     polynomial::manager m(rl, nm);
727     polynomial_ref x(m);
728     x = m.mk_polynomial(m.mk_var());
729     // create univariate polynomial using multivariate polynomial package
730     polynomial_ref p(m);
731     polynomial_ref q(m);
732 
733     p = (x^16) - 136*(x^14) + 6476*(x^12) - 141912*(x^10) + 1513334*(x^8) - 7453176*(x^6) + 13950764*(x^4) - 5596840*(x^2) + 46225;
734     q = ((x^8) - 40*(x^6) + 352*(x^4) - 960*(x^2) + 576)^2;
735 
736     upolynomial::manager um(rl, nm);
737     upolynomial::scoped_numeral_vector _p(um), _q(um);
738     upolynomial::scoped_upolynomial_sequence seq2(um);
739     um.to_numeral_vector(p, _p);
740     um.to_numeral_vector(q, _q);
741     um.sturm_tarski_seq(_p.size(), _p.data(), _q.size(), _q.data(), seq2);
742 
743     std::cout << "upolynomial sturm seq...\n";
744     um.display(std::cout, seq2);
745 }
746 
747 #if 0
748 static void tst_isolate_roots2() {
749     polynomial::numeral_manager nm;
750     polynomial::manager m(nm);
751     polynomial_ref x(m);
752     x = m.mk_polynomial(m.mk_var());
753     // create univariate polynomial using multivariate polynomial package
754     polynomial_ref p(m);
755     p = (2*x - 1)*(x - 21)*(x + 12)*(x - 19)*(x + 11)*(x + 34)*(x - 9)*(x - 72)*(10000*x - 4999)*((x^5) - x - 1)*((x^2) - 2)*((x^2) - 3)*((x^7) - 3)*((x^101) - 3);
756     {
757         tst_isolate_roots(p, 10);
758     }
759 }
760 
761 static void tst_isolate_roots3() {
762     polynomial::numeral_manager nm;
763     polynomial::manager m(nm);
764     polynomial_ref x1(m), x2(m), x3(m), x4(m), x5(m), x6(m), x(m);
765     x  = m.mk_polynomial(m.mk_var());
766     x1 = m.mk_polynomial(m.mk_var());
767     x2 = m.mk_polynomial(m.mk_var());
768     x3 = m.mk_polynomial(m.mk_var());
769     x4 = m.mk_polynomial(m.mk_var());
770     x5 = m.mk_polynomial(m.mk_var());
771     x6 = m.mk_polynomial(m.mk_var());
772     // create univariate polynomial using multivariate polynomial package
773     polynomial_ref p1(m);
774     polynomial_ref p2(m);
775     polynomial_ref p3(m);
776     polynomial_ref p4(m);
777     polynomial_ref p5(m);
778     polynomial_ref p6(m);
779     polynomial_ref q(m);
780     polynomial_ref r(m);
781     p1 = ((x1^2) - 2);
782     p2 = ((x2^2) - 3);
783     p3 = ((x3^2) - 5);
784     p4 = ((x4^2) - 7);
785     p5 = ((x5^2) - 11);
786     p6 = ((x6^2) - 13);
787     q = (x - x1 - x2 - x3 - x4 - x5 - x6);
788     r = resultant(resultant(resultant(resultant(resultant(resultant(q, p1, 1), p2, 2), p3, 3), p4, 4), p5, 5), p6, 6);
789     std::cout << "r: " << r << "\n";
790     {
791         timeit timer(true, "isolate");
792         tst_isolate_roots(r, 10);
793     }
794 }
795 
796 static void tst_gcd2() {
797     polynomial::numeral_manager nm;
798     polynomial::manager m(nm);
799     polynomial_ref x(m);
800     x = m.mk_polynomial(m.mk_var());
801     // create univariate polynomial using multivariate polynomial package
802     polynomial_ref p(m);
803     p = ((x^1000) - x + 1)^5;
804 
805     reslimit rl; upolynomial::manager um(rl, nm);
806     upolynomial::scoped_numeral_vector _p(um);
807     upolynomial::scoped_numeral_vector _p_sqf(um);
808     um.to_numeral_vector(p, _p);
809     {
810         timeit timer(true, "gcd");
811         um.square_free(_p.size(), _p.c_ptr(), _p_sqf);
812     }
813     um.display(std::cout, _p_sqf.size(), _p_sqf.c_ptr()); std::cout << "\n";
814 }
815 #endif
816 
tst_isolate_roots5()817 static void tst_isolate_roots5() {
818     reslimit rl;
819     polynomial::numeral_manager nm;
820     polynomial::manager m(rl, nm);
821     polynomial_ref x(m);
822     x = m.mk_polynomial(m.mk_var());
823     // create univariate polynomial using multivariate polynomial package
824     polynomial_ref p(m);
825     p = (x^70) - 6*(x^65) - (x^60) + 60*(x^55) - 54*(x^50) - 230*(x^45) + 274*(x^40) + 542*(x^35) - 615*(x^30)
826         - 1120*(x^25) + 1500*(x^20) - 160*(x^15) - 395*(x^10) + 76*(x^5) + 34;
827     {
828         tst_isolate_roots(p, 10);
829     }
830 }
831 
tst_exact_div(polynomial_ref const & p1,polynomial_ref const & p2,bool expected,polynomial_ref const & expected_q)832 static void tst_exact_div(polynomial_ref const & p1, polynomial_ref const & p2, bool expected, polynomial_ref const & expected_q) {
833     reslimit rl;
834     upolynomial::manager um(rl, p1.m().m());
835     upolynomial::scoped_numeral_vector _p1(um), _p2(um), _q(um), _r(um);
836     um.to_numeral_vector(p1, _p1);
837     um.to_numeral_vector(p2, _p2);
838     if (expected)
839         um.to_numeral_vector(expected_q, _q);
840     std::cout << "------\n";
841     std::cout << "p1: "; um.display(std::cout, _p1); std::cout << "\n";
842     std::cout << "p2: "; um.display(std::cout, _p2); std::cout << std::endl;
843     bool res = um.exact_div(_p1.size(), _p1.data(), _p2.size(), _p2.data(), _r);
844     if (res) {
845         std::cout << "r:  "; um.display(std::cout, _r); std::cout << "\n";
846     }
847     if (expected) {
848         std::cout << "expected:  "; um.display(std::cout, _q); std::cout << "\n";
849     }
850     std::cout.flush();
851     ENSURE(res == expected);
852     ENSURE(expected == um.divides(_p1.size(), _p1.data(), _p2.size(), _p2.data()));
853     ENSURE(!expected || um.eq(_r, _q));
854 }
855 
tst_exact_div()856 static void tst_exact_div() {
857     reslimit rl;
858     polynomial::numeral_manager nm;
859     polynomial::manager m(rl, nm);
860     polynomial_ref x(m);
861     x = m.mk_polynomial(m.mk_var());
862     // create univariate polynomial using multivariate polynomial package
863     polynomial_ref p(m);
864     tst_exact_div((x - 1)*(x - 2)*(x - 3), (x-2)*(x-1), true, (x-3));
865     tst_exact_div((x - 1)*(2*x - 4)*(x - 3), (x-2)*(x-1), true, (2*x-6));
866     tst_exact_div((x - 1)*(2*x - 4)*(x - 3), (x-2)*(x-1)*(x-4), false, x);
867     tst_exact_div((x - 3), (x-1), false, x);
868     polynomial_ref z(m);
869     z = m.mk_const(rational(0));
870     tst_exact_div(z, (x-2)*(x-1)*(x-4), true, z);
871     tst_exact_div((x-2)*(x-1)*(x-4), z, false, z);
872     tst_exact_div(z, z, false, z);
873     polynomial_ref two(m);
874     two = m.mk_const(rational(2));
875     tst_exact_div((2*x - 2), (x-1), true, two);
876     tst_exact_div((2*x - 2), (4*x-4), false, two);
877     tst_exact_div((6*x - 4), two, true, (3*x - 2));
878 }
879 
tst_fact(polynomial_ref const & p,unsigned num_distinct_factors,upolynomial::factor_params const & params=upolynomial::factor_params ())880 static void tst_fact(polynomial_ref const & p, unsigned num_distinct_factors, upolynomial::factor_params const & params = upolynomial::factor_params()) {
881     ENSURE(is_univariate(p));
882     std::cout << "---------------\n";
883     std::cout << "p: " << p << std::endl;
884     reslimit rl; upolynomial::manager um(rl, p.m().m());
885     upolynomial::scoped_numeral_vector _p(um);
886     upolynomial::factors fs(um);
887     um.to_numeral_vector(p, _p);
888     um.factor(_p, fs, params);
889     std::cout << "factors:\n";
890     std::cout << um.m().to_string(fs.get_constant()) << "\n";
891     for (unsigned i = 0; i < fs.distinct_factors(); i++) {
892         std::cout << "*("; um.display(std::cout, fs[i]); std::cout << ")^" << fs.get_degree(i) << std::endl;
893     }
894     std::cout << fs.distinct_factors() << " " << num_distinct_factors << "\n";
895     ENSURE(fs.distinct_factors() == num_distinct_factors);
896     upolynomial::scoped_numeral_vector _r(um);
897     fs.multiply(_r);
898     TRACE("upolynomial", tout << "_r: "; um.display(tout, _r); tout << "\n_p: "; um.display(tout, _p); tout << "\n";);
899     ENSURE(um.eq(_p, _r));
900 }
901 
tst_fact()902 static void tst_fact() {
903     reslimit rl;
904     polynomial::numeral_manager nm;
905     polynomial::manager m(rl, nm);
906     polynomial_ref x0(m);
907     x0 = m.mk_polynomial(m.mk_var());
908     tst_fact((x0^4) + (x0^2) - 20, 3);
909     tst_fact((x0^4) + (x0^2) - 20, 1, upolynomial::factor_params(5, 1, 1000));
910     tst_fact((x0^4) + (x0^2) - 20, 1, upolynomial::factor_params(7, 1, 1000));
911     tst_fact((x0^70) - 6*(x0^65) - (x0^60) + 60*(x0^55) - 54*(x0^50) - 230*(x0^45) + 274*(x0^40) + 542*(x0^35) - 615*(x0^30) - 1120*(x0^25) + 1500*(x0^20) - 160*(x0^15) - 395*(x0^10) + 76*(x0^5) + 34, 1, upolynomial::factor_params(3, 1, 20));
912     tst_fact((x0^70) - 6*(x0^65) - (x0^60) + 60*(x0^55) - 54*(x0^50) - 230*(x0^45) + 274*(x0^40) + 542*(x0^35) - 615*(x0^30) - 1120*(x0^25) + 1500*(x0^20) - 160*(x0^15) - 395*(x0^10) + 76*(x0^5) + 34, 1, upolynomial::factor_params(3, 1, 72));
913     tst_fact((x0^70) - 6*(x0^65) - (x0^60) + 60*(x0^55) - 54*(x0^50) - 230*(x0^45) + 274*(x0^40) + 542*(x0^35) - 615*(x0^30) - 1120*(x0^25) + 1500*(x0^20) - 160*(x0^15) - 395*(x0^10) + 76*(x0^5) + 34, 1, upolynomial::factor_params(3, 1, 80));
914     tst_fact( (x0^10) - 10*(x0^8) + 38*(x0^6) - 2*(x0^5) - 100*(x0^4) - 40*(x0^3) + 121*(x0^2) - 38*x0 - 17, 1);
915     tst_fact( (x0^4) - 404*(x0^2) + 39204, 2);
916     tst_fact(((x0^5) - (x0^2) + 1)*((-1)*x0 + 1)*((x0^2) - 2*x0 + 3), 3);
917     tst_fact((x0^4) + (x0^2) - 20, 3);
918     tst_fact((-11)*((x0^5) - (x0^2) + 1)*((-1)*x0 + 1)*((x0^2) - 2*x0 + 3), 3);
919     tst_fact(x0 - 2*(x0^2) + 1, 2);
920     tst_fact(13*((x0 - 3)^6)*((x0 - 5)^5)*((x0 - 11)^7), 3);
921     tst_fact((x0+1)^30, 1);
922     tst_fact((x0^70) - 6*(x0^65) - (x0^60) + 60*(x0^55) - 54*(x0^50) - 230*(x0^45) + 274*(x0^40) + 542*(x0^35) - 615*(x0^30) - 1120*(x0^25) + 1500*(x0^20) - 160*(x0^15) - 395*(x0^10) + 76*(x0^5) + 34, 3);
923     tst_fact(((x0^4) - 8*(x0^2)), 2);
924     tst_fact((x0^5) - 2*(x0^3) + x0 - 1, 1);
925     tst_fact( (x0^25) - 4*(x0^21) - 5*(x0^20) + 6*(x0^17) + 11*(x0^16) + 10*(x0^15) - 4*(x0^13) - 7*(x0^12) - 9*(x0^11) - 10*(x0^10) +
926                (x0^9) + (x0^8) + (x0^7) + (x0^6) + 3*(x0^5) + x0 - 1, 2);
927     tst_fact( (x0^25) - 10*(x0^21) - 10*(x0^20) - 95*(x0^17) - 470*(x0^16) - 585*(x0^15) - 40*(x0^13) - 1280*(x0^12) - 4190*(x0^11) - 3830*(x0^10) + 400*(x0^9)+ 1760*(x0^8) + 760*(x0^7) - 2280*(x0^6) + 449*(x0^5) + 640*(x0^3) - 640*(x0^2) + 240*x0 - 32, 2);
928     tst_fact( x0^10, 1);
929     tst_fact( (x0^2) - 1, 2);
930     tst_fact( (-2)*(x0^2) + 2, 2);
931     polynomial_ref zero(m);
932     polynomial_ref three(m);
933     zero = m.mk_zero();
934     three = m.mk_const(rational(3));
935     tst_fact(zero, 0);
936     tst_fact(three, 0);
937     tst_fact(x0 + 1, 1);
938     tst_fact(x0 - 1, 1);
939     tst_fact((-1)*x0 - 1, 1);
940     tst_fact((-1)*x0 + 1, 1);
941     tst_fact( (x0^10) - 10*(x0^8) + 38*(x0^6) - 2*(x0^5) - 100*(x0^4) - 40*(x0^3) + 121*(x0^2) - 38*x0 - 17, 1);
942     tst_fact( (x0^50) - 10*(x0^40) + 38*(x0^30) - 2*(x0^25) - 100*(x0^20) - 40*(x0^15) + 121*(x0^10) - 38*(x0^5) - 17, 1);
943 
944     tst_fact(        (((x0^5)  +  5*(x0^4) +  10*(x0^3) + 10*(x0^2) + 5*x0)^10)
945                  + 10*(((x0^5)  +  5*(x0^4) +  10*(x0^3) + 10*(x0^2) + 5*x0)^9)
946                  + 35*(((x0^5)  +  5*(x0^4) +  10*(x0^3) + 10*(x0^2) + 5*x0)^8)
947                  + 40*(((x0^5)  +  5*(x0^4) +  10*(x0^3) + 10*(x0^2) + 5*x0)^7)
948                  - 32*(((x0^5)  +  5*(x0^4) +  10*(x0^3) + 10*(x0^2) + 5*x0)^6)
949                  - 82*(((x0^5)  +  5*(x0^4) +  10*(x0^3) + 10*(x0^2) + 5*x0)^5)
950                  - 30*(((x0^5)  +  5*(x0^4) +  10*(x0^3) + 10*(x0^2) + 5*x0)^4)
951                  - 140*(((x0^5) + 5*(x0^4) +   10*(x0^3) + 10*(x0^2) + 5*x0)^3)
952                  - 284*(((x0^5) + 5*(x0^4) +   10*(x0^3) + 10*(x0^2) + 5*x0)^2)
953                  - 168*((x0^5)  + 5*(x0^4) +   10*(x0^3) + 10*(x0^2) + 5*x0)
954                  - 47, 1);
955 
956     tst_fact( (x0^4) - 404*(x0^2) + 39204, 2);
957     tst_fact( ((x0^5) - 15552)*
958               ((x0^20)- 15708*(x0^15) + rational("138771724")*(x0^10)- rational("432104148432")*(x0^5) + rational("614198284585616")),
959               2);
960     tst_fact( (x0^25) -
961               rational("3125")*(x0^21) -
962               rational("15630")*(x0^20) +
963               rational("3888750")*(x0^17) +
964               rational("38684375")*(x0^16) +
965               rational("95765635")*(x0^15) -
966               rational("2489846500")*(x0^13) -
967               rational("37650481875")*(x0^12) -
968               rational("190548065625")*(x0^11) -
969               rational("323785250010")*(x0^10) +
970               rational("750249453025")*(x0^9) +
971               rational("14962295699875")*(x0^8) +
972               rational("111775113235000")*(x0^7) +
973               rational("370399286731250")*(x0^6) +
974               rational("362903064503129")*(x0^5) -
975               rational("2387239013984400")*(x0^4) -
976               rational("23872390139844000")*(x0^3) -
977               rational("119361950699220000")*(x0^2) -
978               rational("298404876748050000")*x0 -
979               rational("298500366308609376"), 2);
980 
981     tst_fact( rational("54")*(x0^24) - (x0^27) - 324*(x0^21) + rational("17496")*(x0^18) - 34992*(x0^15)+ rational("1889568")*(x0^12)- 1259712*(x0^9) + rational("68024448")*(x0^6), 3);
982 
983     tst_fact( ((x0^3)- 432)*(((x0^3)+54)^2)*((x0^6)+108)*((x0^6)+6912)*((x0^6)- 324*(x0^3)+37044),
984                5);
985 
986     tst_fact( ((x0^6)- 6*(x0^4) - 864*(x0^3) + 12*(x0^2) - 5184*x0 + 186616)*
987               (((x0^6) - 6*(x0^4) + 108*(x0^3) + 12*(x0^2) + 648*x0 + 2908)^2)*
988               ((x0^12) - 12*(x0^10) + 60*(x0^8) + 56*(x0^6) + 6720*(x0^4) + 12768*(x0^2) + 13456)*
989               ((x0^12) - 12*(x0^10) + 60*(x0^8) + 13664*(x0^6) + 414960*(x0^4) + 829248*(x0^2) + 47886400)*
990               ((x0^12) - 12*(x0^10) - 648*(x0^9)+ 60*(x0^8) + 178904*(x0^6) + 15552*(x0^5) + 1593024*(x0^4) - 24045984*(x0^3) +
991                5704800*(x0^2) - 143995968*x0 + 1372010896),
992               5);
993 }
994 
tst_rem(polynomial_ref const & p,polynomial_ref const & q,polynomial_ref const & expected)995 static void tst_rem(polynomial_ref const & p, polynomial_ref const & q, polynomial_ref const & expected) {
996     ENSURE(is_univariate(p));
997     ENSURE(is_univariate(q));
998     std::cout << "---------------\n";
999     std::cout << "p: " << p << std::endl;
1000     std::cout << "q: " << q << std::endl;
1001     reslimit rl; upolynomial::manager um(rl, p.m().m());
1002     upolynomial::scoped_numeral_vector _p(um), _q(um), _r(um);
1003     um.to_numeral_vector(p, _p);
1004     um.to_numeral_vector(q, _q);
1005     um.rem(_p.size(), _p.data(), _q.size(), _q.data(), _r);
1006     polynomial_ref r(p.m());
1007     r = p.m().to_polynomial(_r.size(), _r.data(), 0);
1008     std::cout << "r: " << r << std::endl;
1009     ENSURE(eq(expected, r));
1010 }
1011 
tst_rem()1012 static void tst_rem() {
1013     reslimit rl;
1014     polynomial::numeral_manager nm;
1015     polynomial::manager m(rl, nm);
1016     polynomial_ref x0(m), zero(m), one(m);
1017     x0 = m.mk_polynomial(m.mk_var());
1018     zero = m.mk_zero();
1019     one  = m.mk_const(rational(1));
1020     tst_rem((x0^2) + x0, x0, zero);
1021     tst_rem((x0^2) + x0 + 1, x0, one);
1022     tst_rem((x0^2) + 2*x0 + 1, 2*x0 + 2, zero);
1023 }
1024 
tst_lower_bound(polynomial_ref const & p)1025 static void tst_lower_bound(polynomial_ref const & p) {
1026     ENSURE(is_univariate(p));
1027     std::cout << "---------------\n";
1028     std::cout << "p: " << p << std::endl;
1029     reslimit rl; upolynomial::manager um(rl, p.m().m());
1030     upolynomial::scoped_numeral_vector _p(um);
1031     um.to_numeral_vector(p, _p);
1032     std::cout << "_p: "; um.display(std::cout, _p); std::cout << "\n";
1033     unsigned k = um.nonzero_root_lower_bound(_p.size(), _p.data());
1034     std::cout << "_p: "; um.display(std::cout, _p); std::cout << "\n";
1035     std::cout << "k:  " << k << "\n";
1036 }
1037 
tst_lower_bound()1038 static void tst_lower_bound() {
1039     reslimit rl;
1040     polynomial::numeral_manager nm;
1041     polynomial::manager m(rl, nm);
1042     polynomial_ref x(m), zero(m), one(m);
1043     x = m.mk_polynomial(m.mk_var());
1044     zero = m.mk_zero();
1045     one  = m.mk_const(rational(1));
1046     tst_lower_bound((x^2) - 2);
1047     tst_lower_bound((x^5));
1048     tst_lower_bound((x - 1)*(2*x - 1)*(4*x - 1)*(8*x - 1));
1049     tst_lower_bound((x - 1)*(2*x - 1)*(4*x - 1)*(8*x - 1)*(16*x - 1));
1050     tst_lower_bound((x - 1)*(2*x - 1)*(4*x - 1)*(8*x - 1)*(16*x - 1)*(x^3));
1051     tst_lower_bound((x^5) - x - 1);
1052     tst_lower_bound((1000*x - 1)*(x - 1));
1053     tst_lower_bound((x + 1)*(2*x - 1)*(4*x + 1)*(8*x - 1)*(16*x + 1));
1054     tst_lower_bound((x + 1)*(2*x + 1)*(4*x + 1)*(8*x + 1)*(16*x + 1));
1055     tst_lower_bound((x^10) - 10*(x^8) + 38*(x^6) - 2*(x^5) - 100*(x^4) - 40*(x^3) + 121*(x^2) - 38*x - 17);
1056     tst_lower_bound(((x^17) + 5*(x^16) + 3*(x^15) + 10*(x^13) + 13*(x^10) + (x^9) + 8*(x^5) + 3*(x^2) + 7)*(((x^5) - x - 1)^2)*(((x^3) - 2)^2));
1057     tst_lower_bound((((x^5) - 1000000000)^3)*((3*x - 10000000)^2)*((10*x - 632)^2));
1058 }
1059 
tst_upolynomial()1060 void tst_upolynomial() {
1061     set_verbosity_level(1000);
1062     enable_trace("mpz_gcd");
1063     enable_trace("normalize_bug");
1064     enable_trace("factor_bug");
1065     enable_trace("factor");
1066     // enable_trace("mpzp_inv_bug");
1067     // enable_trace("mpz");
1068     tst_gcd();
1069     tst_lower_bound();
1070     tst_fact();
1071     tst_rem();
1072     tst_exact_div();
1073     tst_isolate_roots5();
1074     // tst_gcd2();
1075     // tst_isolate_roots4();
1076     // tst_isolate_roots3();
1077     // tst_isolate_roots2();
1078     // return;
1079     tst_isolate_roots();
1080     tst_sturm2();
1081     tst_convert_q2bq();
1082     enable_trace("div_bug");
1083     enable_trace("mpbq_bug");
1084     tst_translate_q();
1085     tst_refine();
1086     tst_refinable();
1087     tst_sturm();
1088     tst_remove_one_half();
1089     tst_isolate_roots();
1090     tst1();
1091     tst_zp();
1092     tst_zp2();
1093     tst_ext_gcd();
1094     tst_ext_gcd_z7();
1095 }
1096