Revision e86ca2eec22056e3c1fbf77b56d66c09c01afe71 authored by Sébastien Loriot on 12 March 2018, 09:43:57 UTC, committed by Sébastien Loriot on 12 March 2018, 09:43:57 UTC
1 parent 8be7c2b
Raw File
TODO
Concerning the main code:
-------------------------
- Policy for overlapping comparisons : another good (faster) solution
  would be to set a static boolean variable to indicate a buggy comparison
  happenned (a la IEEE inexact flags).  Drawback is that it's not thread safe,
  but could be made safe with pthread_key_create()...
  Clearly, all this stuff is policy.
    struct overlap_throw {
      void operator() const { throw(ce_qui_faut); }
    };
  Or :
    class overlap_static {
      static bool pipo = false;
    public:
      void operator() const { pipo = true; }
      void reset() const { pipo = false; }
    };
- Use expression templates for Interval_nt<> and Lazy_exact_nt<>.
- Specializations for is_zero() and co, and make use of them in the kernel.
  [Filtered_exact<> doesn't define them either, it's a bug...]
- SunPro 5.x supports Interval arithmetic...
  http://docs.sun.com/htmlcoll/coll.693.1/iso-8859-1/CPPARITHPROG/iapg_bookTOC.html
  http://www.sun.com/forte/cplusplus/interval/index.html;$sessionid$GSXJDFYAABWVTAMTA1FU45Q
- Try to get rid of the libc5 compatible version (make benchmarks first).
- Have determinant_by_formula() overloading for Lazy_exact_nt<> ?
  And what about for Interval_nt<> too ?
- Turn CGAL_IA_CHECK_RESTRICT into an [expensive] assertion ?
- Handle in_smallest_orthogonalcircle_ftC2.h correctly (needs an include)
- Bench -fbranch-probabilities ?  Use __builtin_expect() for GCC 3 ?
- Mark the cache as "mutable" (see Stroustrup, page 232) ?
- Filter_Cache: Faire des benchs, et une test-suite qui soit raisonnable.
  Hum, rajouter un booléen pour calculer le cache seulement sur demande ?
  (ça évite de le faire inutilement pour les variables intermédiaires,
  mais ça prend un chouia plus de place... mais en comparaison du reste...)
- Replace CGAL_IA_MAX_DOUBLE by standard DBL_MAX in <cfloat>, if portable
  (add a test).  Not possible for CGAL_IA_MIN_DOUBLE, since DBL_MIN is the
  _normalized_ minimum.
- See the C++ Standard numeric_limits<>, section 18.2.
? See ISO C99 and http://http.cs.berkeley.edu/~fateman/fp98/korenF/node3.html.
- "C9x FP unordered compares":
  +  /* ISO C99 IEEE Unordered compares.  */
  +  builtin_function ("__builtin_isgreater", default_function_type,
  +                   BUILT_IN_ISGREATER, BUILT_IN_NORMAL, NULL_PTR);
  +  builtin_function ("__builtin_isgreaterequal", default_function_type,
  +                   BUILT_IN_ISGREATEREQUAL, BUILT_IN_NORMAL, NULL_PTR);
  +  builtin_function ("__builtin_isless", default_function_type,
  +                   BUILT_IN_ISLESS, BUILT_IN_NORMAL, NULL_PTR);
  +  builtin_function ("__builtin_islessequal", default_function_type,
  +                   BUILT_IN_ISLESSEQUAL, BUILT_IN_NORMAL, NULL_PTR);
  +  builtin_function ("__builtin_islessgreater", default_function_type,
  +                   BUILT_IN_ISLESSGREATER, BUILT_IN_NORMAL, NULL_PTR);
  +  builtin_function ("__builtin_isunordered", default_function_type,
  +                   BUILT_IN_ISUNORDERED, BUILT_IN_NORMAL, NULL_PTR);
  [voir le draft C99 ce que c'est]

Concerning the doc:
-------------------
- In the 2.0 HTML doc, my enums are indexed twice.
  probably a cc_manual compliance bug from me.
  Idem, my fct to_double(Ia) is not the same as the others...
- add a pointer to my MISC'99 paper.
- DOCUMENT the new boolean template parameter, the script, the static filters.

Concerning the test-suite:
--------------------------
- Check it with GCOV again before the next public release.
- Make a more extensive test-suite for the filtered predicates.
  The script could output information to test them generically somehow.
- Test NaN propagation.  Comparisons with these should throw the exception...
  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...


back to top