make_root_of_2() merged into each number type files like all other

NT requirements.
This commit is contained in:
Sylvain Pion 2006-04-06 09:10:38 +00:00
parent cf5519caf3
commit d2f695fa4c
14 changed files with 349 additions and 84 deletions

View File

@ -38,6 +38,10 @@
#include <boost/operators.hpp>
#include <CGAL/make_root_of_2.h>
#include <CGAL/Root_of_traits.h>
#include <CGAL/Root_of_2.h>
CGAL_BEGIN_NAMESPACE
// TODO : add mixed operators with Gmpz.
@ -319,6 +323,23 @@ struct Rational_traits<Gmpq> {
{ return n / d; }
};
inline
Root_of_2< CGAL::Gmpz >
make_root_of_2(const CGAL::Gmpq &a, const CGAL::Gmpq &b,
const CGAL::Gmpq &c, bool d)
{
return CGALi::make_root_of_2_rational< CGAL::Gmpz, CGAL::Gmpq >(a,b,c,d);
}
// CGAL::Gmpq is the same as Root_of_traits< CGAL::Gmpz >::RootOf_1
template <>
struct Root_of_traits< CGAL::Gmpq >
{
typedef CGAL::Gmpq RootOf_1;
typedef Root_of_2< CGAL::Gmpz > RootOf_2;
};
CGAL_END_NAMESPACE
#endif // CGAL_GMPQ_H

View File

@ -42,6 +42,9 @@
#include <boost/operators.hpp>
#include <CGAL/Root_of_traits.h>
#include <CGAL/Root_of_2_fwd.h>
CGAL_BEGIN_NAMESPACE
// TODO : benchmark without ref-counting, and maybe give the possibility
@ -475,4 +478,25 @@ double to_double(const Quotient<Gmpz>& quot)
CGAL_END_NAMESPACE
#include <CGAL/Root_of_2.h>
CGAL_BEGIN_NAMESPACE
template <>
struct Root_of_traits< CGAL::Gmpz >
{
typedef CGAL::Gmpq RootOf_1;
typedef Root_of_2< CGAL::Gmpz > RootOf_2;
};
inline
Root_of_2<Gmpz>
make_root_of_2(const Gmpz &a, const Gmpz &b, const Gmpz &c, bool smaller)
{
CGAL_assertion( a != 0 );
return Root_of_2<Gmpz>(a, b, c, smaller);
}
CGAL_END_NAMESPACE
#endif // CGAL_GMPZ_H

View File

@ -25,6 +25,7 @@
#define CGAL_GMPZQ_FWD_H
#include <CGAL/Quotient_fwd.h>
#include <CGAL/Root_of_2_fwd.h>
// Forward declarations of functions over Gmpz and Gmpq.
@ -52,6 +53,10 @@ std::pair<double, double> to_interval (const Gmpq &);
double to_double(const Quotient<Gmpz>&);
Root_of_2< CGAL::Gmpz >
make_root_of_2(const CGAL::Gmpq &a, const CGAL::Gmpq &b,
const CGAL::Gmpq &c, bool d);
CGAL_END_NAMESPACE
#endif // CGAL_GMPZQ_FWD_H

View File

@ -50,6 +50,9 @@
#include <boost/operators.hpp>
#include <CGAL/Root_of_traits.h>
#include <CGAL/make_root_of_2.h>
CGAL_BEGIN_NAMESPACE
#define CGAL_int(T) typename First_if_different<int, T>::Type
@ -573,6 +576,22 @@ struct Rational_traits< Quotient<NT> >
{ return n / d; }
};
template < class NT >
inline
typename Root_of_traits< NT >::RootOf_2
make_root_of_2(const Quotient< NT > &a, const Quotient< NT > &b,
const Quotient< NT > &c, bool d)
{
return CGALi::make_root_of_2_rational< NT, Quotient< NT > >(a,b,c,d);
}
// CGAL::Quotient<NT> should be the same as Root_of_traits<NT>::RootOf_1
// i.e the default implementation.
template < class NT >
struct Root_of_traits< Quotient< NT > >
: public Root_of_traits< NT > {};
CGAL_END_NAMESPACE
#endif // CGAL_QUOTIENT_H

View File

@ -27,6 +27,7 @@
CGAL_BEGIN_NAMESPACE
template <class NT> class Quotient;
template <class RT> class Root_of_traits;
template <class NT>
Quotient<NT> sqrt(const Quotient<NT> &);
@ -46,6 +47,11 @@ bool is_valid(const Quotient<NT>&);
template <class NT>
bool is_finite(const Quotient<NT>&);
template < class NT >
typename Root_of_traits< NT >::RootOf_2
make_root_of_2(const Quotient< NT > &a, const Quotient< NT > &b,
const Quotient< NT > &c, bool d);
CGAL_END_NAMESPACE
#endif // CGAL_QUOTIENT_FWD_H

View File

@ -24,6 +24,7 @@
#include <iostream>
#include <CGAL/basic.h>
#include <CGAL/Root_of_2_fwd.h>
#include <CGAL/Root_of_traits.h>
#include <CGAL/NT_converter.h>
#include <CGAL/enum.h>
@ -81,8 +82,6 @@ namespace CGAL {
// polynomial class which performed this task (and others)...
// - overloaded versions of make_root_of_2<>() for Lazy_exact_nt<> and others.
template < typename RT > struct Root_of_traits;
template < typename RT_ >
class Root_of_2 {
RT_ C0,C1,C2; // Coefficients (see below)
@ -202,31 +201,6 @@ public:
}; // Root_of_2
template < typename RT > class Root_of_2;
template < typename RT > class Root_of_3;
template < typename RT > class Root_of_4;
// Template default version generating a Root_of_2<>.
template < typename RT >
inline
Root_of_2<RT>
make_root_of_2(const RT &a, const RT &b, const RT &c, bool smaller)
{
CGAL_assertion( a != 0 );
return Root_of_2<RT>(a, b, c, smaller);
}
//Default Traits class for RT types
template < typename RT >
struct Root_of_traits
{
typedef Quotient< RT > RootOf_1;
typedef Root_of_2< RT > RootOf_2;
typedef Root_of_3< RT > RootOf_3;
typedef Root_of_4< RT > RootOf_4;
};
template < class NT1,class NT2 >
struct NT_converter < Root_of_2<NT1> , Root_of_2<NT2> >
: public std::unary_function< NT1, NT2 >
@ -265,51 +239,6 @@ struct NT_converter < Root_of_2<NT1>, Root_of_2<NT1> >
}
};
namespace CGALi {
// This version is internal and can be re-used for
// number types which also support division and sqrt().
template < typename NT >
NT
make_root_of_2_sqrt(const NT &a, const NT &b, const NT &c, bool smaller)
{
CGAL_assertion( a != 0 );
NT discriminant = CGAL_NTS square(b) - a*c*4;
CGAL_assertion( discriminant >= 0 );
NT d = sqrt(discriminant);
if ((smaller && a>0) || (!smaller && a<0))
d = -d;
return (d-b)/(a*2);
}
// This version is internal and can be re-used for
// number types which are rational.
template < typename RT, typename FT >
Root_of_2< RT >
make_root_of_2_rational(const FT &a, const FT &b, const FT &c, bool smaller)
{
typedef CGAL::Rational_traits< FT > Rational;
Rational r;
// CGAL_assertion( r.denominator(a) > 0 );
// CGAL_assertion( r.denominator(b) > 0 );
// CGAL_assertion( r.denominator(c) > 0 );
/* const RT lcm = ( r.denominator(a) * r.denominator(b) * r.denominator(c) )/
( gcd( r.denominator(a), gcd(r.denominator(b), r.denominator(c)) ) );
RT a_ = r.numerator(a) * ( lcm / r.denominator(a) );
RT b_ = r.numerator(b) * ( lcm / r.denominator(b) );
RT c_ = r.numerator(c) * ( lcm / r.denominator(c) );
*/
RT a_ = r.numerator(a) * r.denominator(b) * r.denominator(c);
RT b_ = r.numerator(b) * r.denominator(a) * r.denominator(c);
RT c_ = r.numerator(c) * r.denominator(a) * r.denominator(b);
return make_root_of_2(a_,b_,c_,smaller);
}
} // namespace CGALi
template < typename RT >
Sign

View File

@ -77,8 +77,16 @@ io_Operator io_tag(const Root_of_2<T>&);
template < typename T >
Root_of_2<T> square(const Root_of_2<T>&);
template < typename T >
Root_of_2<T> make_root_of_2(const T &a, const T &b, const T &c, bool smaller);
namespace CGALi {
template < typename RT,
typename Has_sqrt = typename Number_type_traits<RT>::Has_sqrt >
struct Make_root_of_2_helper;
} // CGALi
// Template default version generating a Root_of_2<>.
template < typename RT >
typename CGALi::Make_root_of_2_helper<RT>::result_type
make_root_of_2(const RT &a, const RT &b, const RT &c, bool smaller);
CGAL_END_NAMESPACE

View File

@ -0,0 +1,59 @@
// Copyright (c) 2005,2006 INRIA Sophia-Antipolis (France)
// All rights reserved.
//
// This file is part of CGAL (www.cgal.org); you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public License as
// published by the Free Software Foundation; version 2.1 of the License.
// See the file LICENSE.LGPL distributed with CGAL.
//
// 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.
//
// $URL$
// $Id$
//
//
// Author(s) : Sylvain Pion, Monique Teillaud, Athanasios Kakargias
#ifndef CGAL_ROOT_OF_TRAITS_H
#define CGAL_ROOT_OF_TRAITS_H
#include <CGAL/basic.h>
#include <CGAL/Root_of_2_fwd.h>
#include <CGAL/Quotient_fwd.h>
namespace CGAL {
namespace CGALi {
// Dispatcher for the case Has_sqrt==Tag_true or not.
template < typename RT,
typename Has_sqrt = typename Number_type_traits<RT>::Has_sqrt >
struct Root_of_traits_helper
{
typedef Quotient< RT > RootOf_1;
typedef Root_of_2< RT > RootOf_2;
};
// Specialization for Has_sqrt==Tag_true.
template < typename RT >
struct Root_of_traits_helper < RT, Tag_true >
{
typedef RT RootOf_1;
typedef RT RootOf_2;
};
} // namespace CGALi
// Default Traits class for RT types
template < typename RT >
struct Root_of_traits
: public CGALi::Root_of_traits_helper<RT> {};
} // namespace CGAL
#endif // CGAL_ROOT_OF_TRAITS_H

View File

@ -32,6 +32,9 @@
#include <gmpxx.h>
#include <mpfr.h>
#include <CGAL/Root_of_traits.h>
#include <CGAL/Root_of_2.h>
// This file gathers the necessary adaptors so that the following
// C++ number types that come with GMP can be used by CGAL :
// - mpz_class
@ -200,6 +203,63 @@ bool
is_negative(const ::__gmp_expr<T, U> & e)
{ return ::sgn(e) < 0; }
// XXX : __gmpz_value does not work with GMP >= 4.2
// Idea for fixing : parameterize by __gmp_expr<T, U[123]>, and add
// a CGALi function taking a __gmp_expr<T, T> as pointer to distinguish,
// matching mp[zq]_class.
template < typename U1, typename U2, typename U3 >
inline
Root_of_2< ::mpz_class >
make_root_of_2(const ::__gmp_expr< __gmpz_value, U1> & a,
const ::__gmp_expr< __gmpz_value, U2> & b,
const ::__gmp_expr< __gmpz_value, U3> & c,
bool d)
{
return Root_of_2< ::mpz_class >(a, b, c, d);
}
template < typename U1, typename U2, typename U3 >
inline
Root_of_2< ::mpz_class >
make_root_of_2(const ::__gmp_expr< __gmpq_value, U1> & a,
const ::__gmp_expr< __gmpq_value, U2> & b,
const ::__gmp_expr< __gmpq_value, U3> & c,
bool d)
{
typedef CGAL::Rational_traits< ::mpq_class > Rational;
Rational r;
CGAL_assertion( r.denominator(a) > 0 );
CGAL_assertion( r.denominator(b) > 0 );
CGAL_assertion( r.denominator(c) > 0 );
/* const RT lcm = ( r.denominator(a) * r.denominator(b) * r.denominator(c) )/
( gcd( r.denominator(a), gcd(r.denominator(b), r.denominator(c)) ) );
RT a_ = r.numerator(a) * ( lcm / r.denominator(a) );
RT b_ = r.numerator(b) * ( lcm / r.denominator(b) );
RT c_ = r.numerator(c) * ( lcm / r.denominator(c) );
*/
::mpz_class a_ = r.numerator(a) * r.denominator(b) * r.denominator(c);
::mpz_class b_ = r.numerator(b) * r.denominator(a) * r.denominator(c);
::mpz_class c_ = r.numerator(c) * r.denominator(a) * r.denominator(b);
return Root_of_2< ::mpz_class >(a, b, c, d);
}
template < typename T, typename U >
struct Root_of_traits< ::__gmp_expr<T, U> >
{
typedef ::mpq_class RootOf_1;
typedef Root_of_2< ::mpz_class > RootOf_2;
};
CGAL_END_NAMESPACE
// XXX : These seem necessary.
// I don't know why doing them in namespace CGAL is not enough.
// using CGAL::to_double;
// using CGAL::is_valid;
#endif // CGAL_GMPXX_H

View File

@ -27,6 +27,7 @@
#ifdef CGAL_USE_GMPXX
#include <gmpxx.h>
#include <CGAL/Root_of_2_fwd.h>
CGAL_BEGIN_NAMESPACE
@ -75,6 +76,20 @@ bool is_positive(const ::__gmp_expr<T, U> &);
template < typename T, typename U >
bool is_negative(const ::__gmp_expr<T, U> &);
template < typename U1, typename U2, typename U3 >
Root_of_2< ::mpz_class >
make_root_of_2(const ::__gmp_expr< __gmpz_value, U1> & a,
const ::__gmp_expr< __gmpz_value, U2> & b,
const ::__gmp_expr< __gmpz_value, U3> & c,
bool d);
template < typename U1, typename U2, typename U3 >
Root_of_2< ::mpz_class >
make_root_of_2(const ::__gmp_expr< __gmpq_value, U1> & a,
const ::__gmp_expr< __gmpq_value, U2> & b,
const ::__gmp_expr< __gmpq_value, U3> & c,
bool d);
CGAL_END_NAMESPACE
#endif // CGAL_USE_GMPXX

View File

@ -0,0 +1,117 @@
// Copyright (c) 2005,2006 INRIA Sophia-Antipolis (France)
// All rights reserved.
//
// This file is part of CGAL (www.cgal.org); you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public License as
// published by the Free Software Foundation; version 2.1 of the License.
// See the file LICENSE.LGPL distributed with CGAL.
//
// 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.
//
// $URL$
// $Id$
//
//
// Author(s) : Sylvain Pion, Monique Teillaud, Athanasios Kakargias
#ifndef CGAL_MAKE_ROOT_OF_2_H
#define CGAL_MAKE_ROOT_OF_2_H
#include <iostream>
#include <CGAL/basic.h>
#include <CGAL/Root_of_2_fwd.h>
namespace CGAL {
namespace CGALi {
// This version is internal and can be re-used for
// number types which also support division and sqrt().
template < typename NT >
NT
make_root_of_2_sqrt(const NT &a, const NT &b, const NT &c, bool smaller)
{
CGAL_assertion( a != 0 );
NT discriminant = CGAL_NTS square(b) - a*c*4;
CGAL_assertion( discriminant >= 0 );
NT d = CGAL_NTS sqrt(discriminant);
if ((smaller && a>0) || (!smaller && a<0))
d = -d;
return (d-b)/(a*2);
}
// This version is internal and can be re-used for
// number types which are rational.
template < typename RT, typename FT >
Root_of_2< RT >
make_root_of_2_rational(const FT &a, const FT &b, const FT &c, bool smaller)
{
typedef CGAL::Rational_traits< FT > Rational;
Rational r;
// CGAL_assertion( r.denominator(a) > 0 );
// CGAL_assertion( r.denominator(b) > 0 );
// CGAL_assertion( r.denominator(c) > 0 );
/* const RT lcm = ( r.denominator(a) * r.denominator(b) * r.denominator(c) )/
( gcd( r.denominator(a), gcd(r.denominator(b), r.denominator(c)) ) );
RT a_ = r.numerator(a) * ( lcm / r.denominator(a) );
RT b_ = r.numerator(b) * ( lcm / r.denominator(b) );
RT c_ = r.numerator(c) * ( lcm / r.denominator(c) );
*/
RT a_ = r.numerator(a) * r.denominator(b) * r.denominator(c);
RT b_ = r.numerator(b) * r.denominator(a) * r.denominator(c);
RT c_ = r.numerator(c) * r.denominator(a) * r.denominator(b);
return make_root_of_2(a_,b_,c_,smaller);
}
// automatic dispatcher between the 2 generic versions (using Root_of_2 or
// sqrt()), if sqrt() exists (checking Has_sqrt).
template < typename RT,
typename Has_sqrt /*= typename Number_type_traits<RT>::Has_sqrt*/ >
struct Make_root_of_2_helper
{
typedef Root_of_2<RT> result_type;
result_type operator()(const RT& a, const RT& b, const RT& c, bool smaller)
const
{
return Root_of_2<RT>(a, b, c, smaller);
}
};
// Specialization for Has_sqrt == Tag_true
template < typename RT >
struct Make_root_of_2_helper <RT, Tag_true>
{
typedef RT result_type;
result_type operator()(const RT& a, const RT& b, const RT& c, bool smaller)
const
{
return CGALi::make_root_of_2_sqrt(a, b, c, smaller);
}
};
} // namespace CGALi
// Template default version generating a Root_of_2<>.
template < typename RT >
inline
typename CGALi::Make_root_of_2_helper<RT>::result_type
make_root_of_2(const RT &a, const RT &b, const RT &c, bool smaller)
{
CGAL_assertion( a != 0 );
return CGALi::Make_root_of_2_helper<RT>()(a, b, c, smaller);
}
} // namespace CGAL
#endif // CGAL_MAKE_ROOT_OF_2_H

View File

@ -77,6 +77,8 @@ CGAL_END_NAMESPACE
#include <CGAL/Quotient_fwd.h>
#include <CGAL/Root_of_2_fwd.h>
#include <CGAL/make_root_of_2.h>
// We must also include the following two, because of the overloadings
// for Quotient<MP_Float> and Quotient<Gmpz>, which triggers their
// instantiation, even if only to_double(double) is called, at least
@ -96,6 +98,7 @@ double to_double(Fixed_precision_nt);
bool is_finite(Fixed_precision_nt);
bool is_valid(Fixed_precision_nt);
std::pair<double,double> to_interval(Fixed_precision_nt);
#if 0
// Polynomial
@ -133,6 +136,7 @@ double to_double(const Nef_polynomial<ET> &);
template <typename ET>
Nef_polynomial<ET> gcd(const Nef_polynomial<ET> &, const Nef_polynomial<ET> &);
#endif
CGAL_END_NAMESPACE
#endif // CGAL_CFG_NO_TWO_STAGE_NAME_LOOKUP

View File

@ -1,6 +1,7 @@
#include <CGAL/basic.h>
#ifdef CGAL_USE_GMP
#include <CGAL/basic.h>
#include <CGAL/Gmpz.h>
#include <CGAL/Gmpq.h>

View File

@ -19,11 +19,6 @@
#include <CGAL/Lazy_exact_nt.h>
#include <CGAL/MP_Float.h>
#include <CGAL/Quotient.h>
//#include <CGAL/NT_extensions_Root_of/CGAL_Lazy_exact_nt.h>
//#include <CGAL/NT_extensions_Root_of/CGAL_Quotient.h>
//#include <CGAL/NT_extensions_Root_of/CGAL_Gmpz.h>
//#include <CGAL/NT_extensions_Root_of/CGAL_Gmpq.h>
//#include <CGAL/NT_extensions_Root_of/CGAL_Interval_nt.h>
#include <CGAL/Root_of_2.h>
#ifdef CGAL_USE_GMP
@ -427,10 +422,12 @@ 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);
typename Root::FT r(n);
typedef typename Root::FT FT;
typedef CGAL::Rational_traits<FT> Rat_traits;
FT r(n);
Root r1(r);
Root r2(n);
Root r3(r.denominator(),- r.numerator());
Root r3(Rat_traits().denominator(r),- Rat_traits().numerator(r));
assert(r1 == r1);
assert(r2 == r2);
assert(r3 == r3);
@ -476,8 +473,8 @@ int main(int argc, char **argv) {
std::cout << "Testing Root_of_2<mpq_class>" << std::endl;
result = result && test_root_of<Root_of_2<mpq_class> >();
std::cout << "Testing Root_of_2<Quotient<mpz_class> >" << std::endl;
result = result && test_root_of<Root_of_2<CGAL::Quotient<mpz_class> > >();
//std::cout << "Testing Root_of_2<Quotient<mpz_class> >" << std::endl;
//result = result && test_root_of<Root_of_2<CGAL::Quotient<mpz_class> > >();
std::cout << "Testing Root_of_2<mpz_class>" << std::endl;
result = result && test_root_of<Root_of_2<mpz_class> >();