mirror of https://github.com/CGAL/cgal
180 lines
5.5 KiB
C++
180 lines
5.5 KiB
C++
// ============================================================================
|
||
//
|
||
// Copyright (c) 2001-2006 Max-Planck-Institut Saarbruecken (Germany).
|
||
// All rights reserved.
|
||
//
|
||
// This file is part of EXACUS (http://www.mpi-inf.mpg.de/projects/EXACUS/).
|
||
// You can redistribute it and/or modify it under the terms of the GNU
|
||
// General Public License as published by the Free Software Foundation,
|
||
// either version 3 of the License, or (at your option) any later version.
|
||
//
|
||
// Licensees holding a valid commercial license may use this file in
|
||
// accordance with the commercial license agreement provided with the software.
|
||
//
|
||
// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
|
||
// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
|
||
//
|
||
// ----------------------------------------------------------------------------
|
||
//
|
||
// Library : CGAL
|
||
// File : test/Chinese_remaminder_test.C
|
||
// CGAL_release : $Name: $
|
||
// Revision : $Revision$
|
||
// Revision_date : $Date$
|
||
//
|
||
// Author(s) : Dominik H<>lse <dominik.huelse@gmx.de>
|
||
// Michael Hemmer <hemmer@mpi-inf.mpg.de>
|
||
//
|
||
// ============================================================================
|
||
|
||
#undef NDEBUG
|
||
#include <CGAL/basic.h>
|
||
#include <CGAL/Chinese_remainder_traits.h>
|
||
#include <CGAL/Arithmetic_kernel.h>
|
||
#include <CGAL/CORE_arithmetic_kernel.h>
|
||
#include <CGAL/LEDA_arithmetic_kernel.h>
|
||
#include <CGAL/Polynomial.h>
|
||
#include <CGAL/Residue.h>
|
||
#include <CGAL/Sqrt_extension.h>
|
||
#include <CGAL/primes.h>
|
||
#include <CGAL/use.h>
|
||
|
||
#include <cassert>
|
||
|
||
//#define WITH_OUTPUT 1
|
||
|
||
template <class NT>
|
||
struct Get_max_coefficient{
|
||
typedef NT result_type;
|
||
result_type operator () (const NT& a) {
|
||
return CGAL::abs(a);
|
||
}
|
||
};
|
||
|
||
template <class NT, class Root,class ACDE_TAG, class FP_TAG>
|
||
struct Get_max_coefficient<CGAL::Sqrt_extension<NT, Root, ACDE_TAG, FP_TAG> >{
|
||
typedef Get_max_coefficient<NT> GMC;
|
||
typedef typename GMC::result_type result_type;
|
||
|
||
result_type operator () (const CGAL::Sqrt_extension<NT, Root, ACDE_TAG, FP_TAG>& a) {
|
||
GMC gmc;
|
||
return (std::max)((std::max)(gmc(a.a0()), gmc(a.a1())), gmc(NT(a.root())));
|
||
}
|
||
};
|
||
|
||
template <class NT>
|
||
struct Get_max_coefficient<CGAL::Polynomial<NT> >{
|
||
typedef Get_max_coefficient<NT> GMC;
|
||
typedef typename GMC::result_type result_type;
|
||
|
||
result_type operator () (const CGAL::Polynomial<NT>& a) {
|
||
GMC gmc;
|
||
result_type m=0;
|
||
for(int i=0; i<=a.degree(); i++){
|
||
m = (std::max)(gmc(a[i]),m);
|
||
}
|
||
return m;
|
||
}
|
||
};
|
||
|
||
template<class NT>
|
||
void test_CR_for(const NT& f){
|
||
|
||
// Enforce IEEE double precision before using modular arithmetic
|
||
CGAL::Set_ieee_double_precision pfr;
|
||
|
||
typedef CGAL::Modular_traits<NT> MT;
|
||
CGAL_USE_TYPE(typename CGAL::Modular_traits<NT>::Residue_type);
|
||
typename MT::Modular_image modular_image;
|
||
typename MT::Modular_image_representative modular_image_representative;
|
||
|
||
|
||
typedef CGAL::Chinese_remainder_traits<NT> CRT;
|
||
typedef typename CRT::Scalar_type Scalar_type;
|
||
typename CRT::Chinese_remainder chinese_remainder;
|
||
|
||
Scalar_type max_coeff = Get_max_coefficient<NT>()(f);
|
||
|
||
NT g, g_old;
|
||
Scalar_type p,q,pq;
|
||
|
||
int prime_index, current_prime;
|
||
bool test = true;
|
||
prime_index = 0;
|
||
|
||
// init chinese remainder
|
||
q = current_prime = CGAL::internal::primes[prime_index];
|
||
CGAL::Residue::set_current_prime(current_prime);
|
||
g_old = modular_image_representative(modular_image(f));
|
||
pq= p = q;
|
||
|
||
|
||
// try chinese remainder
|
||
do{
|
||
// chinese remainder failed if q > 2*max_coeff(f)
|
||
CGAL_postcondition_msg(pq < p*(2*max_coeff), " chinese remainder failed ");
|
||
|
||
prime_index++;
|
||
if(prime_index < 1000){
|
||
current_prime = CGAL::internal::primes[prime_index];
|
||
}
|
||
else{
|
||
std::cerr<<"primes in the array exhausted"<<std::endl;
|
||
current_prime = CGAL::internal::get_next_lower_prime(current_prime);
|
||
}
|
||
CGAL::Residue::set_current_prime(current_prime);
|
||
p = current_prime;
|
||
|
||
chinese_remainder(q,g_old,p,modular_image_representative(modular_image(f)),pq,g);
|
||
|
||
try{
|
||
test = g != g_old;
|
||
}catch(...){}
|
||
|
||
q = pq;
|
||
g_old = g;
|
||
|
||
|
||
}while(test);
|
||
|
||
assert( g == f );
|
||
}
|
||
|
||
|
||
|
||
template<class AT>
|
||
void test_CR() {
|
||
typedef typename AT::Integer Integer;
|
||
typedef CGAL::Sqrt_extension<Integer,Integer> EXT;
|
||
typedef CGAL::Polynomial<Integer> Poly;
|
||
test_CR_for(Integer("13472398473248763214987"));
|
||
test_CR_for(EXT(
|
||
Integer("13472398473248763214987"),
|
||
Integer("43857430987524589"),
|
||
Integer("84397984359843")));
|
||
test_CR_for(EXT(
|
||
Integer("13472398473248763214987"),
|
||
Integer("0"),
|
||
Integer("84397984359843")));
|
||
test_CR_for(Poly(
|
||
Integer("13472398473248763214987"),
|
||
Integer("-43857430987524589"),
|
||
Integer("84397984359843")));
|
||
}
|
||
|
||
int main(){
|
||
|
||
#ifdef CGAL_USE_LEDA
|
||
test_CR<CGAL::LEDA_arithmetic_kernel>();
|
||
#endif // CGAL_USE_LEDA
|
||
|
||
#ifdef CGAL_USE_CORE
|
||
test_CR<CGAL::CORE_arithmetic_kernel>();
|
||
#endif // Lis_HAVE_CORE
|
||
|
||
return 0;
|
||
}
|
||
|
||
|
||
// EOF
|