couple more places for stateful kernels

This commit is contained in:
Marc Glisse 2011-05-23 15:58:00 +00:00
parent 32fecea31f
commit 5f0f7fb19d
4 changed files with 440 additions and 2 deletions

View File

@ -0,0 +1,420 @@
// Copyright (c) 2001-2005 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
#ifndef CGAL_FILTERED_PREDICATE_H
#define CGAL_FILTERED_PREDICATE_H
#include <string>
#include <CGAL/config.h>
#include <CGAL/Interval_nt.h>
#include <CGAL/Uncertain.h>
#include <CGAL/Profile_counter.h>
namespace CGAL {
// This template class is a wrapper that implements the filtering for any
// predicate (dynamic filters with IA).
// TODO :
// - each predicate in the default kernel should define a tag that says if it
// wants to be filtered or not (=> all homogeneous predicate define this
// tag). We could even test-suite that automatically. It makes a strong
// new requirement on the kernel though...
// Could be done with a traits mechanism ?
// A default template could use the current IA, but other tags or whatever
// could specify no filtering at all, or static filtering...
// - same thing for constructions => virtual operator() ?
// - similarly, constructions should have a tag saying if they can throw or
// not, or we let all this up to the compiler optimizer to figure out ?
// - Some caching could be done at the Point_2 level.
template <class EP, class AP, class C2E, class C2A, bool Protection = true>
class Filtered_predicate
{
//TODO: pack (at least use a tuple)
//FIXME: is it better to store those, or just store enough to recreate them
//(i.e. possibly references to the kernels)?
EP ep;
AP ap;
C2E c2e;
C2A c2a;
typedef typename AP::result_type Ares;
public:
typedef AP Approximate_predicate;
typedef EP Exact_predicate;
typedef C2E To_exact_converter;
typedef C2A To_approximate_converter;
typedef typename EP::result_type result_type;
// AP::result_type must be convertible to EP::result_type.
Filtered_predicate()
{}
template <class K>
Filtered_predicate(const K& k)
: ep(k.exact_kernel()), ap(k.approximate_kernel()), c2e(k,k.exact_kernel()), c2a(k,k.approximate_kernel())
{}
template <class K, class EK, class AK>
Filtered_predicate(const K& k,const EK& ek,const AK& ak)
: ep(ek), ap(ak), c2e(k,ek), c2a(k,ak)
{}
#ifndef CGAL_CFG_NO_CPP0X_VARIADIC_TEMPLATES
template <typename... Args>
result_type
operator()(const Args&... args) const;
#else
template <class A1>
result_type
operator()(const A1 &a1) const;
template <class A1, class A2>
result_type
operator()(const A1 &a1, const A2 &a2) const;
template <class A1, class A2, class A3>
result_type
operator()(const A1 &a1, const A2 &a2, const A3 &a3) const;
template <class A1, class A2, class A3, class A4>
result_type
operator()(const A1 &a1, const A2 &a2, const A3 &a3, const A4 &a4) const;
template <class A1, class A2, class A3, class A4, class A5>
result_type
operator()(const A1 &a1, const A2 &a2, const A3 &a3, const A4 &a4,
const A5 &a5) const;
template <class A1, class A2, class A3, class A4, class A5, class A6>
result_type
operator()(const A1 &a1, const A2 &a2, const A3 &a3, const A4 &a4,
const A5 &a5, const A6 &a6) const;
template <class A1, class A2, class A3, class A4, class A5, class A6,
class A7>
result_type
operator()(const A1 &a1, const A2 &a2, const A3 &a3, const A4 &a4,
const A5 &a5, const A6 &a6, const A7 &a7) const;
template <class A1, class A2, class A3, class A4, class A5, class A6,
class A7, class A8>
result_type
operator()(const A1 &a1, const A2 &a2, const A3 &a3, const A4 &a4,
const A5 &a5, const A6 &a6, const A7 &a7, const A8 &a8) const;
template <class A1, class A2, class A3, class A4, class A5, class A6,
class A7, class A8, class A9>
result_type
operator()(const A1 &a1, const A2 &a2, const A3 &a3, const A4 &a4,
const A5 &a5, const A6 &a6, const A7 &a7, const A8 &a8,
const A9 &a9) const;
template <class A1, class A2, class A3, class A4, class A5, class A6,
class A7, class A8, class A9, class A10>
result_type
operator()(const A1 &a1, const A2 &a2, const A3 &a3, const A4 &a4,
const A5 &a5, const A6 &a6, const A7 &a7, const A8 &a8,
const A9 &a9, const A10 &a10) const;
// Idem for more than 10 arguments. Do it on demand.
#endif
};
#ifndef CGAL_CFG_NO_CPP0X_VARIADIC_TEMPLATES
template <class EP, class AP, class C2E, class C2A, bool Protection>
template <typename... Args>
typename Filtered_predicate<EP,AP,C2E,C2A,Protection>::result_type
Filtered_predicate<EP,AP,C2E,C2A,Protection>::
operator()(const Args&... args) const
{
CGAL_BRANCH_PROFILER(std::string(" failures/calls to : ") + std::string(CGAL_PRETTY_FUNCTION), tmp);
// Protection is outside the try block as VC8 has the CGAL_CFG_FPU_ROUNDING_MODE_UNWINDING_VC_BUG
{
Protect_FPU_rounding<Protection> p;
try
{
Ares res = ap(c2a(args)...);
if (is_certain(res))
return get_certain(res);
}
catch (Uncertain_conversion_exception) {}
}
CGAL_BRANCH_PROFILER_BRANCH(tmp);
Protect_FPU_rounding<!Protection> p(CGAL_FE_TONEAREST);
return ep(c2e(args)...);
}
#else
template <class EP, class AP, class C2E, class C2A, bool Protection>
template <class A1>
typename Filtered_predicate<EP,AP,C2E,C2A,Protection>::result_type
Filtered_predicate<EP,AP,C2E,C2A,Protection>::
operator()(const A1 &a1) const
{
CGAL_BRANCH_PROFILER(std::string(" failures/calls to : ") + std::string(CGAL_PRETTY_FUNCTION), tmp);
{
Protect_FPU_rounding<Protection> p;
try
{
Ares res = ap(c2a(a1));
if (is_certain(res))
return get_certain(res);
}
catch (Uncertain_conversion_exception) {}
}
CGAL_BRANCH_PROFILER_BRANCH(tmp);
Protect_FPU_rounding<!Protection> p(CGAL_FE_TONEAREST);
return ep(c2e(a1));
}
template <class EP, class AP, class C2E, class C2A, bool Protection>
template <class A1, class A2>
typename Filtered_predicate<EP,AP,C2E,C2A,Protection>::result_type
Filtered_predicate<EP,AP,C2E,C2A,Protection>::
operator()(const A1 &a1, const A2 &a2) const
{
CGAL_BRANCH_PROFILER(std::string(" failures/calls to : ") + std::string(CGAL_PRETTY_FUNCTION), tmp);
{
Protect_FPU_rounding<Protection> p;
try
{
Ares res = ap(c2a(a1), c2a(a2));
if (is_certain(res))
return get_certain(res);
}
catch (Uncertain_conversion_exception) {}
}
CGAL_BRANCH_PROFILER_BRANCH(tmp);
Protect_FPU_rounding<!Protection> p(CGAL_FE_TONEAREST);
return ep(c2e(a1), c2e(a2));
}
template <class EP, class AP, class C2E, class C2A, bool Protection>
template <class A1, class A2, class A3>
typename Filtered_predicate<EP,AP,C2E,C2A,Protection>::result_type
Filtered_predicate<EP,AP,C2E,C2A,Protection>::
operator()(const A1 &a1, const A2 &a2, const A3 &a3) const
{
CGAL_BRANCH_PROFILER(std::string(" failures/calls to : ") + std::string(CGAL_PRETTY_FUNCTION), tmp);
{
Protect_FPU_rounding<Protection> p;
try
{
Ares res = ap(c2a(a1), c2a(a2), c2a(a3));
if (is_certain(res))
return get_certain(res);
}
catch (Uncertain_conversion_exception) {}
}
CGAL_BRANCH_PROFILER_BRANCH(tmp);
Protect_FPU_rounding<!Protection> p(CGAL_FE_TONEAREST);
return ep(c2e(a1), c2e(a2), c2e(a3));
}
template <class EP, class AP, class C2E, class C2A, bool Protection>
template <class A1, class A2, class A3, class A4>
typename Filtered_predicate<EP,AP,C2E,C2A,Protection>::result_type
Filtered_predicate<EP,AP,C2E,C2A,Protection>::
operator()(const A1 &a1, const A2 &a2, const A3 &a3, const A4 &a4) const
{
CGAL_BRANCH_PROFILER(std::string(" failures/calls to : ") + std::string(CGAL_PRETTY_FUNCTION), tmp);
{
Protect_FPU_rounding<Protection> p;
try
{
Ares res = ap(c2a(a1), c2a(a2), c2a(a3), c2a(a4));
if (is_certain(res))
return get_certain(res);
}
catch (Uncertain_conversion_exception) {}
}
CGAL_BRANCH_PROFILER_BRANCH(tmp);
Protect_FPU_rounding<!Protection> p(CGAL_FE_TONEAREST);
return ep(c2e(a1), c2e(a2), c2e(a3), c2e(a4));
}
template <class EP, class AP, class C2E, class C2A, bool Protection>
template <class A1, class A2, class A3, class A4, class A5>
typename Filtered_predicate<EP,AP,C2E,C2A,Protection>::result_type
Filtered_predicate<EP,AP,C2E,C2A,Protection>::
operator()(const A1 &a1, const A2 &a2, const A3 &a3, const A4 &a4,
const A5 &a5) const
{
CGAL_BRANCH_PROFILER(std::string(" failures/calls to : ") + std::string(CGAL_PRETTY_FUNCTION), tmp);
{
Protect_FPU_rounding<Protection> p;
try
{
Ares res = ap(c2a(a1), c2a(a2), c2a(a3), c2a(a4), c2a(a5));
if (is_certain(res))
return get_certain(res);
}
catch (Uncertain_conversion_exception) {}
}
CGAL_BRANCH_PROFILER_BRANCH(tmp);
Protect_FPU_rounding<!Protection> p(CGAL_FE_TONEAREST);
return ep(c2e(a1), c2e(a2), c2e(a3), c2e(a4), c2e(a5));
}
template <class EP, class AP, class C2E, class C2A, bool Protection>
template <class A1, class A2, class A3, class A4, class A5, class A6>
typename Filtered_predicate<EP,AP,C2E,C2A,Protection>::result_type
Filtered_predicate<EP,AP,C2E,C2A,Protection>::
operator()(const A1 &a1, const A2 &a2, const A3 &a3, const A4 &a4,
const A5 &a5, const A6 &a6) const
{
CGAL_BRANCH_PROFILER(std::string(" failures/calls to : ") + std::string(CGAL_PRETTY_FUNCTION), tmp);
{
Protect_FPU_rounding<Protection> p;
try
{
Ares res = ap(c2a(a1), c2a(a2), c2a(a3), c2a(a4), c2a(a5), c2a(a6));
if (is_certain(res))
return get_certain(res);
}
catch (Uncertain_conversion_exception) {}
}
CGAL_BRANCH_PROFILER_BRANCH(tmp);
Protect_FPU_rounding<!Protection> p(CGAL_FE_TONEAREST);
return ep(c2e(a1), c2e(a2), c2e(a3), c2e(a4), c2e(a5), c2e(a6));
}
template <class EP, class AP, class C2E, class C2A, bool Protection>
template <class A1, class A2, class A3, class A4, class A5, class A6,
class A7>
typename Filtered_predicate<EP,AP,C2E,C2A,Protection>::result_type
Filtered_predicate<EP,AP,C2E,C2A,Protection>::
operator()(const A1 &a1, const A2 &a2, const A3 &a3, const A4 &a4,
const A5 &a5, const A6 &a6, const A7 &a7) const
{
CGAL_BRANCH_PROFILER(std::string(" failures/calls to : ") + std::string(CGAL_PRETTY_FUNCTION), tmp);
{
Protect_FPU_rounding<Protection> p;
try
{
Ares res = ap(c2a(a1), c2a(a2), c2a(a3), c2a(a4), c2a(a5), c2a(a6),
c2a(a7));
if (is_certain(res))
return get_certain(res);
}
catch (Uncertain_conversion_exception) {}
}
CGAL_BRANCH_PROFILER_BRANCH(tmp);
Protect_FPU_rounding<!Protection> p(CGAL_FE_TONEAREST);
return ep(c2e(a1), c2e(a2), c2e(a3), c2e(a4), c2e(a5), c2e(a6), c2e(a7));
}
template <class EP, class AP, class C2E, class C2A, bool Protection>
template <class A1, class A2, class A3, class A4, class A5, class A6,
class A7, class A8>
typename Filtered_predicate<EP,AP,C2E,C2A,Protection>::result_type
Filtered_predicate<EP,AP,C2E,C2A,Protection>::
operator()(const A1 &a1, const A2 &a2, const A3 &a3, const A4 &a4,
const A5 &a5, const A6 &a6, const A7 &a7, const A8 &a8) const
{
CGAL_BRANCH_PROFILER(std::string(" failures/calls to : ") + std::string(CGAL_PRETTY_FUNCTION), tmp);
{
Protect_FPU_rounding<Protection> p;
try
{
Ares res = ap(c2a(a1), c2a(a2), c2a(a3), c2a(a4), c2a(a5), c2a(a6),
c2a(a7), c2a(a8));
if (is_certain(res))
return get_certain(res);
}
catch (Uncertain_conversion_exception) {}
}
CGAL_BRANCH_PROFILER_BRANCH(tmp);
Protect_FPU_rounding<!Protection> p(CGAL_FE_TONEAREST);
return ep(c2e(a1), c2e(a2), c2e(a3), c2e(a4), c2e(a5), c2e(a6), c2e(a7),
c2e(a8));
}
template <class EP, class AP, class C2E, class C2A, bool Protection>
template <class A1, class A2, class A3, class A4, class A5, class A6,
class A7, class A8, class A9>
typename Filtered_predicate<EP,AP,C2E,C2A,Protection>::result_type
Filtered_predicate<EP,AP,C2E,C2A,Protection>::
operator()(const A1 &a1, const A2 &a2, const A3 &a3, const A4 &a4,
const A5 &a5, const A6 &a6, const A7 &a7, const A8 &a8,
const A9 &a9) const
{
CGAL_BRANCH_PROFILER(std::string(" failures/calls to : ") + std::string(CGAL_PRETTY_FUNCTION), tmp);
{
Protect_FPU_rounding<Protection> p;
try
{
Ares res = ap(c2a(a1), c2a(a2), c2a(a3), c2a(a4), c2a(a5), c2a(a6),
c2a(a7), c2a(a8), c2a(a9));
if (is_certain(res))
return get_certain(res);
}
catch (Uncertain_conversion_exception) {}
}
CGAL_BRANCH_PROFILER_BRANCH(tmp);
Protect_FPU_rounding<!Protection> p(CGAL_FE_TONEAREST);
return ep(c2e(a1), c2e(a2), c2e(a3), c2e(a4), c2e(a5), c2e(a6), c2e(a7),
c2e(a8), c2e(a9));
}
template <class EP, class AP, class C2E, class C2A, bool Protection>
template <class A1, class A2, class A3, class A4, class A5, class A6,
class A7, class A8, class A9, class A10>
typename Filtered_predicate<EP,AP,C2E,C2A,Protection>::result_type
Filtered_predicate<EP,AP,C2E,C2A,Protection>::
operator()(const A1 &a1, const A2 &a2, const A3 &a3, const A4 &a4,
const A5 &a5, const A6 &a6, const A7 &a7, const A8 &a8,
const A9 &a9, const A10 &a10) const
{
CGAL_BRANCH_PROFILER(std::string(" failures/calls to : ") + std::string(CGAL_PRETTY_FUNCTION), tmp);
{
Protect_FPU_rounding<Protection> p;
try
{
Ares res = ap(c2a(a1), c2a(a2), c2a(a3), c2a(a4), c2a(a5), c2a(a6),
c2a(a7), c2a(a8), c2a(a9), c2a(a10));
if (is_certain(res))
return get_certain(res);
}
catch (Uncertain_conversion_exception) {}
}
CGAL_BRANCH_PROFILER_BRANCH(tmp);
Protect_FPU_rounding<!Protection> p(CGAL_FE_TONEAREST);
return ep(c2e(a1), c2e(a2), c2e(a3), c2e(a4), c2e(a5), c2e(a6), c2e(a7),
c2e(a8), c2e(a9), c2e(a10));
}
#endif
} //namespace CGAL
#endif // CGAL_FILTERED_PREDICATE_H

View File

@ -4,6 +4,7 @@
#include <CGAL/basic.h> #include <CGAL/basic.h>
#include <CGAL/Kernel_d/Cartesian_converter.h> #include <CGAL/Kernel_d/Cartesian_converter.h>
#include <CGAL/Filtered_predicate.h> #include <CGAL/Filtered_predicate.h>
#include <boost/mpl/if.hpp>
namespace CGAL { namespace CGAL {
@ -20,7 +21,12 @@ struct Cartesian_filter_K : public Base_,
typedef Base_ Kernel_base; typedef Base_ Kernel_base;
typedef AK_ AK; typedef AK_ AK;
typedef EK_ EK; typedef EK_ EK;
//TODO: C2A/C2E should be able to convert *this into this->kernel() or this->kernel2(). typedef typename Store_kernel<AK_>::reference_type AK_rt;
AK_rt approximate_kernel()const{return this->kernel();}
typedef typename Store_kernel2<EK_>::reference2_type EK_rt;
EK_rt exact_kernel()const{return this->kernel2();}
//TODO: C2A/C2E could be able to convert *this into this->kernel() or this->kernel2().
typedef CartesianD_converter<Kernel_base,AK> C2A; typedef CartesianD_converter<Kernel_base,AK> C2A;
typedef CartesianD_converter<Kernel_base,EK> C2E; typedef CartesianD_converter<Kernel_base,EK> C2E;

View File

@ -15,7 +15,12 @@ struct Lazy_cartesian : Dimension_base<typename EK_::Default_ambient_dimension>
//CGAL_CONSTEXPR Lazy_cartesian(){} //CGAL_CONSTEXPR Lazy_cartesian(){}
//CGAL_CONSTEXPR Lazy_cartesian(int d):Base_(d){} //CGAL_CONSTEXPR Lazy_cartesian(int d):Base_(d){}
//TODO: store an AK and an EK //TODO: Do we want to store an AK and an EK? Or just references?
//FIXME: references would be better I guess.
AK_ ak; EK_ ek;
AK_ const& approximate_kernel()const{return ak;}
EK_ const& exact_kernel()const{return ek;}
typedef Lazy_cartesian<EK_,AK_,E2A_/*,Kernel_*/> Self; typedef Lazy_cartesian<EK_,AK_,E2A_/*,Kernel_*/> Self;
//typedef typename Default::Get<Kernel_,Self>::type Kernel; //typedef typename Default::Get<Kernel_,Self>::type Kernel;
typedef Self Kernel; typedef Self Kernel;

View File

@ -852,6 +852,9 @@ struct Approx_converter
typedef K1 Source_kernel; typedef K1 Source_kernel;
typedef K2 Target_kernel; typedef K2 Target_kernel;
//typedef Converter Number_type_converter; //typedef Converter Number_type_converter;
Approx_converter(){}
Approx_converter(K1 const&,K2 const&){}
//TODO: check that it is normal that we never need k1 or k2 here
template<class,bool/*ET*/,bool/*iter*/> struct result_; template<class,bool/*ET*/,bool/*iter*/> struct result_;
template<class T,bool b> struct result_<T,true,b> { template<class T,bool b> struct result_<T,true,b> {
@ -899,6 +902,9 @@ struct Exact_converter
typedef K1 Source_kernel; typedef K1 Source_kernel;
typedef K2 Target_kernel; typedef K2 Target_kernel;
//typedef Converter Number_type_converter; //typedef Converter Number_type_converter;
Exact_converter(){}
Exact_converter(K1 const&,K2 const&){}
//TODO: check that it is normal that we never need k1 or k2 here
template<class,bool/*ET*/,bool/*iter*/> struct result_; template<class,bool/*ET*/,bool/*iter*/> struct result_;
template<class T,bool b> struct result_<T,true,b> { template<class T,bool b> struct result_<T,true,b> {
@ -1784,6 +1790,7 @@ struct Lazy_construction
AC ac; AC ac;
EC ec; EC ec;
//TODO: need a constructor to initialize ac and ec properly
public: public: