-fix is valid Lazy_exact_nt

-make Lazy_exact_nt and root_of_2 play better together
-update root_of_2 and root_of_traits testsuite
This commit is contained in:
Sébastien Loriot 2006-12-21 15:24:20 +00:00
parent 7886199da9
commit 7013ca3965
4 changed files with 194 additions and 110 deletions

View File

@ -1246,7 +1246,7 @@ class Is_valid< Lazy_exact_nt<ET> >
: public Unary_function< Lazy_exact_nt<ET>, bool > {
public :
bool operator()( const Lazy_exact_nt<ET>& x ) const {
return is_valid(x.approx()) || is_valid(x.exact());
return is_valid(x.approx());
}
};
@ -1268,7 +1268,6 @@ fit_in_double(const Lazy_exact_nt<ET>& l, double& r)
// We create a type of new node in Lazy_exact_nt's DAG
// for the make_root_of_2() operation.
#if 0 // To be finished
template <typename ET >
struct Lazy_exact_ro2
: public Lazy_exact_nt_rep< typename Root_of_traits<ET>::RootOf_2 >
@ -1314,27 +1313,48 @@ struct Lazy_exact_ro2
}
};
template < typename ET >
inline
Lazy_exact_nt< typename Root_of_traits<ET>::RootOf_2 >
make_root_of_2( const Lazy_exact_nt<ET> &a,
const Lazy_exact_nt<ET> &b,
const Lazy_exact_nt<ET> &c, bool d)
{
return new Lazy_exact_ro2<ET>(a, b, c, d);
}
template <typename NT >
struct Root_of_traits< Lazy_exact_nt < NT > >
{
private:
typedef Root_of_traits<NT> T;
public:
typedef Root_of_traits< Lazy_exact_nt < NT > > Base;
typedef Lazy_exact_nt< typename T::RootOf_1 > RootOf_1;
typedef Lazy_exact_nt< typename T::RootOf_2 > RootOf_2;
typedef RootOf_2 Root_of_2;
typedef RootOf_1 Root_of_1;
struct Make_root_of_2{
typedef RootOf_2 result_type;
Root_of_2
operator()(const Lazy_exact_nt<NT>& a, const Lazy_exact_nt<NT>& b, const Lazy_exact_nt<NT>& c) const{
return new Lazy_exact_ro2<NT>(a, b, c, true);
};
RootOf_2
operator()(const Lazy_exact_nt<NT>& a, const Lazy_exact_nt<NT>& b, const Lazy_exact_nt<NT>& c, bool smaller) const{
return new Lazy_exact_ro2<NT>(a, b, c, smaller);
};
};
};
#endif // 0
//these two functions for test suite requirement
template < typename RT >
typename CGAL::Root_of_traits<CGAL::Lazy_exact_nt<RT> >::RootOf_2 make_sqrt(const CGAL::Lazy_exact_nt< RT> & r)
{
typedef Lazy_exact_nt< RT> TT;
CGAL_assertion(r >= 0);
if(CGAL_NTS is_zero(r)) return make_root_of_2((TT) 1,(TT) 0,(TT) 0);
return make_root_of_2((TT) 1,(TT) 0,-r,false);
}
template < typename RT >
void
print(std::ostream &os, const CGAL::Lazy_exact_nt< Root_of_2<RT> > &r)
{
print(os,r.exact());
}
#undef CGAL_double
#undef CGAL_int

View File

@ -992,7 +992,7 @@ Root_of_2<RT> make_sqrt(const RT& r)
}
template < typename RT >
Root_of_2<RT> make_sqrt(const typename Root_of_traits< RT >::RootOf_1 r)
Root_of_2<RT> make_sqrt(const typename Root_of_traits< RT >::RootOf_1& r)
{
CGAL_assertion(r >= 0);
if(CGAL_NTS is_zero(r)) return Root_of_2<RT>();

View File

@ -57,11 +57,10 @@ int main(){
test_root_of_traits<RT,Root_of_1,Root_of_2>();
test_root_of_traits<Root_of_1,Root_of_1,Root_of_2>();
}{
typedef CGAL::Lazy_exact_nt<CGAL::Gmpz> RT;
typedef CGAL::Quotient<CGAL::Lazy_exact_nt<CGAL::Gmpz> > Root_of_1;
typedef CGAL::Root_of_2<CGAL::Lazy_exact_nt<CGAL::Gmpz> > Root_of_2;
test_root_of_traits<RT,Root_of_1,Root_of_2>();
typedef CGAL::Lazy_exact_nt<CGAL::Gmpq> RT;
typedef CGAL::Lazy_exact_nt<CGAL::Gmpq> Root_of_1;
typedef CGAL::Lazy_exact_nt<CGAL::Root_of_2<CGAL::Gmpz> > Root_of_2;
test_root_of_traits<RT,Root_of_1,Root_of_2>();
test_root_of_traits<Root_of_1,Root_of_1,Root_of_2>();
}
#endif

View File

@ -58,26 +58,84 @@ NT my_rand()
return rnd.get_int(-64, 63);
}
//----------------------
template<class T>
bool is_RO2_class(const typename CGAL::Root_of_2<T>& ){ return true;}
template<class T>
bool is_RO2_class(const T& ){ return false;}
template<class T>
CGAL::Root_of_2<T> conjugate(const typename CGAL::Root_of_2<T>& R){
return R.conjugate();
}
template<class T>
T conjugate(const T& R){ return T(); }
template<class T>
T inverse_helper(const T& R){ return (T) 1/R; }
template<class T>
CGAL::Root_of_2<T> inverse_helper(const typename CGAL::Root_of_2<T>& R){
return inverse(R);
}
template<class T>
bool is_smaller_helper(const T& R){ return R.exact().is_smaller(); }
template<class T>
bool is_smaller_helper(const typename CGAL::Root_of_2<T>& R){ return R.is_smaller();}
template<class RT, class T>
RT bracket(const T& R,int i){ return R.exact()[i]; }
template<class RT>
RT bracket(const typename CGAL::Root_of_2<RT>& R,int i){
return R[i];
}
//----------------------------
template < class Root, class RT >
Root create_root_helper(RT a, RT b, Root *)
{
return Root(a)/b;
}
template < class T, class RT >
CGAL::Root_of_2<T> create_root_helper(RT a, RT b, typename CGAL::Root_of_2<T> *)
{
return CGAL::Root_of_2<T>(a, b);
}
template < class Root, class RT >
Root create_root(RT a, RT b)
{
return create_root_helper(a, b, (Root*) 0);
}
// Generate random Root_of_2 of degree 1
template < typename Root >
template < typename Root,typename RT >
Root my_rand_root_1()
{
typedef typename Root::RT RT;
Root r;
do {
RT a = my_rand<RT>();
if (a == 0)
continue;
r = Root(my_rand<RT>(), a);
r = create_root<Root>(my_rand<RT>(), a);
} while (! is_valid(r));
return r;
}
// Generate random Root_of_2 of degree 2
template < typename Root >
template < typename Root,typename RT >
Root my_rand_root()
{
typedef typename Root::RT RT;
do {
RT a = my_rand<RT>();
RT b = my_rand<RT>();
@ -85,9 +143,9 @@ Root my_rand_root()
if (a == 0 && b == 0)
return Root(c);
if (a == 0)
return Root(c, b);
return create_root<Root>(c, b);
if (b*b-4*a*c >= 0)
return Root(a, b, c, rnd.get_bool());
return CGAL::make_root_of_2(a, b, c, rnd.get_bool());
} while (true);
}
@ -111,13 +169,13 @@ test_compare(const Root &r1, const Root &r2)
return false;
}
template < typename Root >
template < typename RT, typename Root >
bool
test_to_interval(const Root &r1)
{
std::pair<double, double> the_interval = CGAL_NTS to_interval(r1);
if(!((to_double(r1) >= the_interval.first) && (to_double(r1) <= the_interval.second))) {
std::cout << r1[2] << " " << r1[1] << " " << r1[0] << " " << r1.is_smaller() << std::endl;
std::cout << bracket<RT>(r1,2) << " " << bracket<RT>(r1,1) << " " << bracket<RT>(r1,0) << " " << is_smaller_helper(r1) << std::endl;
std::cout << setprecision (18) << to_double(r1) << std::endl;
std::cout << "[" << setprecision (18) << the_interval.first << "," << setprecision (18) << the_interval.second << "]";
}
@ -126,30 +184,30 @@ test_to_interval(const Root &r1)
template < typename Root >
template < typename Root,typename RT,typename FT >
bool
test_root_of()
test_root_of_g()
{
typedef typename Root::RT RT;
CGAL::test_real_embeddable<Root>();
std::cout << " Testing zeros" << std::endl;
Root zero1(1, 0, 0, true);
Root zero2(1, 0, 0, false);
Root zero1=CGAL::make_root_of_2((RT) 1,(RT)0,(RT)0, true);
Root zero2=CGAL::make_root_of_2((RT)1,(RT)0,(RT)0, false);
Root zero3(0);
assert(zero1.conjugate() == zero2);
assert(zero2.conjugate() == zero1);
assert(zero3.conjugate() == zero3);
if (is_RO2_class(zero1)) assert(conjugate(zero1) == zero2);
if (is_RO2_class(zero2)) assert(conjugate(zero2) == zero1);
if (is_RO2_class(zero3)) assert(conjugate(zero3) == zero3);
assert(is_valid(zero1));
assert(is_valid(zero2));
assert(is_valid(zero3));
assert(CGAL_NTS to_double(zero1) == 0.0);
assert(CGAL_NTS to_double(zero2) == 0.0);
assert(CGAL_NTS to_double(zero3) == 0.0);
assert(test_to_interval(zero1));
assert(test_to_interval(zero2));
assert(test_to_interval(zero3));
assert(test_to_interval<RT>(zero1));
assert(test_to_interval<RT>(zero2));
assert(test_to_interval<RT>(zero3));
assert(CGAL_NTS sign(zero1) == 0);
assert(CGAL_NTS sign(zero2) == 0);
assert(CGAL_NTS sign(zero3) == 0);
@ -183,15 +241,15 @@ test_root_of()
assert(CGAL_NTS compare(zero2, zero3) == 0);
std::cout << " Testing ones" << std::endl;
Root one1 (-1, 0, 1, false);
Root mone1(-1, 0, 1, true);
Root one1=CGAL::make_root_of_2 ((RT)-1,(RT) 0,(RT) 1, false);
Root mone1=CGAL::make_root_of_2((RT)-1,(RT) 0,(RT) 1, true);
Root one2 = Root(1);
Root mone2 = Root(-1);
Root one3 = Root(1, 1);
Root mone3 = Root(-1, 1);
Root one3 = create_root<Root>((RT) 1,(RT) 1);
Root mone3 = create_root<Root>(-1, 1);
assert(one1.conjugate() == mone1);
if (is_RO2_class(one1)) assert(conjugate(one1) == mone1);
//It is not true that those must hold
//assert(one2.conjugate() == mone2);
//assert(one3.conjugate() == mone3);
@ -203,12 +261,12 @@ test_root_of()
assert(CGAL_NTS to_double(mone1) == -1.0);
assert(CGAL_NTS to_double(one2) == 1.0);
assert(CGAL_NTS to_double(mone2) == -1.0);
assert(test_to_interval(one1));
assert(test_to_interval(mone1));
assert(test_to_interval(one2));
assert(test_to_interval(mone2));
assert(test_to_interval(one3));
assert(test_to_interval(mone3));
assert(test_to_interval<RT>(one1));
assert(test_to_interval<RT>(mone1));
assert(test_to_interval<RT>(one2));
assert(test_to_interval<RT>(mone2));
assert(test_to_interval<RT>(one3));
assert(test_to_interval<RT>(mone3));
assert(CGAL_NTS sign( one1) > 0);
assert(CGAL_NTS sign( one2) > 0);
@ -261,16 +319,16 @@ test_root_of()
assert(CGAL_NTS compare( Root(0), Root(1)) < 0);
assert(CGAL_NTS compare( Root(1), Root(-1)) > 0);
assert(CGAL_NTS compare( Root(-4, 2), Root(-2)) == 0);
assert(CGAL_NTS compare( Root(-4, 2), Root(-1)) < 0);
assert(CGAL_NTS compare( Root(-4, 2), Root(-3)) > 0);
assert(CGAL_NTS compare( create_root<Root>(-4, 2), Root(-2)) == 0);
assert(CGAL_NTS compare( create_root<Root>(-4, 2), Root(-1)) < 0);
assert(CGAL_NTS compare( create_root<Root>(-4, 2), Root(-3)) > 0);
std::cout << " Testing degree 1 and 2" << std::endl;
Root rone(1, 0, -1, false);
Root rmone(1, 0, -1, true);
assert(rone.conjugate() == rmone);
assert(test_to_interval(rone));
assert(test_to_interval(rmone));
Root rone=CGAL::make_root_of_2((RT)1, (RT)0, (RT)-1, false);
Root rmone=CGAL::make_root_of_2((RT)1, (RT)0,(RT) -1, true);
if (is_RO2_class(rone)) assert(conjugate(rone) == rmone);
assert(test_to_interval<RT>(rone));
assert(test_to_interval<RT>(rmone));
// Compare the two roots of the above polynomial (-1 and 1),
// succesively with -2, -1, 0, 1, 2.
assert(CGAL_NTS compare(Root(-2), rmone) < 0);
@ -302,55 +360,55 @@ test_root_of()
Root r1 = Root(my_rand<RT>());
Root r2 = Root(my_rand<RT>());
assert(r1 == r1);
assert(test_to_interval(r1));
assert(test_to_interval<RT>(r1));
assert(r2 == r2);
assert(test_to_interval(r2));
assert(test_to_interval<RT>(r2));
// assert(test_compare(r1, r2));
}
std::cout << " Testing random roots of degree 1" << std::endl;
for (int i = 0; i < test_loops; ++i) {
Root r1 = my_rand_root_1<Root>();
Root r2 = my_rand_root_1<Root>();
Root r1 = my_rand_root_1<Root,RT>();
Root r2 = my_rand_root_1<Root,RT>();
assert(r1 == r1);
assert(test_to_interval(r1));
assert(test_to_interval<RT>(r1));
assert(r2 == r2);
assert(test_to_interval(r2));
assert(test_to_interval<RT>(r2));
// assert(test_compare(r1, r2));
}
std::cout << " Testing random roots of degree 2" << std::endl;
for (int i = 0; i < test_loops; ++i) {
Root r1 = my_rand_root<Root>();
Root r2 = my_rand_root<Root>();
Root r1 = my_rand_root<Root,RT>();
Root r2 = my_rand_root<Root,RT>();
assert(r1 == r1);
assert(test_to_interval(r1));
assert(test_to_interval<RT>(r1));
assert(r2 == r2);
assert(test_to_interval(r2));
assert(test_to_interval<RT>(r2));
// assert(test_compare(r1, r2));
}
std::cout << " Testing random roots of degree 1 and 2" << std::endl;
for (int i = 0; i < test_loops; ++i) {
Root r1 = my_rand_root_1<Root>();
Root r2 = my_rand_root<Root>();
Root r1 = my_rand_root_1<Root,RT>();
Root r2 = my_rand_root<Root,RT>();
assert(r1 == r1);
assert(test_to_interval(r1));
assert(test_to_interval<RT>(r1));
assert(r2 == r2);
assert(test_to_interval(r2));
assert(test_to_interval<RT>(r2));
// assert(test_compare(r1, r2));
}
std::cout << " Testing squares of random roots of degree 2" << std::endl;
for (int i = 0; i < test_loops; ++i) {
Root r1 = my_rand_root<Root>();
Root r2 = my_rand_root<Root>();
Root r1 = my_rand_root<Root,RT>();
Root r2 = my_rand_root<Root,RT>();
Root r1_sqr = CGAL_NTS square(r1);
Root r2_sqr = CGAL_NTS square(r2);
assert(test_to_interval(r1));
assert(test_to_interval(r2));
assert(test_to_interval(r1_sqr));
assert(test_to_interval(r2_sqr));
assert(test_to_interval<RT>(r1));
assert(test_to_interval<RT>(r2));
assert(test_to_interval<RT>(r1_sqr));
assert(test_to_interval<RT>(r2_sqr));
// double dr1 = to_double(r1);
// double dr2 = to_double(r2);
// assert(CGAL_NTS compare(r1_sqr, r2_sqr) == compare(dr1*dr1, dr2*dr2));
@ -360,7 +418,7 @@ test_root_of()
<< std::endl;
for (int i = 0; i < test_loops; ++i) {
RT r = my_rand<RT>();
Root r1 = my_rand_root<Root>();
Root r1 = my_rand_root<Root,RT>();
Root r2 = r1 - r;
Root r3 = r1 + r;
Root r4 = r - r1;
@ -370,11 +428,11 @@ test_root_of()
assert(r3 == r3);
assert(r4 == r4);
assert(r5 == r5);
assert(test_to_interval(r1));
assert(test_to_interval(r2));
assert(test_to_interval(r3));
assert(test_to_interval(r4));
assert(test_to_interval(r5));
assert(test_to_interval<RT>(r1));
assert(test_to_interval<RT>(r2));
assert(test_to_interval<RT>(r3));
assert(test_to_interval<RT>(r4));
assert(test_to_interval<RT>(r5));
// assert(test_compare(r1, r2));
// assert(test_compare(r1, r3));
// assert(test_compare(r1, r4));
@ -388,31 +446,31 @@ test_root_of()
std::cout << " Testing multiplication of Root_of_2<NT> with NT" << std::endl;
for (int i = 0; i < test_loops; ++i) {
RT r = my_rand<RT>();
Root r1 = my_rand_root<Root>();
Root r1 = my_rand_root<Root,RT>();
Root r2 = r1 * r;
Root r3 = r * r1;
int n = rnd.get_int(0, 63);
typename Root::FT rn(n);
FT rn(n);
if (r != 0){
Root r4 = r2 / r;
assert(r4 == r4);
assert(test_to_interval(r4));
assert(test_to_interval<RT>(r4));
assert(r4 == r1);
}
if (n != 0){
Root r5 = my_rand_root<Root>();
Root r5 = my_rand_root<Root,RT>();
Root r6 = r5 * rn;
Root r4 = r6 / rn;
assert(r4 == r4);
assert(test_to_interval(r4));
assert(test_to_interval<RT>(r4));
assert(r4 == r5);
}
assert(r1 == r1);
assert(r2 == r2);
assert(r3 == r3);
assert(test_to_interval(r1));
assert(test_to_interval(r2));
assert(test_to_interval(r3));
assert(test_to_interval<RT>(r1));
assert(test_to_interval<RT>(r2));
assert(test_to_interval<RT>(r3));
// assert(test_compare(r1, r2));
// assert(test_compare(r1, r3));
// assert(test_compare(r2, r3));
@ -431,16 +489,16 @@ test_root_of()
std::cout << " Testing the inverse of random roots of degree 2" << std::endl;
for (int i = 0; i < test_loops; ++i) {
Root r1 = my_rand_root<Root>();
Root r2 = my_rand_root<Root>();
while(r1 == 0) r1 = my_rand_root<Root>();
while(r2 == 0) r2 = my_rand_root<Root>();
Root r1_inv = inverse(r1);
Root r2_inv = inverse(r2);
assert(test_to_interval(r1));
assert(test_to_interval(r2));
assert(test_to_interval(r1_inv));
assert(test_to_interval(r2_inv));
Root r1 = my_rand_root<Root,RT>();
Root r2 = my_rand_root<Root,RT>();
while(r1 == 0) r1 = my_rand_root<Root,RT>();
while(r2 == 0) r2 = my_rand_root<Root,RT>();
Root r1_inv = inverse_helper(r1);
Root r2_inv = inverse_helper(r2);
assert(test_to_interval<RT>(r1));
assert(test_to_interval<RT>(r2));
assert(test_to_interval<RT>(r1_inv));
assert(test_to_interval<RT>(r2_inv));
// double dr1 = to_double(r1);
// double dr2 = to_double(r2);
// assert(CGAL_NTS compare(r1_inv, r2_inv) == compare(1.0/dr1, 1.0/dr2));
@ -454,8 +512,8 @@ test_root_of()
while(r2 < 0) r2 = my_rand<RT>();
Root sqr_r1 = CGAL::make_sqrt(r1);
Root sqr_r2 = CGAL::make_sqrt(r2);
assert(test_to_interval(sqr_r1));
assert(test_to_interval(sqr_r2));
assert(test_to_interval<RT>(sqr_r1));
assert(test_to_interval<RT>(sqr_r2));
// double dr1 = to_double(r1);
// double dr2 = to_double(r2);
// assert(CGAL_NTS compare(sqr_r1, sqr_r2) == compare(std::sqrt(dr1), std::sqrt(dr2)));
@ -464,12 +522,11 @@ test_root_of()
std::cout << " Testing Root_of_2<FT>" << std::endl;
for (int i = 0; i < test_loops; ++i) {
int n = rnd.get_int(0, 63);
typedef typename Root::FT FT;
typedef CGAL::Rational_traits<FT> Rat_traits;
FT r(n);
Root r1(r);
Root r2(n);
Root r3(Rat_traits().numerator(r), Rat_traits().denominator(r));
Root r3=create_root<Root>(Rat_traits().numerator(r), Rat_traits().denominator(r));
assert(r1 == r1);
assert(r2 == r2);
assert(r3 == r3);
@ -480,6 +537,14 @@ test_root_of()
return true;
}
template<typename Root >
bool
test_root_of(){
typedef typename Root::RT RT;
typedef typename Root::FT FT;
return test_root_of_g<Root,RT,FT>();
}
// ALL THOSE TESTS ARE BASED ON COMPARING THE DOUBLE RESULT
// WITH THE EXACT RESULT
// THAT IS NOT NECESSARILY CORRECT
@ -493,7 +558,7 @@ int main(int argc, char **argv) {
bool result = true;
// std::cout << "Testing Root_of_2<double>" << std::endl;
// result = result && test_root_of<Root_of_2<double> >();
//~ result = result && test_root_of<Root_of_2<double> >();
std::cout << "Testing Root_of_2<MP_Float>" << std::endl;
result = result && test_root_of<Root_of_2<CGAL::MP_Float> >();
@ -507,8 +572,8 @@ int main(int argc, char **argv) {
std::cout << "Testing Lazy_exact_nt<MP_Float>'s RootOf_2 " << std::endl;
result = result &&
test_root_of<CGAL::Root_of_traits<CGAL::Lazy_exact_nt<CGAL::MP_Float> >
::RootOf_2 >();
test_root_of_g<CGAL::Root_of_traits<CGAL::Lazy_exact_nt<CGAL::MP_Float> >
::RootOf_2,CGAL::Lazy_exact_nt<CGAL::MP_Float>,CGAL::Lazy_exact_nt<CGAL::MP_Float> >();
#ifdef CGAL_USE_GMP