mirror of https://github.com/CGAL/cgal
move unused header file to archive
This commit is contained in:
parent
6f122cfa1a
commit
01865a2765
|
|
@ -1,5 +1,3 @@
|
||||||
[See also the file TODO_static_filters]
|
|
||||||
|
|
||||||
Concerning the main code:
|
Concerning the main code:
|
||||||
-------------------------
|
-------------------------
|
||||||
- Policy for overlapping comparisons : another good (faster) solution
|
- Policy for overlapping comparisons : another good (faster) solution
|
||||||
|
|
@ -70,3 +68,143 @@ Concerning the test-suite:
|
||||||
The script could output information to test them generically somehow.
|
The script could output information to test them generically somehow.
|
||||||
- Test NaN propagation. Comparisons with these should throw the exception...
|
- Test NaN propagation. Comparisons with these should throw the exception...
|
||||||
Check that they are correctly propagated (by min(), max(), even operator*...)
|
Check that they are correctly propagated (by min(), max(), even operator*...)
|
||||||
|
|
||||||
|
Special TODO list for the static filters.
|
||||||
|
-----------------------------------------
|
||||||
|
It's a lot of work here for a "minor" optimization, so it's "low" priority,
|
||||||
|
except we could merge stuff with Olivier's Fixed !
|
||||||
|
|
||||||
|
- Known problems with the current approach:
|
||||||
|
- Match operator<(a,b) and co...
|
||||||
|
- What to do with branches (e.g. collinearC3() and power_test()):
|
||||||
|
- The epsilon computation type should return ZERO/EQUAL as default.
|
||||||
|
This way, collinearC3() works.
|
||||||
|
- The user can provide the epsilon variant inside the source code,
|
||||||
|
delimited by special symbols /*CGAL_FILTER_BODY ... */. That's the
|
||||||
|
solution for CGAL.
|
||||||
|
- Checks that the epsilons have been updated (which will not prove that
|
||||||
|
it's correct, but is better than nothing).
|
||||||
|
- Or use G++'s interface as a parser ? See gcc mail archives, 15 august 2000,
|
||||||
|
"XML output for GCC". An XML description for predicates ?
|
||||||
|
- /*DEGREE=2*/ attribute to the arguments ?
|
||||||
|
- # of bounds : one per predicate, or one per argument ? give choice.
|
||||||
|
- # of epsilons: one per predicate, or one set per sub-predicate ? choice.
|
||||||
|
- Check that the compiler optimizes the epsilon computation (use
|
||||||
|
__attribute__((const)) for Static_filter_error operators) ?
|
||||||
|
- As Fred pointed out: the scheme is not thread safe.
|
||||||
|
- Remove the assertions in the original code.
|
||||||
|
- In case there are loops, we must take the max() of the epsilons. This should
|
||||||
|
not happen often, imho... Wait and see.
|
||||||
|
- Move static_infos in src/.
|
||||||
|
- Replace: NEW_bound = max(NEW_bound, fabs(px.to_double())); by: if (NEW_bound
|
||||||
|
< fabs(px.to_double())) NEW_bound = fabs(px.to_double()); or even, using a
|
||||||
|
.bound() member function: if (NEW_bound < px.bound()) NEW_bound = px.bound();
|
||||||
|
Moreover, to_double() is not exact, we should use abs(to_interval(x)).sup() !
|
||||||
|
- Member function access for generic type should be (?): .dbl_approx()
|
||||||
|
.bound() (basically a bound on: fabs(.dbl_approx())) .error()
|
||||||
|
- Add a "number of bits" field in Static_filter_error ? (so that we get the
|
||||||
|
same thing as Fixed for 24 bits)
|
||||||
|
|
||||||
|
- Another approach to consider : Implement predicates taking one or several
|
||||||
|
epsilons as additional parameters, and have the functionality found in Open
|
||||||
|
CasCade, using sign(a, epsilon). Then with a special traits or something,
|
||||||
|
we can define sign(a,epsilon) = sign(a), and get the traditionnal template
|
||||||
|
predicates from that... So that the epsilons are removed at compile time ?
|
||||||
|
It would be nice to know exactly the desired functionality for epsilons...
|
||||||
|
|
||||||
|
- Where to put the context of the predicates ? different possibilities :
|
||||||
|
1- static data member of the predicate object (~as it is now)
|
||||||
|
2- data member of the predicate object
|
||||||
|
3- static data member of the kernel
|
||||||
|
4- data member of the kernel
|
||||||
|
5- global data
|
||||||
|
|
||||||
|
Things to take into account :
|
||||||
|
- I want to be able to initialize the bounds externally.
|
||||||
|
This can't be done if we choose 2-.
|
||||||
|
- I want to be able to have different contexts depending where I use the
|
||||||
|
predicate, this can't be done with 5- nor 3- nor 1-.
|
||||||
|
- If I add a failure_counter, it should be at the same place as the context,
|
||||||
|
and I should be able to access it from the outside. If we do that like
|
||||||
|
triangulation, treating geom_traits as a data member of triangulatino, then
|
||||||
|
it's ok.
|
||||||
|
- So it remains 2 possibilities :
|
||||||
|
a- data member of the predicate object.
|
||||||
|
b- data member of the kernel.
|
||||||
|
|
||||||
|
So 1-, 3-, 5- are out since we can't have different contexts.
|
||||||
|
2- and 4- are basically equivalent if we can access the context of an object
|
||||||
|
via the kernel object (_gt in triangulation). So, Orientation_2_object(),
|
||||||
|
for this particular kernel, would return a const ref to a data member of the
|
||||||
|
kernel...
|
||||||
|
So the good choice seems to be to have data stored in each predicate object,
|
||||||
|
and having the kernel store a predicate object for each predicate.
|
||||||
|
Then the orientation_2_object() simply returns a reference to it.
|
||||||
|
|
||||||
|
Then it means algorithms should use one "global" object per predicate (e.g.
|
||||||
|
one orientation object for a whole Triangulation). Except for cases where
|
||||||
|
they actually want different contexts.
|
||||||
|
|
||||||
|
// Additional kernel for storage type ?
|
||||||
|
template <class SK, class EK, class IK = Cartesian<Interval_nt> >
|
||||||
|
class Filtered_Point_2
|
||||||
|
{
|
||||||
|
const CK::Point_2 storage;
|
||||||
|
|
||||||
|
// IK cached ? It doesn't make sense to do it lazily because it's going to
|
||||||
|
// be used. BUT, what is worth is the case when the storage number type is
|
||||||
|
// like a double : in this case, no approximation needs to be stored.
|
||||||
|
|
||||||
|
IK::Point_2 app;
|
||||||
|
const IK::Point_2 & approx() { return app; }
|
||||||
|
|
||||||
|
#if No_cache_EK // via a traits parameter ? Have a generic caching mechanism ?
|
||||||
|
EK::Point_2 exact() { return EK::Point_2(storage); }
|
||||||
|
#else
|
||||||
|
EK::Point_2 ex;
|
||||||
|
const EK::Point_2 & exact { return ex; }
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
|
||||||
|
// For filtered constructions, we should be able to re-use the same predicates,
|
||||||
|
// but have different constructions and objects Point_2...
|
||||||
|
template <class EK, class IK = Cartesian<Interval> >
|
||||||
|
class Filtered_kernel
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
Filtered_kernel()
|
||||||
|
: ik(), ek(),
|
||||||
|
orientation_2_obj(ik.orientation_2_object(), ek.orientation_2_object())
|
||||||
|
// ...
|
||||||
|
{}
|
||||||
|
|
||||||
|
typedef CGAL::Filtered_Point_2<...> Point_2;
|
||||||
|
// ...
|
||||||
|
|
||||||
|
typedef CGAL::Filtered_p_Orientation<IK, EK> Orientation_2;
|
||||||
|
Orientation_2 orientation_2_obj;
|
||||||
|
const Orientation_2 & orientation_2_object() const
|
||||||
|
{ return orientation_2_obj; }
|
||||||
|
|
||||||
|
const IK & get_ik() const { return ik; }
|
||||||
|
const EK & get_ek() const { return ek; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
EK ek;
|
||||||
|
IK ik;
|
||||||
|
};
|
||||||
|
|
||||||
|
Then you use this thing as a kernel :
|
||||||
|
Filtered_kernel<Cartesian<leda_real> >
|
||||||
|
eventually adding profiling template parameters...
|
||||||
|
Just like we have at the NT level : Lazy_exact_nt<leda_real>.
|
||||||
|
|
||||||
|
Maybe have a unique (Cartesian) kernel that includes filtering and caching
|
||||||
|
capabilities which are toggleable by a simple traits ? The predicate objects
|
||||||
|
would include the (currently so-called) update_epsilon() member functions...
|
||||||
|
Or probably better, a filtering wrapper that can be used by homogeneous as
|
||||||
|
well...
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,138 +0,0 @@
|
||||||
Special TODO list for the static filters.
|
|
||||||
-----------------------------------------
|
|
||||||
It's a lot of work here for a "minor" optimization, so it's "low" priority,
|
|
||||||
except we could merge stuff with Olivier's Fixed !
|
|
||||||
|
|
||||||
- Known problems with the current approach:
|
|
||||||
- Match operator<(a,b) and co...
|
|
||||||
- What to do with branches (e.g. collinearC3() and power_test()):
|
|
||||||
- The epsilon computation type should return ZERO/EQUAL as default.
|
|
||||||
This way, collinearC3() works.
|
|
||||||
- The user can provide the epsilon variant inside the source code,
|
|
||||||
delimited by special symbols /*CGAL_FILTER_BODY ... */. That's the
|
|
||||||
solution for CGAL.
|
|
||||||
- Checks that the epsilons have been updated (which will not prove that
|
|
||||||
it's correct, but is better than nothing).
|
|
||||||
- Or use G++'s interface as a parser ? See gcc mail archives, 15 august 2000,
|
|
||||||
"XML output for GCC". An XML description for predicates ?
|
|
||||||
- /*DEGREE=2*/ attribute to the arguments ?
|
|
||||||
- # of bounds : one per predicate, or one per argument ? give choice.
|
|
||||||
- # of epsilons: one per predicate, or one set per sub-predicate ? choice.
|
|
||||||
- Check that the compiler optimizes the epsilon computation (use
|
|
||||||
__attribute__((const)) for Static_filter_error operators) ?
|
|
||||||
- As Fred pointed out: the scheme is not thread safe.
|
|
||||||
- Remove the assertions in the original code.
|
|
||||||
- In case there are loops, we must take the max() of the epsilons. This should
|
|
||||||
not happen often, imho... Wait and see.
|
|
||||||
- Move static_infos in src/.
|
|
||||||
- Replace: NEW_bound = max(NEW_bound, fabs(px.to_double())); by: if (NEW_bound
|
|
||||||
< fabs(px.to_double())) NEW_bound = fabs(px.to_double()); or even, using a
|
|
||||||
.bound() member function: if (NEW_bound < px.bound()) NEW_bound = px.bound();
|
|
||||||
Moreover, to_double() is not exact, we should use abs(to_interval(x)).sup() !
|
|
||||||
- Member function access for generic type should be (?): .dbl_approx()
|
|
||||||
.bound() (basically a bound on: fabs(.dbl_approx())) .error()
|
|
||||||
- Add a "number of bits" field in Static_filter_error ? (so that we get the
|
|
||||||
same thing as Fixed for 24 bits)
|
|
||||||
|
|
||||||
- Another approach to consider : Implement predicates taking one or several
|
|
||||||
epsilons as additional parameters, and have the functionality found in Open
|
|
||||||
CasCade, using sign(a, epsilon). Then with a special traits or something,
|
|
||||||
we can define sign(a,epsilon) = sign(a), and get the traditionnal template
|
|
||||||
predicates from that... So that the epsilons are removed at compile time ?
|
|
||||||
It would be nice to know exactly the desired functionality for epsilons...
|
|
||||||
|
|
||||||
- Where to put the context of the predicates ? different possibilities :
|
|
||||||
1- static data member of the predicate object (~as it is now)
|
|
||||||
2- data member of the predicate object
|
|
||||||
3- static data member of the kernel
|
|
||||||
4- data member of the kernel
|
|
||||||
5- global data
|
|
||||||
|
|
||||||
Things to take into account :
|
|
||||||
- I want to be able to initialize the bounds externally.
|
|
||||||
This can't be done if we choose 2-.
|
|
||||||
- I want to be able to have different contexts depending where I use the
|
|
||||||
predicate, this can't be done with 5- nor 3- nor 1-.
|
|
||||||
- If I add a failure_counter, it should be at the same place as the context,
|
|
||||||
and I should be able to access it from the outside. If we do that like
|
|
||||||
triangulation, treating geom_traits as a data member of triangulatino, then
|
|
||||||
it's ok.
|
|
||||||
- So it remains 2 possibilities :
|
|
||||||
a- data member of the predicate object.
|
|
||||||
b- data member of the kernel.
|
|
||||||
|
|
||||||
So 1-, 3-, 5- are out since we can't have different contexts.
|
|
||||||
2- and 4- are basically equivalent if we can access the context of an object
|
|
||||||
via the kernel object (_gt in triangulation). So, Orientation_2_object(),
|
|
||||||
for this particular kernel, would return a const ref to a data member of the
|
|
||||||
kernel...
|
|
||||||
So the good choice seems to be to have data stored in each predicate object,
|
|
||||||
and having the kernel store a predicate object for each predicate.
|
|
||||||
Then the orientation_2_object() simply returns a reference to it.
|
|
||||||
|
|
||||||
Then it means algorithms should use one "global" object per predicate (e.g.
|
|
||||||
one orientation object for a whole Triangulation). Except for cases where
|
|
||||||
they actually want different contexts.
|
|
||||||
|
|
||||||
// Additional kernel for storage type ?
|
|
||||||
template <class SK, class EK, class IK = Cartesian<Interval_nt> >
|
|
||||||
class Filtered_Point_2
|
|
||||||
{
|
|
||||||
const CK::Point_2 storage;
|
|
||||||
|
|
||||||
// IK cached ? It doesn't make sense to do it lazily because it's going to
|
|
||||||
// be used. BUT, what is worth is the case when the storage number type is
|
|
||||||
// like a double : in this case, no approximation needs to be stored.
|
|
||||||
|
|
||||||
IK::Point_2 app;
|
|
||||||
const IK::Point_2 & approx() { return app; }
|
|
||||||
|
|
||||||
#if No_cache_EK // via a traits parameter ? Have a generic caching mechanism ?
|
|
||||||
EK::Point_2 exact() { return EK::Point_2(storage); }
|
|
||||||
#else
|
|
||||||
EK::Point_2 ex;
|
|
||||||
const EK::Point_2 & exact { return ex; }
|
|
||||||
#endif
|
|
||||||
};
|
|
||||||
|
|
||||||
// For filtered constructions, we should be able to re-use the same predicates,
|
|
||||||
// but have different constructions and objects Point_2...
|
|
||||||
template <class EK, class IK = Cartesian<Interval> >
|
|
||||||
class Filtered_kernel
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
|
|
||||||
Filtered_kernel()
|
|
||||||
: ik(), ek(),
|
|
||||||
orientation_2_obj(ik.orientation_2_object(), ek.orientation_2_object())
|
|
||||||
// ...
|
|
||||||
{}
|
|
||||||
|
|
||||||
typedef CGAL::Filtered_Point_2<...> Point_2;
|
|
||||||
// ...
|
|
||||||
|
|
||||||
typedef CGAL::Filtered_p_Orientation<IK, EK> Orientation_2;
|
|
||||||
Orientation_2 orientation_2_obj;
|
|
||||||
const Orientation_2 & orientation_2_object() const
|
|
||||||
{ return orientation_2_obj; }
|
|
||||||
|
|
||||||
const IK & get_ik() const { return ik; }
|
|
||||||
const EK & get_ek() const { return ek; }
|
|
||||||
|
|
||||||
private:
|
|
||||||
|
|
||||||
EK ek;
|
|
||||||
IK ik;
|
|
||||||
};
|
|
||||||
|
|
||||||
Then you use this thing as a kernel :
|
|
||||||
Filtered_kernel<Cartesian<leda_real> >
|
|
||||||
eventually adding profiling template parameters...
|
|
||||||
Just like we have at the NT level : Lazy_exact_nt<leda_real>.
|
|
||||||
|
|
||||||
Maybe have a unique (Cartesian) kernel that includes filtering and caching
|
|
||||||
capabilities which are toggleable by a simple traits ? The predicate objects
|
|
||||||
would include the (currently so-called) update_epsilon() member functions...
|
|
||||||
Or probably better, a filtering wrapper that can be used by homogeneous as
|
|
||||||
well...
|
|
||||||
|
|
||||||
|
|
@ -1,2 +0,0 @@
|
||||||
TODO_static_filters
|
|
||||||
Restricted_double.h
|
|
||||||
Loading…
Reference in New Issue