// Copyright (c) 2006-2008 Max-Planck-Institute Saarbruecken (Germany). // All rights reserved. // // This file is part of CGAL (www.cgal.org) // // $URL$ // $Id$ // SPDX-License-Identifier: LGPL-3.0-or-later OR LicenseRef-Commercial // // // Author(s) : Lutz Kettner // Michael Hemmer // // ============================================================================= /* \brief provides test functions for the various ring concepts of number * types. */ // within this file AS ^= Type #include //#include #include #include #include #include #include #include #include #include #include #ifndef CGAL_TEST_ALGEBRAIC_STRUCTURE_H #define CGAL_TEST_ALGEBRAIC_STRUCTURE_H #include // checks the result type of a functor template void check_result_type(AdaptableFunctor, ResultType){ typedef typename AdaptableFunctor::result_type result_type; static_assert(::std::is_same::value); CGAL_USE_TYPE(result_type); } // check nothing for CGAL::Null_functor template void check_result_type(CGAL::Null_functor, ResultType){} #define CGAL_SNAP_AST_FUNCTORS(Traits) \ typedef typename Traits::Simplify Simplify ; \ typedef typename Traits::Unit_part Unit_part; \ typedef typename Traits::Integral_division Integral_division; \ typedef typename Traits::Divides Divides; \ typedef typename Traits::Is_square Is_square; \ typedef typename Traits::Gcd Gcd; \ typedef typename Traits::Div_mod Div_mod; \ typedef typename Traits::Div Div; \ typedef typename Traits::Mod Mod; \ typedef typename Traits::Square Square; \ typedef typename Traits::Is_zero Is_zero; \ typedef typename Traits::Is_one Is_one; \ typedef typename Traits::Sqrt Sqrt; \ typedef typename Traits::Kth_root Kth_root; \ typedef typename Traits::Root_of Root_of; \ CGAL_USE_TYPE(Simplify) ; \ CGAL_USE_TYPE(Unit_part); \ CGAL_USE_TYPE(Integral_division); \ CGAL_USE_TYPE(Divides); \ CGAL_USE_TYPE(Is_square); \ CGAL_USE_TYPE(Gcd); \ CGAL_USE_TYPE(Div_mod); \ CGAL_USE_TYPE(Div); \ CGAL_USE_TYPE(Mod); \ CGAL_USE_TYPE(Square); \ CGAL_USE_TYPE(Is_zero); \ CGAL_USE_TYPE(Is_one); \ CGAL_USE_TYPE(Sqrt); \ CGAL_USE_TYPE(Kth_root); \ CGAL_USE_TYPE(Root_of); namespace CGAL { template< class AS > bool test_equality_epsilon( const AS & a, const AS & b, const AS & epsilon ) { typedef Algebraic_structure_traits AST; typedef typename AST::Is_exact Is_exact; if( Is_exact::value ) return a == b; else { return ( a < (b + epsilon) ) && ( a > (b - epsilon) ); } } template< class AS > AS unit_normal( const AS& x ) { typedef Algebraic_structure_traits AST; CGAL_SNAP_AST_FUNCTORS(AST); const Unit_part unit_part = Unit_part(); const Integral_division integral_division = Integral_division(); return integral_division( x, unit_part(x) ); } //Syntax tests template< class AS > void test_algebraic_structure_intern( const CGAL::Integral_domain_without_division_tag& ) {} template< class AS > void test_algebraic_structure_intern( const CGAL::Integral_domain_tag& ) { // test of functors typedef CGAL::Algebraic_structure_traits< AS > AST; CGAL_SNAP_AST_FUNCTORS(AST); using CGAL::Null_functor; static_assert(!::std::is_same< Integral_division, Null_functor >::value); static_assert(!::std::is_same< Divides, Null_functor >::value); static_assert(!::std::is_same< Is_zero, Null_functor >::value); static_assert(!::std::is_same< Is_one, Null_functor >::value); static_assert(!::std::is_same< Square, Null_functor >::value); // functor const Is_zero is_zero = Is_zero(); assert( is_zero( AS (0)) ); assert(! is_zero( AS (23)) ); assert( is_zero( AS (0) + AS(0) ) ); assert( CGAL_NTS is_zero( AS (0)) ); assert(! CGAL_NTS is_zero( AS (23)) ); assert( CGAL_NTS is_zero( AS (0) + AS(0) ) ); const Is_one is_one = Is_one(); assert( is_one( AS (1)) ); assert(! is_one( AS (23)) ); assert( is_one( AS (1) + AS(0) ) ); assert( CGAL_NTS is_one( AS (1)) ); assert(! CGAL_NTS is_one( AS (23)) ); assert( CGAL_NTS is_one( AS (1) + AS(0) ) ); const Square square = Square(); assert( square( AS (23)) == AS (23*23) ); assert( CGAL_NTS square( AS (23)) == AS (23*23) ); const Integral_division integral_division = Integral_division(); AS a(6); AS b(2); AS c(3); assert( integral_division( a,b) == c); assert( integral_division( a,c) == b); assert( integral_division( a+a-a,c*b-c) == b); assert( CGAL_NTS integral_division( a,b) == c); assert( CGAL_NTS integral_division( a,c) == b); assert( CGAL_NTS integral_division( a+a-a,c*b-c) == b); const Divides divides = Divides(); assert( divides(b,AS(0))); assert( divides(b,a)); assert( divides(c,a)); //assert( divides(c*b-c,a+a-a)); assert( CGAL_NTS divides(b,AS(0))); assert( CGAL_NTS divides(b,a)); assert( CGAL_NTS divides(c,a)); //assert( CGAL_NTS divides(c*b-c,a+a-a)); typedef typename AST::Is_exact Is_exact; // VC7 produced an ICE for // assert( ! Is_exact::value || ... ); bool ie = Is_exact::value; (void) ie; AS tmp; assert( divides(b,AS(0),tmp)); assert( !ie || tmp == integral_division(AS(0),b)); assert( divides(b,a,tmp)); assert( !ie || tmp == integral_division(a,b)); assert( divides(c,a,tmp)); assert( !ie || tmp == integral_division(a,c)); assert( divides(c*b-c,a+a-a,tmp)); assert( !ie || tmp == integral_division(a+a-a,c*b-c)); assert( CGAL_NTS divides(b,AS(0),tmp)); assert( !ie || tmp == integral_division(AS(0),b)); assert( CGAL_NTS divides(b,a,tmp)); assert( !ie || tmp == integral_division(a,b)); assert( CGAL_NTS divides(c,a,tmp)); assert( !ie || tmp == integral_division(a,c)); assert( CGAL_NTS divides(AS(c*b-c),AS(a+a-a),tmp)); assert( !ie || tmp == integral_division(a+a-a,c*b-c)); } template< class AS > void test_algebraic_structure_intern( const CGAL::Unique_factorization_domain_tag& ) { test_algebraic_structure_intern< AS >(CGAL::Integral_domain_tag()); typedef CGAL::Algebraic_structure_traits< AS > AST; CGAL_SNAP_AST_FUNCTORS(AST); using CGAL::Null_functor; static_assert(!::std::is_same< Gcd, Null_functor>::value); const Gcd gcd = Gcd(); assert( gcd( AS ( 0), AS ( 0)) == unit_normal( AS (0) ) ); assert( gcd( AS ( 7), AS ( 0)) == unit_normal( AS (7) ) ); assert( gcd( AS (-7), AS ( 0)) == unit_normal( AS (7) ) ); assert( gcd( AS ( 0), AS ( 7)) == unit_normal( AS (7) ) ); assert( gcd( AS ( 0), AS (-7)) == unit_normal( AS (7) ) ); assert( gcd( AS (-7), AS ( 1)) == unit_normal( AS (1) ) ); assert( gcd( AS ( 1), AS (-7)) == unit_normal( AS (1) ) ); assert( gcd( AS ( 15), AS ( 12)) == unit_normal( AS (3) ) ); assert( gcd( AS (-15), AS ( 12)) == unit_normal( AS (3) ) ); assert( gcd( AS ( 15), AS (-12)) == unit_normal( AS (3) ) ); assert( gcd( AS (-15), AS (-12)) == unit_normal( AS (3) ) ); // special test for expression template, e.g. mpz_class assert( gcd(AS(-10)+AS(-5),AS(-4)*AS(-3)) == unit_normal( AS (3) ) ); assert( CGAL_NTS gcd( AS ( 0), AS ( 0)) == unit_normal( AS (0) ) ); assert( CGAL_NTS gcd( AS ( 7), AS ( 0)) == unit_normal( AS (7) ) ); assert( CGAL_NTS gcd( AS (-7), AS ( 0)) == unit_normal( AS (7) ) ); assert( CGAL_NTS gcd( AS ( 0), AS ( 7)) == unit_normal( AS (7) ) ); assert( CGAL_NTS gcd( AS ( 0), AS (-7)) == unit_normal( AS (7) ) ); assert( CGAL_NTS gcd( AS (-7), AS ( 1)) == unit_normal( AS (1) ) ); assert( CGAL_NTS gcd( AS ( 1), AS (-7)) == unit_normal( AS (1) ) ); assert( CGAL_NTS gcd( AS ( 15), AS ( 12)) == unit_normal( AS (3) ) ); assert( CGAL_NTS gcd( AS (-15), AS ( 12)) == unit_normal( AS (3) ) ); assert( CGAL_NTS gcd( AS ( 15), AS (-12)) == unit_normal( AS (3) ) ); assert( CGAL_NTS gcd( AS (-15), AS (-12)) == unit_normal( AS (3) ) ); // special test for expression template, e.g. mpz_class assert( CGAL_NTS gcd(AS(-10)+AS(-5),AS(-4)*AS(-3)) == unit_normal( AS (3) ) ); } template< class AS > void test_algebraic_structure_intern( const CGAL::Euclidean_ring_tag&) { test_algebraic_structure_intern< AS > ( CGAL::Unique_factorization_domain_tag() ); typedef CGAL::Algebraic_structure_traits< AS > AST; CGAL_SNAP_AST_FUNCTORS(AST); using CGAL::Null_functor; static_assert(!::std::is_same< Div, Null_functor>::value); static_assert(!::std::is_same< Mod, Null_functor>::value); static_assert(!::std::is_same< Div_mod, Null_functor>::value); const Div div=Div(); const Mod mod=Mod(); const Div_mod div_mod=Div_mod(); // Rounding mode for div is: to zero assert( div( AS ( 3), AS (3)) == AS (1)); assert( div( AS ( 2), AS (3)) == AS (0)); assert( div( AS ( 1), AS (3)) == AS (0)); assert( div( AS ( 0), AS (3)) == AS (0)); assert( div( AS (-1), AS (3)) == AS (0)); assert( div( AS (-2), AS (3)) == AS (0)); assert( div( AS (-3), AS (3)) == AS (-1)); assert( mod( AS ( 3), AS (3)) == AS (0)); assert( mod( AS ( 2), AS (3)) == AS (2)); assert( mod( AS ( 1), AS (3)) == AS (1)); assert( mod( AS ( 0), AS (3)) == AS (0)); assert( mod( AS (-1), AS (3)) == AS (-1)); assert( mod( AS (-2), AS (3)) == AS (-2)); assert( mod( AS (-3), AS (3)) == AS (0)); assert( div( AS ( 3), AS(-3)) == AS (-1)); assert( div( AS ( 2), AS(-3)) == AS (0)); assert( div( AS ( 1), AS(-3)) == AS (0)); assert( div( AS ( 0), AS(-3)) == AS (0)); assert( div( AS (-1), AS(-3)) == AS (0)); assert( div( AS (-2), AS(-3)) == AS (0)); assert( div( AS (-3), AS(-3)) == AS (1)); assert( mod( AS ( 3), AS(-3)) == AS (0)); assert( mod( AS ( 2), AS(-3)) == AS (2)); assert( mod( AS ( 1), AS(-3)) == AS (1)); assert( mod( AS ( 0), AS(-3)) == AS (0)); assert( mod( AS (-1), AS(-3)) == AS (-1)); assert( mod( AS (-2), AS(-3)) == AS (-2)); assert( mod( AS (-3), AS(-3)) == AS (0)); for (int i = -12; i <= 12; i++){ for (int j = 1; j < 10; j++){ AS q,r; { AS a(i),b(j); div_mod(a,b,q,r); assert(q == div(a,b)); assert(r == mod(a,b)); }{ AS a(i),b(-j); div_mod(a,b,q,r); assert(q == div(a,b)); assert(r == mod(a,b)); } } } // special syntax test for expression template, e.g. mpz_class assert( div(AS(-4)+AS(-4),AS(3)*AS(1)) == AS (-2)); assert( mod(AS(-4)+AS(-4),AS(3)*AS(1)) == AS (-2)); AS q,r; div_mod(AS(-4)+AS(-4),AS(3)*AS(1),q,r); } template< class AS > void test_algebraic_structure_intern( const CGAL::Field_tag& ) { test_algebraic_structure_intern< AS >( CGAL::Integral_domain_tag()); AS a(1); AS b(3); AS& b_ref = b; b = b_ref; // to exercise self-copy AS c = a / b; (void)c; // avoid warnings for unused variables typedef Algebraic_structure_traits AST; typedef typename AST::Is_exact Is_exact; // VC7 produced an ICE for // assert( ! Is_exact::value || ... ); bool ie = Is_exact::value; assert( ! ie || c * b == a ); a = AS (1); a /= AS (2); a /= AS (2); // that must work correctly also for float types assert( a * AS (4) == AS (1)); typename AST::Divides divides; assert(divides(AS(2),AS(0))); assert(divides(AS(2),AS(5))); assert(divides(AS(5),AS(2))); AS tmp; assert(divides(AS(2),AS(0),tmp)); assert(!ie || tmp == AS(0)); assert(divides(AS(2),AS(5),tmp)); assert(!ie || tmp == AS(5)/AS(2)); assert(divides(AS(5),AS(2),tmp)); assert(!ie || tmp == AS(2)/AS(5)); assert(CGAL_NTS divides(AS(2),AS(0),tmp)); assert(!ie || tmp == AS(0)); assert(CGAL_NTS divides(AS(2),AS(5),tmp)); assert(!ie || tmp == AS(5)/AS(2)); assert(CGAL_NTS divides(AS(5),AS(2),tmp)); assert(!ie || tmp == AS(2)/AS(5)); typename AST::Inverse inverse; assert(AS(1)/AS(2) == inverse(AS(2))); assert(AS(1)/AS(2) == CGAL::inverse(AS(2))); } template void test_algebraic_structure_intern( const CGAL::Field_with_sqrt_tag& ) { test_algebraic_structure_intern< AS >( CGAL::Field_tag()); typedef CGAL::Algebraic_structure_traits< AS > AST; typedef typename AST::Is_exact Is_exact; CGAL_SNAP_AST_FUNCTORS(AST); static_assert(!::std::is_same< Sqrt, Null_functor>::value); const Sqrt sqrt =Sqrt(); AS a(4); AS c = sqrt( a); bool ie = Is_exact::value; assert( ! ie || (c == AS (2)) ); c = AS (5); assert( !ie || sqrt(c) * sqrt(c) == c ); (void)c; // avoid warnings for unused variables // #### more involved square root and root tests } //semantic test template void test_algebraic_structure_intern( const AS & a ,const AS & b, const AS & c, const CGAL::Integral_domain_without_division_tag&) { assert( a != AS (0)); assert( b != AS (0)); assert( c != AS (0)); // AS (0) == nullptr of IntegralDomain assert(a* AS (0)== AS (0)); assert(a+ AS (0)==a); assert(b* AS (0)== AS (0)); assert(b+ AS (0)==b); assert(c* AS (0)== AS (0)); assert(c+ AS (0)==c); // AS (1) == ONE of IntegralDomain assert(a* AS (1)==a); assert(b* AS (1)==b); assert(c* AS (1)==c); assert( AS (-1)* AS (-1)== AS (1)); //associative assert((a+b)+c==a+(b+c)); assert((a*b)*c==a*(b*c)); //commutative assert(a+b+c==c+b+a); assert(a*b*c==c*b*a); //distributive assert((a-b)*c==a*c-b*c); assert((a+b)*c==a*c+b*c); //binom assert((a+b)*(a+b)==a*a+ AS (2)*a*b+b*b); assert((a-b)*(a-b)==a*a- AS (2)*a*b+b*b); assert((a-b)*(a+b)==a*a-b*b); // unary operators assert(a==+a); assert(b==+b); assert(c==+c); assert(-a* AS (-1)==a); assert(-b* AS (-1)==b); assert(-c* AS (-1)==c); } template void test_algebraic_structure_intern( const AS & a ,const AS & b, const AS & c, const CGAL::Integral_domain_tag&) { assert( a != AS (0)); assert( b != AS (0)); assert( c != AS (0)); test_algebraic_structure_intern(a,b,c, CGAL::Integral_domain_without_division_tag()); typedef CGAL::Algebraic_structure_traits< AS > AST; CGAL_SNAP_AST_FUNCTORS(AST); //Integral_div const Integral_division integral_division = Integral_division(); assert(integral_division(a*b,a)==b); assert(integral_division(a*c,a)==c); assert(integral_division(b*a,b)==a); assert(integral_division(b*c,b)==c); assert(integral_division(c*a,c)==a); assert(integral_division(c*b,c)==b); assert(CGAL_NTS integral_division(c*b,c)==b); const Divides divides = Divides(); assert(divides(a,a*b)); assert(divides(a,a*c)); assert(divides(b,b*a)); assert(divides(b,b*c)); assert(divides(c,c*a)); assert(divides(c,c*b)); assert(CGAL_NTS divides(c,c*b)); } template void test_algebraic_structure_intern( const AS & a , const AS & b, const AS & c, const CGAL::Unique_factorization_domain_tag&) { assert( a != AS (0)); assert( b != AS (0)); assert( c != AS (0)); test_algebraic_structure_intern(a,b,c,CGAL::Integral_domain_tag()); typedef CGAL::Algebraic_structure_traits< AS > AST; CGAL_SNAP_AST_FUNCTORS(AST); const Gcd gcd = Gcd(); const Unit_part unit_part = Unit_part(); assert(unit_part(a)*gcd(a*b,a*c)==a*gcd(b,c)); assert(unit_part(b)*gcd(a*b,b*c)==b*gcd(a,c)); assert(unit_part(c)*gcd(a*c,b*c)==c*gcd(b,a)); assert(gcd( AS (0),a)*unit_part(a)==a); assert(gcd( AS (0),b)*unit_part(b)==b); assert(gcd( AS (0),c)*unit_part(c)==c); assert(gcd(-a,a)*unit_part(a)==a); assert(gcd(-b,b)*unit_part(b)==b); assert(gcd(-c,c)*unit_part(c)==c); } template void test_algebraic_structure_intern( const AS & a , const AS & b, const AS & c, const CGAL::Euclidean_ring_tag&) { assert( a != AS (0)); assert( b != AS (0)); assert( c != AS (0)); test_algebraic_structure_intern(a,b,c, CGAL::Unique_factorization_domain_tag()); typedef CGAL::Algebraic_structure_traits< AS > AST; CGAL_SNAP_AST_FUNCTORS(AST); const Div div = Div(); const Mod mod = Mod(); const Div_mod div_mod = Div_mod(); // do we have any AS tmp_mod,tmp_div; div_mod(a,b,tmp_div,tmp_mod); assert(tmp_div==div(a,b)); assert(tmp_mod==mod(a,b)); assert(tmp_div*b+tmp_mod==a); div_mod(a,c,tmp_div,tmp_mod); assert(tmp_div==div(a,c)); assert(tmp_mod==mod(a,c)); assert(tmp_div*c+tmp_mod==a); div_mod(c,b,tmp_div,tmp_mod); assert(tmp_div==div(c,b)); assert(tmp_mod==mod(c,b)); assert(tmp_div*b+tmp_mod==c); } template void test_algebraic_structure_intern( const AS & a, const AS & b, const AS & c, const CGAL::Field_tag&) { assert( a != AS (0)); assert( b != AS (0)); assert( c != AS (0)); test_algebraic_structure_intern(a,b,c,CGAL::Integral_domain_tag()); AS epsilon = AS (1)/ AS (128); assert( test_equality_epsilon( AS ((a/b)*b), AS ( a ), epsilon ) ); assert( test_equality_epsilon( AS ( (a/c)*c ), AS ( a ), epsilon ) ); assert( test_equality_epsilon( AS ( (b/a)*a ), AS ( b ), epsilon ) ); assert( test_equality_epsilon( AS ( (b/c)*c ), AS ( b ), epsilon ) ); assert( test_equality_epsilon( AS ( (c/b)*b ), AS ( c ), epsilon ) ); assert( test_equality_epsilon( AS ( (c/a)*a ), AS ( c ), epsilon ) ); } template void test_algebraic_structure_intern( const AS & a , const AS & b, const AS & c, const CGAL::Field_with_sqrt_tag&) { assert( a != AS (0)); assert( b != AS (0)); assert( c != AS (0)); test_algebraic_structure_intern(a,b,c,CGAL::Field_tag()); typedef CGAL::Algebraic_structure_traits< AS > AST; CGAL_SNAP_AST_FUNCTORS(AST); const Sqrt sqrt = Sqrt(); AS tmp; AS epsilon = AS (1); tmp=CGAL_NTS unit_part(a)*a; assert( test_equality_epsilon( sqrt(tmp)*sqrt(tmp), tmp, epsilon ) ); tmp=CGAL_NTS unit_part(b)*b; assert( test_equality_epsilon( sqrt(tmp)*sqrt(tmp), tmp, epsilon ) ); tmp=CGAL_NTS unit_part(c)*c; assert( test_equality_epsilon( sqrt(tmp)*sqrt(tmp), tmp, epsilon ) ); } template< class AS, class Is_square > class Test_is_square { public: void operator()( const Is_square& is_square ) { typedef typename Is_square::first_argument_type First_argument_type; typedef typename Is_square::second_argument_type Second_argument_type; typedef typename Is_square::result_type Result_type; CGAL_USE_TYPE(First_argument_type); CGAL_USE_TYPE(Second_argument_type); static_assert(::std::is_same< AS , First_argument_type>::value); static_assert(::std::is_same< AS& , Second_argument_type>::value); //static_assert(::std::is_same< bool , Result_type>::value); bool b = Result_type(true); CGAL_USE(b); AS test_number = AS(3)*AS(3); AS result; assert( is_square( test_number)); assert( is_square( test_number, result )); assert( test_equality_epsilon( result , AS(3), AS(1) ) ); assert( CGAL_NTS is_square( test_number)); assert( CGAL_NTS is_square( test_number, result )); assert( test_equality_epsilon( result , AS(3), AS(1) ) ); } }; template class Test_is_square< AS , CGAL::Null_functor> { public: void operator() (CGAL::Null_functor) { // ok, nothing to test } }; template class Test_sqrt { public: void operator() (const Sqrt& sqrt) { CGAL_USE(sqrt); typedef typename Sqrt::argument_type Argument_type; typedef typename Sqrt::result_type Result_type; CGAL_USE_TYPE(Argument_type); CGAL_USE_TYPE(Result_type); static_assert(::std::is_same< AS , Argument_type>::value); static_assert(::std::is_same< AS , Result_type>::value); typedef Algebraic_structure_traits AST; typedef typename AST::Is_exact Is_exact; assert( !Is_exact::value || AS (3) == sqrt( AS (9))); } }; template class Test_sqrt< AS , CGAL::Null_functor> { public: void operator() (CGAL::Null_functor) { // ok, nothing to test } }; template class Test_root { public: void operator() (const Root& root) { typedef typename Root::first_argument_type First_argument_type; typedef typename Root::second_argument_type Second_argument_type; typedef typename Root::result_type Result_type; CGAL_USE_TYPE(First_argument_type); CGAL_USE_TYPE(Second_argument_type); CGAL_USE_TYPE(Result_type); static_assert(::std::is_same::value); static_assert(::std::is_same< AS , Second_argument_type>::value); static_assert(::std::is_same< AS , Result_type>::value); AS epsilon(1); assert( test_equality_epsilon( AS (2), root( 4, AS (16) ), epsilon ) ); assert( test_equality_epsilon( AS (3), root( 3, AS (27) ), epsilon ) ); } }; template class Test_root< AS , CGAL::Null_functor> { public: void operator() (CGAL::Null_functor) { // ok, nothing to test } }; // Type_functions ----------------------------------------------- template void test_Type_functions( const CGAL::Integral_domain_without_division_tag&) { AS x(-15); CGAL_NTS simplify(x); assert(x== AS (-15)); CGAL_NTS unit_part(x); assert( CGAL_NTS is_zero( AS (0)) ); assert( CGAL_NTS is_one( AS (1)) ); assert( CGAL_NTS square( AS (23)) == AS (23*23) ); } template void test_Type_functions( const CGAL::Integral_domain_tag&) { test_Type_functions< AS > (CGAL::Integral_domain_without_division_tag()); assert(CGAL_NTS integral_division( AS (10), AS (2))== AS (5)); } template void test_Type_functions( const CGAL::Unique_factorization_domain_tag&) { test_Type_functions< AS >(CGAL::Integral_domain_tag()); assert(CGAL_NTS gcd( AS (21), AS (15)) == unit_normal(AS (3))); } template void test_Type_functions( const CGAL::Euclidean_ring_tag&) { test_Type_functions< AS >( CGAL::Unique_factorization_domain_tag()); //std::cerr << CGAL_NTS mod( AS(14), AS(5) ) << std::endl; AS q,r,a,b; a = AS(14); b = AS(5); r = CGAL_NTS mod(a,b); q = CGAL_NTS div(a,b); assert( a == b*q+r); CGAL_NTS div_mod(a,b,q,r); assert( a == b*q+r); } template void test_Type_functions( const CGAL::Field_tag&) { test_Type_functions< AS >(CGAL::Integral_domain_tag()); assert(CGAL_NTS unit_part( AS (-15))== AS (-15)); assert(CGAL_NTS unit_part( AS (1 ))== AS ( 1)); assert(CGAL_NTS unit_part( AS (0 ))== AS ( 1)); } template void test_Type_functions( const CGAL::Field_with_sqrt_tag&) { test_Type_functions< AS >(CGAL::Field_tag()); typedef Algebraic_structure_traits AST; typedef typename AST::Is_exact Is_exact; AS c = CGAL_NTS sqrt( AS (4)); bool ie = Is_exact::value; assert( !ie || c == AS (2) ); } template void test_Type_functions( const CGAL::Field_with_root_of_tag&) { test_Type_functions< AS >(CGAL::Field_with_sqrt_tag()); std::vector< AS > coeffs(4); coeffs[0]= AS (-27); coeffs[1]= AS (0); coeffs[2]= AS (0); coeffs[3]= AS (1); typedef CGAL::Algebraic_structure_traits< AS > AST; CGAL_SNAP_AST_FUNCTORS(AST); // typedef typename Root_of::Boundary Boundary; const Root_of root_of = Root_of(); AS real = root_of(1,coeffs.begin(),coeffs.end()); assert( real == AS (3)); assert(real*real == AS (9)); assert(real-real == AS (0)); assert(CGAL_NTS sqrt(real) == CGAL_NTS sqrt( AS (3))); // Test the function assert( CGAL_NTS root_of(1, coeffs.begin(), coeffs.end() ) == root_of( 1, coeffs.begin(), coeffs.end() ) ); /* AS real2 = root_of( AS (2), AS (4), coeffs.begin(), coeffs.end() ); assert( real2 == AS (3)); assert(real2*real2 == AS (9)); assert(real2-real2 == AS (0)); assert(CGAL::sqrt(real2) == CGAL::sqrt( AS (3))); */ } template void test_algebraic_structure(){ test_Type_functions< AS >(Algebraic_category()); typedef CGAL::Algebraic_structure_traits< AS > AST; CGAL_SNAP_AST_FUNCTORS(AST); static_assert(::std::is_same::value); typedef typename AST::Boolean Boolean; assert(!Boolean()); check_result_type(Is_zero(), Boolean()); check_result_type(Is_one(), Boolean()); check_result_type(Divides(), Boolean()); check_result_type(Is_square(), Boolean()); typedef typename AST::Algebraic_category Tag; using CGAL::Integral_domain_without_division_tag; using CGAL::Null_functor; // Test for desired exactness static_assert(::std::is_same< typename AST::Is_exact, Is_exact >::value); static_assert(::std::is_convertible< Tag, Integral_domain_without_division_tag >::value ); static_assert(::std::is_same< Tag, Algebraic_category>::value); static_assert(!::std::is_same< Simplify, Null_functor>::value); static_assert(!::std::is_same< Unit_part, Null_functor>::value); const Simplify simplify=Simplify();; const Unit_part unit_part= Unit_part(); // the other functors must exist as well, but they might be Null_functor's Integral_division integral_div; Gcd gcd; Div div; Mod mod; Div_mod div_mod; Sqrt sqrt; Kth_root root; Is_square is_square; // typename Traits::Find_only_zero_element find_only_zero_element; // typename Traits::Find_only_equal_pair find_only_equal_pair; (void)integral_div; // avoid warnings for unused variables (void)gcd; (void)div; (void)mod; (void)div_mod; (void)sqrt; (void)root; (void)is_square; // (void)find_only_zero_element; // (void)find_only_equal_pair; AS a; // DefaultConstructible AS b(127); // construction from small integers AS c(-127); a = b; // Assignable AS d(a); assert( a == b); // EqualityComparable assert( a == d); // EqualityComparable assert( c != b); assert( c != d); a = +b; assert( a == b); // == 127 a = -c; assert( a == b); // == 127 a = AS (1); b = AS (5); c = a + b; assert( c == AS (6)); c = a - b; assert( c == AS (-4)); c = a * b; assert( c == AS (5)); c = (a + AS (1)) * b; assert( c == AS (10)); c = b * AS (-3); assert( c == AS (-15)); c = a; c += b; assert( c == AS (6)); c = a; c -= b; assert( c == AS (-4)); c = a; c *= b; assert( c == AS (5)); c = a + AS (1); c *= b; assert( c == AS (10)); simplify(c); assert( c == AS (10)); unit_part( c); test_algebraic_structure_intern< AS >( Tag()); Test_sqrt< AS , typename AST::Sqrt> tsr; tsr(sqrt); Test_root< AS , typename AST::Kth_root> trt; trt(root); Test_is_square< AS, typename AST::Is_square > tis; tis(is_square); { std::vector< AS > v(5); v[0]= AS (30); v[1]= AS (-2); v[2]= AS (0); v[3]= AS (5); v[4]= AS (5); // functor // assert(2 == find_only_zero_element(v.begin(),v.end())); // function // CGAL::find_only_zero_element is not yet implemented // assert(2 == CGAL::find_only_zero_element(v.begin(),v.end())); std::vector< AS > w(3); w[0]= AS (10); w[1]= AS (-8); w[2]= AS (-2); // functor // find_only_equal_pair is not yet implemented // std::pair equal_pair(0,0); // // equal_pair = find_only_equal_pair(v.begin(),v.end(), // w.begin(),w.end()); // assert(1 == equal_pair.first); // assert(2 == equal_pair.second); //function // equal_pair = NiX::find_only_equal_pair(v.begin(),v.end(), // w.begin(),w.end()); // assert(1 == equal_pair.first); // assert(2 == equal_pair.second); } } template void test_algebraic_structure( const AS & a, const AS & b, const AS & c) { assert( a != AS (0)); assert( b != AS (0)); assert( c != AS (0)); test_algebraic_structure< AS ,Algebraic_category, Is_exact>(); test_algebraic_structure_intern(a,b,c,Algebraic_category()); typedef CGAL::Algebraic_structure_traits AST; typedef typename AST::Is_numerical_sensitive Is_numerical_sensitive; static_assert(!::std::is_same::value); CGAL_USE_TYPE(Is_numerical_sensitive); } } //namespace CGAL #include #endif // CGAL_TEST_ALGEBRAIC_STRUCTURE_H