cgal/Polynomial/test/Polynomial/test_polynomial.h

1051 lines
33 KiB
C++

#include <CGAL/use.h>
#include <CGAL/Test/_test_algebraic_structure.h>
#include <CGAL/Test/_test_real_embeddable.h>
#include <iostream>
#include <cassert>
#include <CGAL/Polynomial_traits_d.h>
#include <CGAL/Arithmetic_kernel.h>
#include <CGAL/Polynomial.h>
#include <CGAL/Sqrt_extension.h>
#include <CGAL/Interval_nt.h>
#include <CGAL/Coercion_traits.h>
#define CGAL_DEFINE_TYPES_FROM_AK(AK) \
typedef typename AK::Integer Integer; \
typedef typename AK::Rational Rational; \
typedef typename AK::Field_with_sqrt Field_with_sqrt; CGAL_USE_TYPE(Field_with_sqrt); \
typedef CGAL::Polynomial<Integer> Poly_int1; \
typedef CGAL::Polynomial<Poly_int1> Poly_int2; \
typedef CGAL::Polynomial<Poly_int2> Poly_int3; CGAL_USE_TYPE(Poly_int3); \
typedef CGAL::Polynomial<Rational> Poly_rat1; \
typedef CGAL::Polynomial<Poly_rat1> Poly_rat2; \
typedef CGAL::Polynomial<Poly_rat2> Poly_rat3; CGAL_USE_TYPE(Poly_rat3);
// TODO: copied from number_type_utils.h
namespace CGAL {
template <class NT , class RT>
inline
void convert_to(const NT& x, RT& r){
typedef CGAL::Coercion_traits<NT,RT> CT;
typedef typename CT::Coercion_type RET;
static_assert(::std::is_same<RET,RT>::value);
r = typename CT::Cast()(x);
}
} //namespace CGAL
template <class NT>
void datastru() {
typedef CGAL::Polynomial<NT> POLY;
int i;
// uninitialized construction
POLY p;
assert( p.degree() == 0 );
// construction from iterator range, assignment
NT array[] = { NT(3), NT(1), NT(4), NT(1), NT(5), NT(9) };
NT* const array_end = array + sizeof array / sizeof *array;
POLY q(array, array_end);
p = q;
assert( array_end - array == p.degree() + 1 );
assert( std::equal(p.begin(), p.end(), array) );
// immediate construction, reduce(), copy construction, (in)equality
POLY r(NT(3), NT(1), NT(4), NT(1), NT(5), NT(9), NT(0), NT(0));
assert( q.degree() == r.degree() );
assert( q == r );
assert( r == r );
q = POLY(NT(2), NT(7), NT(1), NT(8), NT(1));
assert( q != r );
POLY s(p);
assert( r == s );
// selection of coefficients
for (i = 0; i <= p.degree(); i++) {
assert( p[i] == array[i] );
}
assert( i == array_end - array );
assert( p.lcoeff() == array_end[-1] );
// reversal()
assert( reversal(q) == POLY(NT(1), NT(8), NT(1), NT(7), NT(2)) );
// divide_by_x()
r.divide_by_x();
assert( r.degree() == 4 );
assert( r == POLY(NT(1), NT(4), NT(1), NT(5), NT(9)) );
// zero test
assert( !p.is_zero() );
q = POLY(NT(0));
assert( q.is_zero() );
}
template <class NT> void signs(::CGAL::Tag_false);
template <class NT> void signs(::CGAL::Tag_true);
template <class NT> void division(CGAL::Integral_domain_without_division_tag);
template <class NT> void division(CGAL::Integral_domain_tag);
template <class NT>
void arithmetic() {
typedef CGAL::Polynomial<NT> POLY;
// evaluation
POLY p(NT(6), NT(-5), NT(1));
assert( p.evaluate(NT(1)) == NT(2) );
assert( p.evaluate(NT(2)) == NT(0) );
assert( p.evaluate(NT(3)) == NT(0) );
// TODO: No evaluate_absolute available for all NTs.
//assert( p.evaluate_absolute(NT(1)) == NT(12) );
// diff
POLY q(NT(3), NT(2), NT(-2));
POLY z(NT(0));
assert( CGAL::differentiate(z) == z );
assert( p.degree() == 2 );
assert( CGAL::differentiate(p) == POLY(NT(-5), NT(2)) );
assert( p.degree() == 2 );
assert( q.degree() == 2 );
q.diff();
assert( q == POLY(NT(2), NT(-4)) );
// scale and translate
p.scale_up(NT(4));
assert( p == POLY(NT(6), NT(-20), NT(16)) );
assert( scale_down(p, NT(2)) == POLY(NT(24), NT(-40), NT(16)) );
assert( p == POLY(NT(6), NT(-20), NT(16)) );
p = POLY(NT(3), NT(2), NT(1));
// CGAL::translate takes an Innermost_coefficient
assert( translate_by_one(p) == CGAL::translate(p, 1) );
p.translate(NT(-2));
assert( p == POLY(NT(3), NT(-2), NT(1)) );
// addition
POLY r;
p = POLY(NT(3), NT(2), NT(1), NT(1));
q = POLY(NT(1), NT(2), NT(-1), NT(-1));
r = p + q;
assert( r.degree() == 1 );
assert( r[0] == NT(4) );
assert( r[1] == NT(4) );
q += p;
assert( q == r );
q += NT(1);
assert( q == POLY(NT(5), NT(4)) );
assert( q == r + NT(1) );
assert( q == NT(1) + r );
// subtraction
p = POLY(NT(3), NT(2), NT(1), NT(1));
q = POLY(NT(1), NT(2), NT(-1), NT(1));
r = p - q;
assert( r.degree() == 2 );
assert( r == POLY(NT(2), NT(0), NT(2)) );
r -= -q;
assert( r == p );
r -= NT(2);
assert( r == p - NT(2) );
assert( -r == NT(2) - p );
// multiplication
p = POLY(NT(1), NT(2), NT(3));
q = POLY(NT(-2), NT(5), NT(2));
r = p * q;
assert( r == POLY(NT(-2), NT(1), NT(6), NT(19), NT(6)) );
q *= p;
assert( q == r );
q *= NT(2);
assert( q == POLY(NT(-4), NT(2), NT(12), NT(38), NT(12)) );
assert( q == r * NT(2) );
assert( q == NT(2) * r );
// sign etc., if applicable
// TODO: Replaced Is_real_comparable with RET::Is_real_embeddable, OK?
typedef typename CGAL::Real_embeddable_traits<NT>::Is_real_embeddable
Embeddable;
signs<NT>(Embeddable());
// division, if applicable
typedef typename CGAL::Algebraic_structure_traits<NT>::Algebraic_category
Algebra_type;
division<NT>(Algebra_type());
}
template <class NT> void signs(::CGAL::Tag_false) {
// nothing to be done
}
template <class POLY>
void test_greater(POLY a, POLY b) {
// check .compare()
assert( a.compare(b) == CGAL::LARGER );
assert( a.compare(a) == CGAL::EQUAL );
assert( b.compare(a) == CGAL::SMALLER );
// check that all comparison operators reflect a > b
assert( a > b );
assert( !(b > a) );
assert( !(a > a) );
assert( b < a );
assert( !(a < b) );
assert( !(a < a) );
assert( a >= b );
assert( !(b >= a) );
assert( a >= a );
assert( b <= a );
assert( !(a <= b) );
assert( a <= a );
}
template <class NT>
void signs(::CGAL::Tag_true) {
typedef CGAL::Polynomial<NT> POLY;
POLY p(NT(6), NT(-5), NT(1));
POLY pp(NT(6), NT(-5), NT(1));
POLY q(NT(3), NT(2), NT(-2));
POLY z(NT(0));
// sign, abs
assert( z.sign() == CGAL::ZERO );
assert( p.sign() == CGAL::POSITIVE );
assert( p.abs() == p );
assert( q.sign() == CGAL::NEGATIVE );
assert( q.abs() == POLY(NT(-3), NT(-2), NT(2)) );
// comparison operators
test_greater(p + NT(1), p);
test_greater(POLY(NT(1), NT(2), NT(3), NT(4)), p);
// sign_at
q=POLY(NT(3),NT(2),NT(-1));
assert(q.sign_at(-2)==CGAL::NEGATIVE);
assert(q.sign_at(-1)==CGAL::ZERO);
assert(q.sign_at( 0)==CGAL::POSITIVE);
assert(q.sign_at( 3)==CGAL::ZERO);
assert(q.sign_at( 4)==CGAL::NEGATIVE);
assert(z.sign_at( 3)==CGAL::ZERO);
}
template <class NT>
void division(CGAL::Integral_domain_without_division_tag) {
// nothing to be done
}
template <class NT>
void division(CGAL::Integral_domain_tag) {
typedef CGAL::Polynomial<NT> POLY;
// integral division (remainder zero)
POLY p(NT(2), NT(4), NT(6)), q(NT(-2), NT(5), NT(2));
POLY r(NT(-4), NT(2), NT(12), NT(38), NT(12)), s;
assert( q == r / p );
r /= q;
assert( r == p );
r /= NT(2);
assert( r == POLY(NT(1), NT(2), NT(3)) );
assert( NT(6) / POLY(NT(3)) == POLY(NT(2)) );
// division with remainder
p = POLY(NT(2), NT(-3), NT(1)); // (x-1)(x-2)
q = POLY(NT(24), NT(-14), NT(2)); // 2(x-3)(x-4)
r = POLY(NT(-5), NT(1)); // (x-5)
s = p*q + r;
assert(!CGAL::divides(q,s));
POLY Q, R;
POLY::euclidean_division(s, p, Q, R); // works, since p.lcoeff() == 1
assert( Q == q );
assert( R == r );
NT D;
POLY::pseudo_division(s, q, Q, R, D);
assert( Q == D*p );
assert( R == D*r );
// codecover
p = POLY(NT(2),NT(3));
s = POLY(NT(2),NT(3),NT(4));
POLY::euclidean_division(p, s, Q, R); // works, since p.lcoeff() == 1
assert( Q == POLY(NT(0)) );
assert( R == p );
POLY::pseudo_division(p, s, Q, R, D); // works, since p.lcoeff() == 1
assert( Q == POLY(NT(0)) );
assert( R == D*p );
}
template <class NT>
void io() {
// https://github.com/CGAL/cgal/issues/6272#issuecomment-1022005703
// VCbug: Setting the rounding mode influences output of double
// The rounding mode is set to CGAL_FE_UPWARD in the test ccp files
// in order to test Modular Arithmetic
// Without this change which is local to the function p == q will fail
CGAL::Protect_FPU_rounding<true> pfr(CGAL_FE_TONEAREST);
typedef CGAL::Polynomial<NT> POLY;
{
// successful re-reading of output
POLY p(NT(-3), NT(5), NT(0), NT(0), NT(-7), NT(9)), q;
std::ostringstream os;
os.precision(17);
os << p;
std::istringstream is(os.str());
is >> q;
assert( p == q );
}{
std::ostringstream os;
CGAL::IO::set_pretty_mode(os);
os << CGAL::IO::oformat(POLY(NT(3)));
assert( os.str() == "3" );
}{
std::ostringstream os;
CGAL::IO::set_pretty_mode(os);
os << CGAL::IO::oformat(POLY(NT(-3)));
assert( os.str() == "(-3)" );
}{
std::ostringstream os;
CGAL::IO::set_pretty_mode(os);
os << CGAL::IO::oformat(POLY(NT(-3)),CGAL::Parens_as_product_tag());
assert( os.str() == "(-3)" );
}{
std::ostringstream os;
CGAL::IO::set_pretty_mode(os);
os << CGAL::IO::oformat(POLY(NT(-3),NT(4)));
if( CGAL::Polynomial_traits_d<POLY>::d == 1)
assert( os.str() == "4*x + (-3)" );
else
assert( os.str() == "4*y + (-3)" );
}{
std::ostringstream os;
CGAL::IO::set_pretty_mode(os);
os << CGAL::IO::oformat(POLY(NT(-3),NT(4)), CGAL::Parens_as_product_tag());
if( CGAL::Polynomial_traits_d<POLY>::d == 1)
assert( os.str() == "(4*x + (-3))" );
else
assert( os.str() == "(4*y + (-3))" );
}
}
template <class NT>
void canon(CGAL::Integral_domain_without_division_tag) {
// dummy for cases where CGAL::canonicalize() does not apply
}
template <class NT>
void canon(CGAL::Unique_factorization_domain_tag) {
typedef CGAL::Polynomial<NT> UNPOLY;
typedef CGAL::Polynomial<UNPOLY> BIPOLY;
BIPOLY p(0), c;
assert(CGAL::canonicalize(p) == BIPOLY(0));
p = BIPOLY(UNPOLY(NT(15)), UNPOLY(NT(-12), NT( 9)), UNPOLY(NT(0), NT(-6)));
c = BIPOLY(UNPOLY(NT(-5)), UNPOLY(NT( 4), NT(-3)), UNPOLY(NT(0), NT( 2)));
assert(CGAL::canonicalize(p) == c);
}
template <class NT>
void canon(CGAL::Field_tag) {
typedef CGAL::Polynomial<NT> UNPOLY;
typedef CGAL::Polynomial<UNPOLY> BIPOLY;
BIPOLY p(0), c;
assert(CGAL::canonicalize(p) == BIPOLY(0));
p = BIPOLY(UNPOLY(NT(15)), UNPOLY(NT(-12), NT( 9)), UNPOLY(NT(0), NT(-6)));
c = BIPOLY(UNPOLY(NT(-5)/NT(2)), UNPOLY(NT(2), NT(-3)/NT(2)),
UNPOLY(NT(0), NT(1)));
assert(CGAL::canonicalize(p) == c);
}
#ifdef NiX_POLY_USE_NT_TESTS
template <class NT>
void nt_tests(::CGAL::Tag_false) {
typedef CGAL::Polynomial<NT> POLY;
if ((volatile bool)0) { // test compilation only
CGAL::test_number_type<POLY,
typename CGAL::Algebraic_structure_traits<POLY>::Algebric_structure_tag>();
}
}
template <class NT>
void nt_tests(::CGAL::Tag_true) {
typedef CGAL::Polynomial<NT> POLY;
CGAL::test_real_comparable<POLY>();
nt_tests<NT>(::CGAL::Tag_false());
}
#endif // NiX_POLY_USE_NT_TESTS
template <class NT>
void unigcdres(CGAL::Field_tag) {
typedef CGAL::Polynomial<NT> POLY;
// test univariate polynomial gcd and resultant over a field
POLY f(NT(2), NT(7), NT(1), NT(8), NT(1), NT(8));
POLY g(NT(3), NT(1), NT(4), NT(1), NT(5), NT(9));
POLY h(NT(3), NT(4), NT(7), NT(7));
f /= NT(3);
g /= NT(5);
h /= h.unit_part();
POLY d;
d = CGAL::gcd(f, g);
assert( d == POLY(NT(1)) );
assert( prs_resultant(f, g) == NT(230664271L)/NT(759375L) ); // Maple
POLY fh(f*h), gh(g*h);
d = CGAL::gcd(fh, gh);
assert( d == h );
assert( prs_resultant(fh, gh) == NT(0) );
POLY a, b;
d = gcdex(fh, gh, a, b);
assert( d == h );
assert( d == a*fh + b*gh );
}
template <class NT>
void unigcdres(CGAL::Integral_domain_tag) {
typedef CGAL::Polynomial<NT> POLY;
// test univariate polynomial gcd and resultant over a non-field
POLY f(NT(2), NT(7), NT(1), NT(8), NT(1), NT(8));
POLY g(NT(3), NT(1), NT(4), NT(1), NT(5), NT(9));
POLY h(NT(3), NT(4), NT(7), NT(7));
POLY d;
NT c(42);
d = CGAL::gcd((-c)*f, c*g);
assert( d == POLY(c) );
assert( prs_resultant(f, g) == NT(230664271L) ); // as computed by Maple
POLY fh(f*h), gh(g*h);
d = CGAL::gcd((-c)*fh, c*gh);
assert( d == c*h );
assert( prs_resultant(fh, gh) == NT(0) );
POLY a, b; NT v;
d = pseudo_gcdex((-c)*fh, c*gh, a, b, v);
assert( d == c*h );
assert( v*d == (-c)*a*fh + c*b*gh );
// Michael Kerber's example for the hgdelta_update() bug:
// These polynomials create a situation where h does not divide g,
// but h^(delta-1) divides g^delta (as predicted by subresultant theory).
// TODO: Uncomment following code
/*CGAL::Creator_1<int, NT> int2nt;
static const int cp[] = { 196, 0, -140, 0, 69, 0, -8, 0, -4 },
cq[] = { -15156, 0, -58572, 0, -82309, 0, -27032, 0,
20190, 0, 1696, 0, -6697, 0, 1644, 0, 1664, 0, 256 };
static const size_t np = sizeof cp / sizeof *cp,
nq = sizeof cq / sizeof *cq;
POLY p(LiS::mapper(cp, int2nt), LiS::mapper(cp+np, int2nt)),
q(LiS::mapper(cq, int2nt), LiS::mapper(cq+nq, int2nt));
d = gcd(p,q);
assert ( d == POLY(1) );*/
}
template <class NT>
void bigcdres(CGAL::Field_tag) {
typedef CGAL::Polynomial<NT> POLY1;
typedef CGAL::Polynomial<POLY1> POLY2;
// test bivariate polynomial gcd and resultant over a field
POLY2 f = POLY2(POLY1(NT(2), NT(7), NT(1)),
POLY1(NT(8), NT(1)), POLY1(NT(8)));
POLY2 g = POLY2(POLY1(NT(3), NT(1), NT(4)),
POLY1(NT(1), NT(5)), POLY1(NT(9)));
POLY2 h = POLY2(POLY1(NT(3), NT(4), NT(1)),
POLY1(NT(9), NT(7)), POLY1(NT(7)));
f /= NT(3);
g /= NT(5);
h /= h.unit_part();
POLY2 d;
d = CGAL::gcd(f, g);
assert( d == POLY2(1) );
POLY1 r(NT(1444), NT(-1726), NT(3295), NT(-2501), NT(560));
r /= NT(225);
assert( prs_resultant(f, g) == r ); // says Maple
POLY2 fh(f*h), gh(g*h);
d = CGAL::gcd(fh, gh);
assert( d == h );
assert( prs_resultant(fh, gh) == POLY1(0) );
}
template <class NT>
void bigcdres(CGAL::Integral_domain_tag) {
typedef CGAL::Polynomial<NT> POLY1;
typedef CGAL::Polynomial<POLY1> POLY2;
// test bivariate polynomial gcd and resultant over a non-field
POLY2 f = POLY2(POLY1(NT(2), NT(7), NT(1)),
POLY1(NT(8), NT(1)), POLY1(NT(8)));
POLY2 g = POLY2(POLY1(NT(3), NT(1), NT(4)),
POLY1(NT(1), NT(5)), POLY1(NT(9)));
POLY2 h = POLY2(POLY1(NT(3), NT(4), NT(1)),
POLY1(NT(9), NT(7)), POLY1(NT(7)));
POLY2 c(42), d;
d = CGAL::gcd(-c*f, c*g);
assert( d == c );
POLY1 r(NT(1444), NT(-1726), NT(3295), NT(-2501), NT(560));
assert( prs_resultant(f, g) == r ); // says Maple
POLY2 fh(f*h), gh(g*h);
d = CGAL::gcd(-c*fh, c*gh);
assert( d == c*h );
assert( prs_resultant(fh, gh) == POLY1(0) );
}
template <class POLY>
void test_sqff_utcf_(const POLY& poly, int n){
typedef CGAL::Polynomial_traits_d<POLY> PT;
std::vector<POLY> fac;
std::vector<int> mul;
std::back_insert_iterator<std::vector<POLY> > fac_bi(fac);
std::back_insert_iterator<std::vector<int> > mul_bi(mul);
int tmp = CGAL::internal::square_free_factorize_utcf(poly, fac_bi, mul_bi);
assert(n == tmp);
assert((int) mul.size() == n);
assert((int) fac.size() == n);
if (typename PT::Total_degree()(poly) == 0 ){
assert(n == 0);
}else{
POLY check(1);
for(int i = 0; i < n ; i++){
assert(typename PT::Total_degree()(fac[i]) > 0);
//std::cout << fac[i] << std::endl;
//std::cout << typename PT::Canonicalize()(fac[i]) << std::endl;
//std::cout << std::endl;
assert(fac[i] == typename PT::Canonicalize()(fac[i]));
check *= CGAL::ipower(fac[i],mul[i]);
}
assert(check == typename PT::Canonicalize()(poly));
}
}
template <class POLY_1>
void test_sqff_utcf(const POLY_1& a1,const POLY_1& b1,const POLY_1& c1){
typedef CGAL::Polynomial<POLY_1> POLY_2;
test_sqff_utcf_(POLY_1(0), 0);
test_sqff_utcf_(POLY_1(1), 0);
test_sqff_utcf_(POLY_1(2), 0);
test_sqff_utcf_(a1, 1);
test_sqff_utcf_(a1*a1, 1);
test_sqff_utcf_(a1*a1*b1,2);
test_sqff_utcf_(a1*POLY_1(5),1);
POLY_2 a2(a1,b1,c1);
POLY_2 b2(a1,c1);
POLY_2 c2(b1,a1,b1);
test_sqff_utcf_(POLY_2(0), 0);
test_sqff_utcf_(POLY_2(1), 0);
test_sqff_utcf_(POLY_2(2), 0);
test_sqff_utcf_(a2,1);
test_sqff_utcf_(a2*a2,1);
test_sqff_utcf_(a2*a2*b2,2);
test_sqff_utcf_(a2*POLY_2(5),1);
test_sqff_utcf_(a2*a2*POLY_2(5),1);
// non regular polynomials
test_sqff_utcf_(a1*a2,2);
test_sqff_utcf_(a1*a2*a2,2);
test_sqff_utcf_(a1*a2*b2*b2,3);
test_sqff_utcf_(a1*a2*POLY_2(5),2);
test_sqff_utcf_(a1*a2*a2*POLY_2(5),2);
test_sqff_utcf_(a1*a2*a2*b2*POLY_2(5),3);
test_sqff_utcf_(a1*a1*a2,2);
test_sqff_utcf_(a1*a1*a2*a2,2);
test_sqff_utcf_(a1*b1*b1*a2*a2,3);
}
template <class AT>
void psqff(){
{
typedef typename AT::Integer NT;
typedef CGAL::Polynomial<NT> POLY_1;
// monic factors
POLY_1 a1(NT(std::string("4352435")), NT(std::string("4325245")));
POLY_1 b1(NT(std::string("123")), NT(std::string("432235")),NT(std::string("43324252")));
POLY_1 c1(NT(std::string("12324")), NT(std::string("25332235")),NT(std::string("24657252")));
test_sqff_utcf(a1,b1,c1);
}{
typedef typename AT::Rational NT;
typedef CGAL::Polynomial<NT> POLY_1;
// monic factors
POLY_1 a1(NT(std::string("4352435")), NT(std::string("4325245")));
POLY_1 b1(NT(std::string("123")), NT(std::string("432235")),NT(std::string("43324252")));
POLY_1 c1(NT(std::string("12324")), NT(std::string("25332235")),NT(std::string("24657252")));
test_sqff_utcf(a1,b1,c1);
}
{
typedef typename AT::Integer Integer; //UFD domain
typedef CGAL::Sqrt_extension<Integer,Integer> NT;
typedef CGAL::Polynomial<NT> POLY;
// square-free factorization (i.e. factorization by multiplicities)
POLY a1(NT(3,4,7), NT(2,3,7), NT(3));
POLY b1(NT(9,2,7), NT(5,11,7), NT(2));
POLY c1(NT(2,8,7), NT(6,3,7), NT(5));
test_sqff_utcf(a1,b1,c1);
}{
typedef typename AT::Integer Integer; //UFD domain
typedef typename AT::Rational Rational; //UFD domain
typedef CGAL::Sqrt_extension<Rational,Integer> NT;
typedef CGAL::Polynomial<NT> POLY;
// square-free factorization (i.e. factorization by multiplicities)
POLY a1(NT(3,4,7), NT(2,3,7), NT(3));
POLY b1(NT(9,2,7), NT(5,11,7), NT(2));
POLY c1(NT(2,8,7), NT(6,3,7), NT(5));
test_sqff_utcf(a1,b1,c1);
}
{
typedef typename AT::Integer Integer; CGAL_USE_TYPE(Integer);
typedef typename AT::Rational Rational;
typedef CGAL::Sqrt_extension<Rational,Rational> NT;
typedef CGAL::Polynomial<NT> POLY;
// square-free factorization (i.e. factorization by multiplicities)
POLY a1(NT(3,4,7), NT(2,3,7), NT(3));
POLY b1(NT(9,2,7), NT(5,11,7), NT(2));
POLY c1(NT(2,8,7), NT(6,3,7), NT(5));
test_sqff_utcf(a1,b1,c1);
}
}
template <class NT>
void sqff() {
typedef CGAL::Polynomial<NT> POLY;
// square-free factorization (i.e. factorization by multiplicities)
POLY p1(NT(3), NT(4), NT(1));
POLY p3(NT(9), NT(5), NT(1));
POLY p4(NT(2), NT(6), NT(1));
POLY p = NT(3) * p1 * p3*p3*p3 * p4*p4*p4*p4;
typedef std::vector<POLY> PVEC;
typedef std::vector<int> IVEC;
PVEC fac;
IVEC mul;
std::back_insert_iterator<PVEC> fac_bi(fac);
std::back_insert_iterator<IVEC> mul_bi(mul);
unsigned n;
NT alpha;
n = CGAL::internal::square_free_factorize(p, fac_bi, mul_bi );
// assert(alpha == 3);
assert(n == 3);
assert(mul.size() == n);
assert(fac.size() == n);
assert(mul[0] == 1 && fac[0] == p1);
assert(mul[1] == 3 && fac[1] == p3);
assert(mul[2] == 4 && fac[2] == p4);
/*p = POLY( NT(1), NT(-2), NT(1) );
std::cerr << p << std::endl;
fac.clear();
mul.clear();
fac_bi = std::back_insert_iterator<PVEC>(fac);
mul_bi = std::back_insert_iterator<IVEC>(mul);
std::cerr << CGAL::internal::square_free_factorize( p, fac_bi, mul_bi ) << std::endl;
std::cerr << fac[0] << std::endl;*/
//std::cerr << fac[1] << std::endl;
typedef CGAL::Polynomial< CGAL::Polynomial< NT > > BPOLY;
typedef std::vector< BPOLY > BPVEC;
BPOLY bp( POLY( NT(1), NT(-2), NT(1) ) );
// std::cerr << bp << std::endl;
// typename CGAL::Polynomial_traits_d< BPOLY >::Make_square_free make_square_free;
// std::cerr << make_square_free( bp ) << std::endl;
// std::cerr << "^^^^^^^^^^" << std::endl;
BPVEC bfac;
mul.clear();
std::back_insert_iterator< BPVEC > bfac_bi( bfac );
mul_bi = std::back_insert_iterator<IVEC>(mul);
// std::cerr << CGAL::POLYNOMIAL::square_free_factorize( bp, bfac_bi, mul_bi ) << std::endl;
// std::cerr << bfac[0] << std::endl;
}
template <class FNT>
void integr() {
typedef CGAL::Polynomial<FNT> FPOLY;
typedef typename CGAL::Fraction_traits<FPOLY>::Numerator_type IPOLY;
typedef typename CGAL::Fraction_traits<FPOLY>::Denominator_type DENOM;
typename CGAL::Fraction_traits<FPOLY>::Decompose decompose;
typename CGAL::Fraction_traits<FPOLY>::Compose compose; (void) compose;
typedef typename IPOLY::NT INT;
// making polynomials integral and fractional
FPOLY fp(FNT(1)/FNT(2), FNT(2)/FNT(3), FNT(3)/FNT(5));
IPOLY ip; DENOM d;
decompose(fp, ip,d);
assert( d == DENOM(30) );
assert( ip == IPOLY(INT(15), INT(20), INT(18)) );
assert( fp == compose(ip, d) );
}
template <class NT>
void basic_tests() {
// tests that should work for all number types
typedef CGAL::Polynomial<NT> POLY;
datastru<NT>();
datastru<POLY>();
arithmetic<NT>();
arithmetic<POLY>();
io<NT>();
io<POLY>();
canon<NT>(typename CGAL::Algebraic_structure_traits<NT >::Algebraic_category());
#ifdef NiX_POLY_USE_NT_TESTS
// TODO: Replaced Is_real_comparable with RET::Is_real_embeddable, OK?
nt_tests<NT >(typename CGAL::Real_embeddable_traits<NT >::Is_real_embeddable());
// TODO: Replaced Is_real_comparable with RET::Is_real_embeddable, OK?
nt_tests<POLY>(typename CGAL::Real_embeddable_traits<POLY>::Is_real_embeddable());
#endif // NiX_POLY_USE_NT_TESTS
}
template <class NT>
void exact_tests() {
// tests that probably don't work for inexact or bounded number types
unigcdres<NT>(typename CGAL::Algebraic_structure_traits<NT>::Algebraic_category());
bigcdres<NT>(typename CGAL::Algebraic_structure_traits<NT>::Algebraic_category());
sqff<NT>();
}
template < class Rational >
void test_coefficients_to() {
typedef CGAL::Polynomial< int > Poly_i1;
typedef CGAL::Polynomial< Poly_i1 > Poly_i2;
typedef CGAL::Polynomial< Poly_i2 > Poly_i3;
typedef CGAL::Polynomial< Rational > Poly_rat1;
typedef CGAL::Polynomial< Poly_rat1 > Poly_rat2;
typedef CGAL::Polynomial< Poly_rat2 > Poly_rat3;
// univariate
{
Poly_i1 p = Poly_i1(-3,4,5,-9,0,2);
Poly_rat1 r = Poly_rat1(Rational(-3),Rational(4),Rational(5),
Rational(-9),Rational(0),Rational(2));
Poly_rat1 tmp;
CGAL::convert_to(p,tmp);
assert(tmp == r);
}
// bivariate
{
Poly_i1 p1 = Poly_i1( 3,-1, 2);
Poly_i1 p2 = Poly_i1(-5, 2,-4);
Poly_i2 p = Poly_i2(p1, p2);
Poly_rat1 r1 = Poly_rat1(Rational( 3),Rational(-1),Rational( 2));
Poly_rat1 r2 = Poly_rat1(Rational(-5),Rational( 2),Rational(-4));
Poly_rat2 r = Poly_rat2(r1,r2);
Poly_rat2 tmp;
CGAL::convert_to(p,tmp);
assert(tmp == r);
}
// trivariate
{
Poly_i1 p11 = Poly_i1( 7,-6, 9);
Poly_i1 p12 = Poly_i1(-1, 3);
Poly_i2 p1 = Poly_i2(p11, p12);
Poly_i1 p21 = Poly_i1(-17, 16, -19);
Poly_i1 p22 = Poly_i1( 11, -13);
Poly_i2 p2 = Poly_i2(p21, p22);
Poly_i3 p = Poly_i3(p1,p2);
Poly_rat1 r11 = Poly_rat1(Rational( 7),Rational(-6),Rational( 9));
Poly_rat1 r12 = Poly_rat1(Rational(-1),Rational( 3));
Poly_rat2 r1 = Poly_rat2(r11, r12);
Poly_rat1 r21 = Poly_rat1(Rational(-17),Rational( 16),Rational(-19));
Poly_rat1 r22 = Poly_rat1(Rational( 11),Rational(-13));
Poly_rat2 r2 = Poly_rat2(r21, r22);
Poly_rat3 r = Poly_rat3(r1,r2);
Poly_rat3 tmp;
CGAL::convert_to(p,tmp);
assert(tmp == r);
}
}
template <class AT>
void test_evaluate(){
CGAL_DEFINE_TYPES_FROM_AK(AT);
{
Poly_int1 P(3,0,2);
Integer x(2);
assert(P.evaluate(x)==Integer(11));
}{
Poly_rat1 P(3,0,2);
Integer x(2);
assert(P.evaluate(x)==Rational(11));
}{
Poly_int1 P(3,0,2);
Rational x(2);
assert(P.evaluate(x)==Rational(11));
}{
Poly_int1 P(3,0,2);
CGAL::Interval_nt<true> x(2);
assert(P.evaluate(x).inf()<=11);
assert(P.evaluate(x).sup()>=11);
}{
CGAL::Polynomial< CGAL::Interval_nt<true> > P(3,0,2);
CGAL::Interval_nt<true> x(2);
assert(P.evaluate(x).inf()<=11);
assert(P.evaluate(x).sup()>=11);
}{
CGAL::Polynomial< CGAL::Interval_nt<true> > P(3,0,2);
Integer x(2);
assert(P.evaluate(x).inf()<=11);
assert(P.evaluate(x).sup()>=11);
}
}
template <class AT>
void test_evaluate_homogeneous(){
CGAL_DEFINE_TYPES_FROM_AK(AT);
{
Poly_int1 P(3,0,2);
Integer u(2);
Integer v(1);
assert(P.evaluate_homogeneous(u,v)==Integer(11));
}{
Poly_rat1 P(2,-1,3);
Rational u(3);
Rational v(5);
assert(P.evaluate_homogeneous(u,v)==Rational(62));
assert(P.evaluate(u/v)==Rational(62)/Rational(25));
}
}
void test_total_degree(){
typedef CGAL::Polynomial<int> Poly_1;
typedef CGAL::Polynomial<Poly_1> Poly_2;
assert(CGAL::total_degree(5) == 0);
assert(CGAL::total_degree(Poly_1(0)) == Poly_1(0).degree());
assert(CGAL::total_degree(Poly_1(1)) == Poly_1(1).degree());
assert(CGAL::total_degree(Poly_1(1,1)) == Poly_1(1,1).degree());
assert(CGAL::total_degree(Poly_1(0,0,0,1))== Poly_1(0,0,0,1).degree());
assert(CGAL::total_degree(Poly_2(0)) == 0);
assert(CGAL::total_degree(Poly_2(1)) == 0);
assert(CGAL::total_degree(Poly_2(Poly_1(1),Poly_1(1))) == 1);
assert(CGAL::total_degree(Poly_2(Poly_1(0),Poly_1(0),Poly_1(0),Poly_1(1)))== 3);
assert(CGAL::total_degree(Poly_2(Poly_1(1,1),Poly_1(1))) == 1);
assert(CGAL::total_degree(Poly_2(Poly_1(0),Poly_1(0),Poly_1(1)))== 2);
assert(CGAL::total_degree(Poly_2(Poly_1(0),Poly_1(0),Poly_1(1)))== 2);
assert(CGAL::total_degree(Poly_2(Poly_1(0),Poly_1(0),Poly_1(1,1)))== 3);
assert(CGAL::total_degree(Poly_2(Poly_1(1),Poly_1(0),Poly_1(1,1)))== 3);
assert(CGAL::total_degree(Poly_2(Poly_1(1),Poly_1(1),Poly_1(1,1)))== 3);
assert(CGAL::total_degree(Poly_2(Poly_1(1),Poly_1(1,1,1,1),Poly_1(1,1)))== 4);
}
template<class AT>
void test_scalar_factor_traits(){
{
typedef typename AT::Integer Integer;
typedef CGAL::Polynomial<Integer> Polynomial;
typedef CGAL::Scalar_factor_traits<Polynomial> SFT;
typedef typename AT::Integer Scalar;
typedef typename SFT::Scalar Scalar_;
static_assert(::std::is_same<Scalar_, Scalar>::value);
typename SFT::Scalar_factor sfac;
assert(sfac(Polynomial(0))==Scalar(0));
assert(sfac(Polynomial(9))==Scalar(9));
assert(sfac(Polynomial(9,15,30))==Scalar(3));
assert(sfac(Polynomial(0), Integer(0))==Scalar(0));
assert(sfac(Polynomial(0), Integer(1))==Scalar(1));
assert(sfac(Polynomial(0), Integer(2))==Scalar(2));
assert(sfac(Polynomial(9), Integer(0))==Scalar(9));
assert(sfac(Polynomial(9), Integer(6))==Scalar(3));
assert(sfac(Polynomial(15,0 ,30) , Integer(9))==Scalar(3));
assert(sfac(Polynomial(0 ,15,30) , Integer(9))==Scalar(3));
assert(sfac(Polynomial(18,15,30) , Integer(0))==Scalar(3));
}{
typedef typename AT::Integer Integer;
typedef CGAL::Sqrt_extension<Integer,Integer> EXT_1;
typedef CGAL::Polynomial<EXT_1 > Poly_1_ext_1;
typedef CGAL::Polynomial<Poly_1_ext_1> Poly_2_ext_1;
typedef CGAL::Scalar_factor_traits<Poly_2_ext_1> SFT;
typedef typename AT::Integer Scalar;
typedef typename SFT::Scalar Scalar_;
static_assert(::std::is_same<Scalar_, Scalar>::value);
typename SFT::Scalar_factor sfac;
assert(sfac(Poly_2_ext_1( ))==Integer(0));
assert(sfac(Poly_2_ext_1(1))==Integer(1));
assert(sfac(Poly_2_ext_1(2))==Integer(2));
EXT_1 a(18,27,456);
EXT_1 b( 0,15,456);
Poly_2_ext_1 p(Poly_1_ext_1(a,b),Poly_1_ext_1(b,a));
assert(sfac(p)==Integer(3));
}
}
template<class Polynomial_d, class T>
void test_interoperable_with(){
// construction
assert(Polynomial_d(-2) == T(-2));
// operators
Polynomial_d f(4);
assert( f + T(2) == Polynomial_d( 6));
assert( f - T(2) == Polynomial_d( 2));
assert( f * T(2) == Polynomial_d( 8));
assert( f / T(2) == Polynomial_d( 2));
assert( T(2) + f == Polynomial_d( 6));
assert( T(2) - f == Polynomial_d(-2));
assert( T(2) * f == Polynomial_d( 8));
assert( T(8) / f == Polynomial_d( 2));
f+=T(2);
f-=T(4);
f*=T(3);
f/=T(2);
assert( f == Polynomial_d(3));
assert( T(2) == Polynomial_d(2));
assert( T(2) != Polynomial_d(4));
assert( (T(2) < Polynomial_d(4)));
assert(!(T(4) < Polynomial_d(4)));
assert(!(T(6) < Polynomial_d(4)));
assert(!(T(2) > Polynomial_d(4)));
assert(!(T(4) > Polynomial_d(4)));
assert( (T(6) > Polynomial_d(4)));
assert( T(2) <= Polynomial_d(4));
assert( T(4) <= Polynomial_d(4));
assert(!(T(6) <= Polynomial_d(4)));
assert(!(T(2) >= Polynomial_d(4)));
assert( (T(4) >= Polynomial_d(4)));
assert( (T(6) >= Polynomial_d(4)));
}
template<class Polynomial_d>
void test_interoperable_poly(){
typedef CGAL::Polynomial_traits_d<Polynomial_d> PT;
typedef typename PT::Coefficient_type Coefficient_type;
typedef typename PT::Innermost_coefficient_type Innermost_coefficient_type;
test_interoperable_with<Polynomial_d,int>();
test_interoperable_with<Polynomial_d,Innermost_coefficient_type>();
test_interoperable_with<Polynomial_d,Coefficient_type>();
test_interoperable_with<Polynomial_d,Polynomial_d>();
}
template<class AT>
void test_interoperable_at(){
typedef typename AT::Integer Integer;
typedef CGAL::Sqrt_extension<Integer,Integer> EXT;
{
typedef int Coefficient_type;
typedef CGAL::Polynomial<Coefficient_type> Poly_1;
typedef CGAL::Polynomial<Poly_1> Poly_2;
test_interoperable_poly<Poly_1>();
test_interoperable_poly<Poly_2>();
}{
typedef Integer Coefficient_type;
typedef CGAL::Polynomial<Coefficient_type> Poly_1;
typedef CGAL::Polynomial<Poly_1> Poly_2;
test_interoperable_poly<Poly_1>();
test_interoperable_poly<Poly_2>();
}{
typedef EXT Coefficient_type;
typedef CGAL::Polynomial<Coefficient_type> Poly_1;
typedef CGAL::Polynomial<Poly_1> Poly_2;
test_interoperable_poly<Poly_1>();
test_interoperable_poly<Poly_2>();
}
}
template <class AT>
void test_AT(){
test_interoperable_at<AT>();
basic_tests<int>();
basic_tests<double>();
{
typedef typename AT::Integer Integer;
typedef typename CGAL::Polynomial<Integer> Polynomial;
typedef CGAL::Unique_factorization_domain_tag Tag;
typedef CGAL::Tag_true Is_exact;
CGAL::test_algebraic_structure<Polynomial,Tag, Is_exact>();
basic_tests<Integer>();
exact_tests<Integer>();
}{
typedef typename AT::Rational Rational;
// typedef typename CGAL::Polynomial<Rational> Polynomial;
// typedef CGAL::Euclidean_ring_tag Tag;
// typedef CGAL::Tag_true Is_exact;
//can't use this test for Polynomials
//CGAL::test_algebraic_structure<Polynomial,Tag, Is_exact>();
basic_tests<Rational>();
exact_tests<Rational>();
integr<Rational>();
}
// TODO: This also leads to trouble with flattening. Needs to be fixed
psqff<AT>();
test_evaluate<AT>();
test_evaluate_homogeneous<AT>();
test_total_degree();
//test_scalar_factor_traits<AT>();
}