mirror of https://github.com/CGAL/cgal
956 lines
31 KiB
C++
956 lines
31 KiB
C++
// 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 <kettner@mpi-inf.mpg.de>
|
|
// Michael Hemmer <hemmer@mpi-inf.mpg.de>
|
|
//
|
|
// =============================================================================
|
|
|
|
/* \brief provides test functions for the various ring concepts of number
|
|
* types.
|
|
*/
|
|
|
|
// within this file AS ^= Type
|
|
|
|
#include <CGAL/Algebraic_structure_traits.h>
|
|
//#include <CGAL/Real_embeddable_traits.h>
|
|
|
|
#include <CGAL/number_utils.h>
|
|
#include <CGAL/assertions.h>
|
|
#include <CGAL/use.h>
|
|
#include <boost/type_traits.hpp>
|
|
#include <CGAL/tags.h>
|
|
#include <cassert>
|
|
#include <functional>
|
|
|
|
#include <vector>
|
|
|
|
#include <CGAL/Testsuite/use.h>
|
|
|
|
|
|
#ifndef CGAL_TEST_ALGEBRAIC_STRUCTURE_H
|
|
#define CGAL_TEST_ALGEBRAIC_STRUCTURE_H
|
|
|
|
#include <CGAL/disable_warnings.h>
|
|
|
|
// checks the result type of a functor
|
|
template <typename AdaptableFunctor, typename ResultType>
|
|
void check_result_type(AdaptableFunctor, ResultType){
|
|
typedef typename AdaptableFunctor::result_type result_type;
|
|
static_assert((::std::is_same<result_type,ResultType>::value));
|
|
CGAL_USE_TYPE(result_type);
|
|
}
|
|
// check nothing for CGAL::Null_functor
|
|
template <typename ResultType>
|
|
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<AS> 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<AS> 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<AS> 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 <class AS >
|
|
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 <class AS >
|
|
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);
|
|
//distributiv
|
|
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 <class AS >
|
|
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 <class AS >
|
|
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 <class AS >
|
|
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 <class AS >
|
|
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 <class AS >
|
|
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 AS >
|
|
class Test_is_square< AS , CGAL::Null_functor> {
|
|
public:
|
|
void operator() (CGAL::Null_functor) {
|
|
// ok, nothing to test
|
|
}
|
|
};
|
|
|
|
template<class AS , class Sqrt>
|
|
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<AS> AST;
|
|
typedef typename AST::Is_exact Is_exact;
|
|
assert( !Is_exact::value || AS (3) == sqrt( AS (9)));
|
|
}
|
|
};
|
|
|
|
template<class AS >
|
|
class Test_sqrt< AS , CGAL::Null_functor> {
|
|
public:
|
|
void operator() (CGAL::Null_functor) {
|
|
// ok, nothing to test
|
|
}
|
|
};
|
|
|
|
template<class AS , class Root>
|
|
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<int, First_argument_type>::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 AS >
|
|
class Test_root< AS , CGAL::Null_functor> {
|
|
public:
|
|
void operator() (CGAL::Null_functor) {
|
|
// ok, nothing to test
|
|
}
|
|
};
|
|
|
|
// Type_functions -----------------------------------------------
|
|
template <class AS >
|
|
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 <class AS >
|
|
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 <class AS >
|
|
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 <class AS >
|
|
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 <class AS >
|
|
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 <class AS >
|
|
void test_Type_functions( const CGAL::Field_with_sqrt_tag&) {
|
|
test_Type_functions< AS >(CGAL::Field_tag());
|
|
typedef Algebraic_structure_traits<AS> 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 <class AS >
|
|
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 <class AS , class Algebraic_category, class Is_exact>
|
|
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<AS,typename AST::Type>::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(( ::boost::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<int,int> 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 <class AS , class Algebraic_category, class Is_exact >
|
|
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<AS> AST;
|
|
typedef typename AST::Is_numerical_sensitive Is_numerical_sensitive;
|
|
static_assert(
|
|
!(::std::is_same<Is_numerical_sensitive, CGAL::Null_tag>::value));
|
|
CGAL_USE_TYPE(Is_numerical_sensitive);
|
|
}
|
|
|
|
} //namespace CGAL
|
|
|
|
#include <CGAL/enable_warnings.h>
|
|
|
|
#endif // CGAL_TEST_ALGEBRAIC_STRUCTURE_H
|