diff --git a/.gitattributes b/.gitattributes index 0fbca7aeb64..6a8aeb41d41 100644 --- a/.gitattributes +++ b/.gitattributes @@ -2634,3 +2634,4 @@ Visibility_complex/doc_tex/fig/points.gif -text svneol=unset#image/gif Visibility_complex/doc_tex/fig/vis-complex.eps -text svneol=unset#application/postscript Visibility_complex/doc_tex/fig/vis-complex.fig -text svneol=unset#application/octet-stream Visibility_complex/doc_tex/fig/vis-complex.gif -text svneol=unset#image/gif +iostream/test/iostream/data/io.cin -text diff --git a/Arrangement_2/bench/Arrangement_2/number_type.hpp b/Arrangement_2/bench/Arrangement_2/number_type.hpp index dc4a0df507e..4c43ddc7be0 100644 --- a/Arrangement_2/bench/Arrangement_2/number_type.hpp +++ b/Arrangement_2/bench/Arrangement_2/number_type.hpp @@ -59,13 +59,13 @@ #elif BENCH_NT == NIX_LEDA_FIELD_WITH_SQRT_NT #include -#if !LiS_HAVE_LEDA +#if ! defined(CGAL_USE_LEDA) #error "Leda not supported" #endif #elif BENCH_NT == NIX_CORE_FIELD_WITH_SQRT_NT #include -#if !LiS_HAVE_CORE +#if !defined(CGAL_USE_CORE) #error "Core not supported!" #endif diff --git a/Kernel_23/include/CGAL/kernel_assertions.h b/Kernel_23/include/CGAL/kernel_assertions.h index 4084d059783..56bddb4f305 100644 --- a/Kernel_23/include/CGAL/kernel_assertions.h +++ b/Kernel_23/include/CGAL/kernel_assertions.h @@ -19,9 +19,9 @@ // // $URL$ // $Id$ -// // -// Author(s) : script by Geert-Jan Giezeman and Sven Schoenherr +// +// Author(s) : script by Geert-Jan Giezeman and Sven Schoenherr @@ -30,6 +30,8 @@ // assertions // ---------- +#ifndef CGAL_KERNEL_ASSERTIONS_H +#define CGAL_KERNEL_ASSERTIONS_H #if defined(CGAL_KERNEL_NO_ASSERTIONS) || defined(CGAL_NO_ASSERTIONS) \ || defined(NDEBUG) @@ -284,4 +286,4 @@ # define CGAL_kernel_expensive_exactness_warnings 1 #endif // CGAL_KERNEL_NO_WARNINGS - +#endif diff --git a/Maintenance/release_building/include_in_release b/Maintenance/release_building/include_in_release index eb77a4912d0..cee0f287d14 100644 --- a/Maintenance/release_building/include_in_release +++ b/Maintenance/release_building/include_in_release @@ -68,6 +68,7 @@ Point_set_2 Polygon Polyhedron Polyhedron_IO +Polynomial NefPolynomial Polytope_distance_d Principal_component_analysis diff --git a/STL_Extension/include/CGAL/Cache.h b/STL_Extension/include/CGAL/Cache.h new file mode 100644 index 00000000000..f27221a1acf --- /dev/null +++ b/STL_Extension/include/CGAL/Cache.h @@ -0,0 +1,171 @@ +// ============================================================================ +// +// Copyright (c) 2001-2006 Max-Planck-Institut Saarbruecken (Germany). +// All rights reserved. +// +// This file is part of EXACUS (http://www.mpi-inf.mpg.de/projects/EXACUS/); +// you may redistribute it under the terms of the Q Public License version 1.0. +// See the file LICENSE.QPL distributed with EXACUS. +// +// 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. +// +// ---------------------------------------------------------------------------- +// +// Library : Support +// File : include/LiS/Cache.h +// SoX_release : $Name: $ +// Revision : $Revision$ +// Revision_date : $Date$ +// +// Author(s) : Michael Hemmer +// +// ============================================================================ + +#ifndef CGAL_CACHE_H +#define CGAL_CACHE_H 1 + +#include +#include +#include + +#include + +CGAL_BEGIN_NAMESPACE + +/*! \brief The Cache serves as a constructor for an object of type Output from + * a object of type Input. + * + * The Cache internally uses the class std::map. + * The Cache works as follows. First the \c input is canonicalized by the + * Canonicalizer and the result is used as the key of the cache. If the + * respective object is not in the cache yet, it is constructed by the Creator + * functor from the canonicalized \c input and added to the map.\n + * + * The Compare functor serves as the key comparison function, which must + * define a total ordering on the Input. \n + * + * The default for the Creator_ functor is Creator_1.\n + * The default for the Canonicalizer_ functor is Creator_1 \n + * The default for the Compare_ functor is std::less. \n + * + */ +template < class Input_, + class Output_, + class Creator_ = Creator_1, + class Canonicalizer_ = Creator_1, + class Compare_ = std::less > +class Cache{ +public: + //! The Input type of the Cache + typedef Input_ Input; + + //! The Output type of the Cache + typedef Output_ Output; + + /*! \brief The Creator functor of the Cache + * This functor is used to create the output from the input. + * If Output has a constructor from input you can use the default.*/ + typedef Creator_ Creator; + + /*! \brief The Canonicalizer functor of the Cache + * This functor is used to canonicalize the input in advance. \n + * If the Input already is canonicalized you can use the default.\n */ + typedef Canonicalizer_ Canonicalizer; + + /*! \brief The Compare functor used by the Cache */ + typedef Compare_ Compare; + + typedef Cache Self; +private: + typedef std::map Map; + Map map; +public: + typedef Map _Rep_type; + //! Iterator type + typedef typename _Rep_type::iterator Iterator; + //! Const_iterator type + typedef typename _Rep_type::const_iterator Const_iterator; + //! Reverse_iterator type + typedef typename _Rep_type::reverse_iterator Reverse_iterator; + //! Const_reverse_iterator type + typedef typename _Rep_type::const_reverse_iterator Const_reverse_iterator; + //! Size_type type + typedef typename _Rep_type::size_type Size_type; +public: + //! default constructor with empty table + Cache() : map() {}; + + /*! \brief Returns the respective object of type Output. + * + * If the object is not in the cache, it is constructed form \c key and + * added to the cache. + */ + Output operator () (const Input& input) { + Canonicalizer canonicalize; + Input key = canonicalize(input); + typename Map::iterator it = map.find(key); + if (it == map.end()) { + Creator create; + Output out = create(key); + map.insert(it,typename Map::value_type(key,out)); + return out; + } else { + return (*it).second; + } + } + + //! Clears the cache contents + void clear() { map.clear(); } + + //! Returns whether the cache is empty. + bool is_empty() const { return map.empty(); } + + //! Returns the current number of different objects in the cache + Size_type size() { return map.size(); } + + //! Returns the largest possible size of the cache. + Size_type max_size() const { return map.max_size(); } + + //! Returns an Iterator pointing to the beginning of the cache. + Iterator begin() { return map.begin(); } + + //! Returns an Iterator pointing to the end of the cache. + Iterator end() { return map.end(); } + + //! Returns a Const_iterator pointing to the beginning of the cache. + Const_iterator begin() const { return map.begin(); } + + //! Returns a Const_iterator pointing to the end of the cache. + Const_iterator end() const { return map.end(); } + + /*! \brief Returns a Reverse_iterator pointing to the beginning of the + * reversed cache. + */ + Reverse_iterator rbegin() { return map.rbegin(); } + + /*! \brief Returns a Reverse_iterator pointing to the end of the reversed + * cache. + */ + Reverse_iterator rend() { return map.rend(); } + + /*! \brief Returns a Const_reverse_iterator pointing to the beginning of + * the reversed cache. + */ + Const_reverse_iterator rbegin() const { return map.rbegin(); } + + /*! \brief Returns a Const_reverse_iterator pointing to the end of the + * reversed cache. + */ + Const_reverse_iterator rend() const { return map.rend(); } + +}; + +CGAL_END_NAMESPACE + +#endif +// EOF diff --git a/STL_Extension/include/CGAL/Flattening_iterator.h b/STL_Extension/include/CGAL/Flattening_iterator.h new file mode 100644 index 00000000000..b9102d40e7b --- /dev/null +++ b/STL_Extension/include/CGAL/Flattening_iterator.h @@ -0,0 +1,287 @@ +// ============================================================================ +// +// Copyright (c) 2001-2006 Max-Planck-Institut Saarbruecken (Germany). +// All rights reserved. +// +// This file is part of EXACUS (http://www.mpi-inf.mpg.de/projects/EXACUS/); +// you may redistribute it under the terms of the Q Public License version 1.0. +// See the file LICENSE.QPL distributed with EXACUS. +// +// 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. +// +// ---------------------------------------------------------------------------- +// +// Library : LiS +// File : include/LiS/Flattening_iterator.h +// LiS_release : $Name: $ +// Revision : $Revision$ +// Revision_date : $Date$ +// +// Author(s) : Arno Eigenwillig +// +// ============================================================================ + +/*! \file LiS/Flattening_iterator.h + * \brief declares classes \c LiS::Flattening_iterator and + * \c LiS::Flattening_const_iterator together with classes + * \c LiS::Recursive_flattening and \c LiS::Recursive_const_flattening + * for their nested application. + * See \link LiS_Flattening_iterator here\endlink. +*/ + +#ifndef CGAL_FLATTENING_ITERATOR_H +#define CGAL_FLATTENING_ITERATOR_H 1 + +#include +#include +#include + +#include +#include + +// LiS2CGAL check whether Nested_iterator in CGAL works in STL_extensions + +CGAL_BEGIN_NAMESPACE + +/*! \ingroup LiS_iterator + * \defgroup LiS_Flattening_iterator Flattening iterators + * Suppose you have an iterator range and suppose further that + * the values in that iterator range are containers and thus + * define iterator ranges themselves (accessible through + * some \c begin and \c end functions). + * \e Flattening the iterator range means to turn it into one + * iterator range whose values are the values of the containers + * in the original range. + * For example, a range of lists (1,2),(3),(4,5,6) can be + * flattened into a range 1,2,3,4,5,6 + * + * The class templates \c LiS::Flattening_iterator and + * \c LiS::Flattening_const_iterator implement this flattening. + * So far, only the \c const version has been implemented, + * i.e. the values in the flattened range are read-only. + * + * But what about an iterator range whose values are lists of + * vectors of vectors of ... and so on? + * Yes, it is possible to flatten such nested containers, too, + * by recursive application of \c LiS::Flattening*_iterator. + * The class templates \c LiS::Recursive_flattening and + * \c LiS::Recursive_const_flattening offer the necessary + * typedefs and conversions. + * So far, only the \c const version has been implemented. + */ + +template +class Recursive_const_flattening; + +template +class Recursive_const_flattening<0, InputIterator> { +public: + typedef Recursive_const_flattening Self; + static const int level = 0; + typedef InputIterator Input_iterator; + + typedef Input_iterator Recursive_flattening_iterator; + + struct Flatten { + typedef Recursive_flattening_iterator result_type; + typedef Input_iterator argument_type; + + Recursive_flattening_iterator + operator () (Input_iterator end, Input_iterator it) { + return it; + } + }; +}; + +template +class Recursive_const_flattening<1, InputIterator> { +public: + typedef Recursive_const_flattening Self; + static const int level = 1; + typedef InputIterator Input_iterator; + +private: + struct Nested_iterator_traits + { + typedef Input_iterator Base_iterator; + typedef typename std::iterator_traits::value_type::const_iterator + Iterator; + + Iterator begin(Input_iterator it) const { return it->begin(); } + Iterator end (Input_iterator it) const { return it->end(); } + }; + +public: + + typedef CGAL::Nested_iterator< Input_iterator, Nested_iterator_traits > + Recursive_flattening_iterator; + + struct Flatten { + typedef Recursive_flattening_iterator result_type; + typedef Input_iterator argument_type; + + Recursive_flattening_iterator + operator () (Input_iterator end, Input_iterator it) { + return Recursive_flattening_iterator(end,it); + } + }; +}; + +/*! \ingroup LiS_Flattening_iterator + \brief Recursive application of \c LiS::Flattening_const_iterator + + An instance \c LiS::Recursive_const_flattening + of this class template contains a typedef \c Recursive_flattening_iterator. + This is a \c level -fold nested instance of + \c LiS::Flattening_const_iterator, where \c level can be any + non-negative integer. At each nesting level, begin and end + functors are supplied to \c LiS::Flattening_const_iterator + which assume that their arguments have a + \c const_iterator typedef and \c begin() and \c end() + member functions in the style of the STL. + + The functor Flatten()(it) converts an \c InputIterator \c it + to a \c Recursive_flattening_iterator. Converting each endpoint + of an iterator range [first,beyond) yields an iterator range + in which \c level levels of packing into containers have been + unpacked. (In particular, the case \c level==0 is permissible + and a no-op.) + + To get a \c const_iterator out of a container \c c of type \c C + which is not \c const itself, one can use syntax like + const_cast(c).begin()). This may sometimes + be necessary in conjunction with \c LiS::Recursive_const_flattening. + */ +template< int level_, class InputIterator > +class Recursive_const_flattening { +public: + //! this instance itself + typedef Recursive_const_flattening Self; + //! this instance's first template argument + static const int level = level_; + //! this instance's second template argument + typedef InputIterator Input_iterator; + + typedef Recursive_const_flattening< + level-1, + typename std::iterator_traits::value_type::const_iterator + > Nested_self; + +private: + struct Nested_iterator_traits + { + typedef Input_iterator + Base_iterator; + typedef typename Nested_self::Recursive_flattening_iterator + Iterator; + + Iterator begin(Input_iterator it) const { return typename Nested_self::Flatten()(it->end(),it->begin()); } + Iterator end (Input_iterator it) const { return typename Nested_self::Flatten()(it->end(),it->end()); } + }; + +public: + typedef CGAL::Nested_iterator< Input_iterator, Nested_iterator_traits > + Recursive_flattening_iterator; + + //! conversion functor (model of STL concept \c AdaptableUnaryFunction ) + struct Flatten { + //! result type + typedef Recursive_flattening_iterator result_type; + //! argument type + typedef Input_iterator argument_type; + + //! conversion functor call + Recursive_flattening_iterator + operator () (Input_iterator end,Input_iterator it) { + return Recursive_flattening_iterator(end,it); + } + }; +}; + +#ifdef DOXYGEN_RUNNING +/*! \ingroup LiS_Flattening_iterator + \brief (unimplemented) + + This class template is unimplemented. + Only \c LiS::Recursive_const_flattening is available at this point. + */ +template +class Recursive_flattening { }; +#endif // DOXYGEN_RUNNING + +/* + * Part 2: Helper functions + */ + +/*! \relates LiS::Recursive_const_flattening + * \brief map \c it to + * LiS::Recursive_const_flattening::Flatten()(it) + * + * See \c LiS::Recursive_const_flattening for explanations. + * This function just exists to save typing via overloading resolution. + * You have to specify \c level explicitly in any case. + * For \c LiS::recursive_const_flattener<1,...>() , there is the + * shorthand \c LiS::const_flattener<...>() . + */ +template inline +typename Recursive_const_flattening + ::Recursive_flattening_iterator +recursive_const_flattener(InputIterator end,InputIterator it) { + return typename Recursive_const_flattening::Flatten()(end,it); +} + +/*! \relates LiS::Flattening_const_iterator + * \brief map \c it to + * LiS::Recursive_const_flattening<1, InputIterator>::Flatten()(it) + * + * A function call fi = const_flattener(it) converts the iterator + * \c it to an instance of \c LiS::Flattening_const_iterator (see ibid.). + * The template arguments are chosen as follows: + * - \c InputIterator1 is \c InputIterator + * - \c InputIterator2 is \c InputIterator::value_type::const_iterator + * - \c UnaryFunction1/2 are set to functors that call \c begin() + * and \c end() member functions. + * + * This function helps to save typing and to avoid manual specification + * of \c UnaryFunction1/2. + */ +template inline +typename Recursive_const_flattening<1, InputIterator> + ::Recursive_flattening_iterator +const_flattener(InputIterator end,InputIterator it) { + return typename Recursive_const_flattening<1, InputIterator>::Flatten()(end,it); +} + +#ifdef DOXYGEN_RUNNING +/*! \relates LiS::Recursive_flattener + \brief (unimplemented) + + This function template is unimplemented. + Only \c LiS::recursive_const_flattener is available at this point. + */ +template inline +typename Recursive_flattening + ::Recursive_flattening_iterator +recursive_flattener(InputIterator it); + +/*! \relates LiS::Flattening_iteratos + \brief (unimplemented) + + This function template is unimplemented. + Only \c LiS::const_flattener is available at this point. + */ +template inline +typename Recursive_flattening<1, InputIterator> + ::Recursive_flattening_iterator +flattener(InputIterator it); +#endif // DOXYGEN_RUNNING + + +CGAL_END_NAMESPACE + +#endif // LiS_FLATTENING_ITERATOR_H +// EOF diff --git a/STL_Extension/include/CGAL/Handle_with_policy.h b/STL_Extension/include/CGAL/Handle_with_policy.h new file mode 100644 index 00000000000..8a945c3011f --- /dev/null +++ b/STL_Extension/include/CGAL/Handle_with_policy.h @@ -0,0 +1,1427 @@ +// ============================================================================ +// +// Copyright (c) 2001-2006 Max-Planck-Institut Saarbruecken (Germany). +// All rights reserved. +// +// This file is part of EXACUS (http://www.mpi-inf.mpg.de/projects/EXACUS/); +// you may redistribute it under the terms of the Q Public License version 1.0. +// See the file LICENSE.QPL distributed with EXACUS. +// +// 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. +// +// ---------------------------------------------------------------------------- +// +// Library : LiS +// File : include/LiS/Handle.h +// LiS_release : $Name: $ +// Revision : $Revision$ +// Revision_date : $Date$ +// +// Author(s) : Michael Seel +// Arno Eigenwillig +// Lutz Kettner +// +// ============================================================================ + +/*! \file LiS/Handle.h + \brief Handles with policy parameter for reference counting and union-find + strategy. Uses \c LEDA_MEMORY if available. + + See for the full documentation: + + - \link LiS_handle Handle for Reference Counting \endlink +*/ + +#ifndef CGAL_HANDLE_WITH_POLICY_H +#define CGAL_HANDLE_WITH_POLICY_H + +#include +#include + +#include +#include +#include + +#include + +#ifdef CGAL_USE_LEDA +#include +#endif + +//#define LiS_HANDLE_OLD_ALLOCATION + +// LiS2CGAL: there are several: +// Handle Handle_for Handle_for_virtual Ref_counted +// boost has shared_ptr +// LiS2CGAL: add it as Handle_with_policy? +// LiS2CGAL: check whether CGAL::Handle is a subset and replacing it +// LiS2CGAL: Start: Copy and use it +// LiS2CGAL: Handle Package? + + +#ifdef LiS_HANDLE_OLD_ALLOCATION +#ifdef CGAL_USE_LEDA +#include +#endif // CGAL_USE_LEDA +#endif // LiS_HANDLE_OLD_ALLOCATION + +CGAL_BEGIN_NAMESPACE + +/*! \defgroup LiS_handle Handle for Reference Counting + \brief \#include for handles with policy + parameter for reference counting and union-find strategy. Uses + \c LEDA_MEMORY if available. The old memory allocation can be + selected by defining the \c LiS_HANDLE_OLD_ALLOCATION macro. + + There are two fundamentally different usages of this base class: + + - with a single representation class. In this case the handle + manages allocation and deallocation and the type \c T can + be an arbitrary type---the handle adds the necessary reference + counter internally. + + - with a hierarchy of representation classes. Type \c T will be + the common base class of this hierarchy and it has to be derived + itself from a specific base class, which can be accessed directly + or generically from the policy class. The allocator in the + handle will not be used in this scenario, since the handle class + does not allocate any representations. Instead, the handle class + derived from this handle base class is allocating the different + representations with the \c new operator. In this case, + the allocator in the base class of \c T is used. + + We give an example for each usage. See also the documentation + of \c Handle_with_policy. + +\b Example + +We use a single representation class to store an integer. The second +constructor makes use of one of the forwarding template constructors +that simply forward their parameter list to the representation +constructors. They exist for up to ten parameters. The third +constructor illustrates how the \c LiS::USE_WITH_INITIALIZE_WITH can be +used. It is useful if extensive computations are necessary before the +representation can be created. + +\code +struct Int_rep { + int val; + Int_rep( int i = 0) : val(i) {} + Int_rep( int i, int j) : val(i+j) {} + Int_rep( int i, int j, int k) : val(i+j+k) {} +}; + +template < class Unify> +struct Int_t : public Handle_with_policy< Int_rep, Unify > { + typedef Handle_with_policy< Int_rep, Unify > Base; + Int_t( int i = 0) : Base( i) {} + Int_t( int i, int j) : Base( i, j) {} // template constructors + Int_t( int i, int j, int k) : Base( Base::USE_WITH_INITIALIZE_WITH) { + initialize_with( i, j + k); + } + int value() const { return ptr()->val; } + void set_value( int i) { + copy_on_write(); + ptr()->val = i; + } + bool operator==( const Int_t& i) const { + bool equal = (value() == i.value()); + if ( equal) + unify(i); + return equal; + } +}; +\endcode + +\b Example + +We use a class hierarchy of two representation classes: one base class +for representing one integer, and a derived class to represent an +additional integer. To also added virtual get and set functions to +make this example similar to the one above. + +We use the generic solution to pick the base class for \c Int_vrep +from the policy class. So all representations are class templates with +a policy and an allocator as parameter and the handle class +instantiates them. If this flexibility is not needed, one could derive +directly from the appropriate base class, i.e., \c +::CGAL::Reference_counted_hierarchy or \c +::CGAL::Reference_counted_hierarchy_with_union. \c Alloc is an +allocator of \c char's here. + +\code +template +struct Int_vrep : public Policy::Hierarchy_base< Alloc>::Type { + int val; + virtual ::CGAL::Reference_counted_hierarchy* clone() { + return new Int_vrep( *this); + } + virtual int get_val() const { return val; } + virtual void set_val( int i) { val = i; } + Int_vrep( int i = 0) : val(i) {} +}; + +template +struct Int_vrep2 : public Int_vrep { + int val2; + virtual ::CGAL::Reference_counted_hierarchy* clone() { + return new Int_vrep2( *this); + } + virtual int get_val() const { return val + val2; } + virtual void set_val( int i) { val = i - val2; } + Int_vrep2( int i, int j) : Int_vrep(i), val2(j) {} +}; + +template < class Unify, class Alloc = CGAL_ALLOCATOR(char) > +struct Int_vt : public Handle_with_policy< Int_vrep, Unify > { + typedef Handle_with_policy< Int_vrep, Unify > Base; + Int_vt( int i = 0) : Base( new Int_vrep(i)) {} + Int_vt( int i, int j) : Base( new Int_vrep2(i,j)) {} + + int value() const { return ptr()->get_val(); } + void set_value( int i) { + copy_on_write(); + ptr()->set_val(i); + } + bool operator==( const Int_vt& i) const { + bool equal = (value() == i.value()); + if ( equal) + unify(i); + return equal; + } +}; +\endcode + +*/ +//@{ + +// Forward declarations of HandlePolicy classes +class Handle_policy_in_place; +class Handle_policy_no_union; +class Handle_policy_union; +class Handle_policy_union_and_reset; + +// Reference counted representation +// ================================ + +//! the base class for bodies of reference counted representations \c T. +template +class Reference_counted { +public: + typedef Reference_counted Self; + typedef T* Rep_pointer; +private: + mutable unsigned int count; // reference counter + T rep; +public: + Reference_counted() : count(1) {} + Reference_counted( const T& t) : count(1), rep(t) {} + Reference_counted( const Self& r) : count(1), rep(r.rep) {} + + void clear() { rep = T(); } + Rep_pointer base_ptr() { return &rep; } + void add_reference() { ++count; } + void remove_reference() { --count; } + bool is_shared() const { return count > 1; } + int union_size() const { return 1+count; } + void add_union_size(int) {} + +#ifdef LiS_HANDLE_OLD_ALLOCATION +#ifdef CGAL_USE_LEDA + LEDA_MEMORY( Self) +#endif // CGAL_USE_LEDA +#endif // LiS_HANDLE_OLD_ALLOCATION +}; + +/*!\brief + * Base class for bodies of reference counted representations \c T + * with a forwarding pointer for identical representations. + */ +template +class Reference_counted_with_forwarding { +public: + typedef Reference_counted_with_forwarding Self; + typedef T* Rep_pointer; + friend class Handle_policy_union; + friend class Handle_policy_union_and_reset; +private: + mutable unsigned int count; // reference counter + mutable Self* next; // forwarding pointer to valid rep or 0 + mutable int u_size; // union set size incl this rep and its handle + mutable T rep; +public: + Reference_counted_with_forwarding() + : count(1), next(0), u_size(2) {} + Reference_counted_with_forwarding( const T& t) + : count(1), next(0), u_size(2), rep(t) {} + Reference_counted_with_forwarding( const Self& r) + : count(1), next(0), u_size(2), rep(r.rep) {} + + void clear() { rep = T(); } + Rep_pointer base_ptr() { return &rep; } + void add_reference() { ++count; } + void remove_reference() { --count; } + bool is_shared() const { return count > 1; } + bool is_forwarding() const { return next != 0; } + int union_size() const { return u_size; } + void add_union_size(int a) { + CGAL_precondition( u_size + a > 0); + u_size += a; + } + +#ifdef LiS_HANDLE_OLD_ALLOCATION +#ifdef CGAL_USE_LEDA + LEDA_MEMORY( Self) +#endif // CGAL_USE_LEDA +#endif // LiS_HANDLE_OLD_ALLOCATION +}; + + +struct Reference_counted_hierarchy_base {}; + + +/*!\brief Base class for reference counted representations with a class + * hierarchy of different representations. Needs an allocator for \c char's + * as parameter. + */ +template +class Reference_counted_hierarchy : public Reference_counted_hierarchy_base { + // make sure it's always a char allocator + typedef typename Allocator_::template rebind< char> Char_alloc_rebind; + typedef typename Char_alloc_rebind::other Char_allocator; + + static Char_allocator alloc; + +public: + void* operator new(size_t bytes) { return alloc.allocate( bytes); } + void operator delete(void* p, size_t bytes) { + alloc.deallocate((char*)p, bytes); + } + +public: + typedef Allocator_ Allocator; + typedef Reference_counted_hierarchy Self; + typedef Self* Rep_pointer; +private: + mutable unsigned int count; // reference counter +public: + Reference_counted_hierarchy() : count(1) {} + Reference_counted_hierarchy( const Self&) : count(1) {} + + Rep_pointer base_ptr() { return this; } + void add_reference() { ++count; } + void remove_reference() { --count; } + bool is_shared() const { return count > 1; } + int union_size() const { return 1+count; } + void add_union_size(int) {} + + //! returns a copy of \c this. Can be implemented like + //! return new Derived_type( *this); + virtual Self* clone() = 0; + //! the virtual destructor is essential for proper memory management here. + virtual ~Reference_counted_hierarchy() {} + //! can be used to minimize memory consumption once it is known that this + //! representation is not used anymore and only needed to keep a fowarding + //! pointer. One example would be cleaning up dynamically allocated + //! data, or another example would be overwriting a \c leda::real with + //! a default constructed value to free its old expression tree. However, + //! this function can also be savely ignored and kept empty. + virtual void clear() {} +}; + +template +typename Reference_counted_hierarchy::Char_allocator + Reference_counted_hierarchy::alloc; + +/*!\brief Base class for reference counted representations with a class + * hierarchy of different representations. Needs an allocator for \c char's + * as parameter. + */ +template +class Reference_counted_hierarchy_with_union + : public Reference_counted_hierarchy +{ + friend class Handle_policy_union; + friend class Handle_policy_union_and_reset; +public: + typedef Allocator_ Allocator; + typedef Reference_counted_hierarchy_with_union Self; +private: + mutable Self* next; // forwarding pointer to valid rep or 0 + mutable int u_size; // union set size incl this rep and its handle +public: + Reference_counted_hierarchy_with_union() : + Reference_counted_hierarchy(), next(0), u_size(2) {} + bool is_forwarding() const { return next != 0; } + int union_size() const { return u_size; } + void add_union_size(int a) { + CGAL_precondition( u_size + a > 0); + u_size += a; + } +}; + + +// Handle for reference counted representation +// =========================================== + +namespace Intern { + // Some helper classes to select representation between single class + // representations and class hierarchy representations. + + // the representation type including a reference counter. + // The handle allocates objects of this type. This is the version + // for the single representation type. + template + struct Rep_bind_reference_counted { + typedef Reference_counted Rep; + }; + + // the representation type including a reference counter. + // The handle allocates objects of this type. This is the version + // for the class hierarchy of representation types. + template + struct Rep_bind_reference_counted { + typedef T Rep; + }; + + // the two versions for Reference_counted_with_forwarding + template + struct Rep_bind_reference_counted_with_forwarding { + typedef Reference_counted_with_forwarding Rep; + }; + + // the representation type including a reference counter. + // The handle allocates objects of this type. This is the version + // for the class hierarchy of representation types. + template + struct Rep_bind_reference_counted_with_forwarding { + Rep_bind_reference_counted_with_forwarding() { + // make sure we derived from the right type + typedef typename T::Allocator Alloc; + typedef ::CGAL::Reference_counted_hierarchy_with_union + Reference_counted_hierarchy_with_union; + BOOST_STATIC_ASSERT(( + ::boost::is_base_and_derived< Reference_counted_hierarchy_with_union, T >::value || + ::boost::is_same < Reference_counted_hierarchy_with_union, T >::value )); + } + typedef T Rep; + }; + +} + +/*! \brief Policy class for \c Handle_with_policy that stores the + representation directly without reference counting and without dynamic + memory allocation, is actually \e not a model of the \c HandlePolicy + concept, but can be used instead of one. It selects a different + specialized implementation of \c Handle_with_policy. It works only with + the single representation type, not with a class hierarchy of + representation types since they need the pointer in the handle + for the polymorphy. +*/ +struct Handle_policy_in_place {}; + +/*!\brief + * Policy class for \c Handle_with_policy that ignores unifying of + * identical representations \c T, is a model of the \c HandlePolicy concept. + */ +class Handle_policy_no_union { +public: + /*!\brief + * A rebind mechanism to create the representation type. + */ + template + struct Rep_bind { + //! the representation type including a reference counter. + //! The handle allocates objects of this type. + typedef typename + Intern::Rep_bind_reference_counted::Rep Rep; + }; + + /*!\brief + * A rebind mechanism to access the base class for class hierarchies + * of representations. + * + * The base classes can be used directly, but this + * rebind mechamism allows the implementation of handle-rep classes + * that are parameterized with the policy class only and adapt to + * the necessary base class. + */ + template + struct Hierarchy_base { + //! type that can be used as base class for the representation type. + typedef Reference_counted_hierarchy Type; + }; + + /*! \brief unifies the representations of the two handles \a h and \a g. + * The effect is void here. + * + * \pre The representations represent the same value and one could be + * replaced by the other. + */ + template + static void unify( const H& h, const H& g) { + (void)h; // avoid warnings for unused parameters + (void)g; // but keep the names in the definition for the doc. + } + + //! finds the currently valid representation for the handle \a h + //! and returns a pointer to its stored value of type \a T. + template + static typename H::Rep_pointer find( const H& h) { + return h.ptr_->base_ptr(); + } +}; + +/*!\brief + * Policy class for \c Handle_with_policy that implements unifying of + * identical representations \c T with trees and path compression, is a + * model of the \c HandlePolicy concept. + */ +class Handle_policy_union { +public: + /*!\brief + * A rebind mechanism to create the representation type. + */ + template + struct Rep_bind { + //! this default constructor contains some compile-time checks. + Rep_bind() { + Intern::Rep_bind_reference_counted_with_forwarding + check; + (void)check; + } + //! the representation type including a reference counter. + //! The handle allocates objects of this type. + typedef typename Intern::Rep_bind_reference_counted_with_forwarding::Rep Rep; + }; + + /*!\brief + * A rebind mechanism to access the base class for class hierarchies + * of representations. + * + * The base classes can be used directly, but this + * rebind mechamism allows the implementation of handle-rep classes + * that are parameterized with the policy class only and adapt to + * the necessary base class. + */ + template + struct Hierarchy_base { + //! type that can be used as base class for the representation type. + typedef Reference_counted_hierarchy_with_union Type; + }; + + /*! \brief unifies the representations of the two handles \a h and \a g. + Performs union. + \pre The representations represent the same value and one can be + replaced by the other. The handles \a h and \a g are already + the representatives found by the find operation and \a h is not + equal to \a g. The tree representing the union of \a h has size + not smaller than the corresponding tree size of \a g. + */ + template + static void unify_large_small( const H& h, const H& g) { + typename H::Rep* hrep = h.ptr_; + typename H::Rep* grep = g.ptr_; + CGAL_precondition( ! grep->is_forwarding()); + CGAL_precondition( hrep->union_size() >= grep->union_size()); + grep->add_union_size(-1); + // make g point to h's rep. + if ( grep->is_shared()) { + // grep survises the loss of one reference + // and hrep gets one more reference + grep->remove_reference(); + hrep->add_reference(); + hrep->add_union_size( grep->union_size()); + grep->next = hrep; + } else { +#ifdef LiS_HANDLE_OLD_ALLOCATION + delete grep; // did not survive loss of handle g +#else // LiS_HANDLE_OLD_ALLOCATION + g.delete_rep( grep); // did not survive loss of handle g +#endif // LiS_HANDLE_OLD_ALLOCATION + } + // redirect handle g and incr. hrep's counter + g.ptr_ = hrep; + hrep->add_reference(); + hrep->add_union_size(1); + } + + /*! \brief unifies the representations of the two handles \a h and \a g. + Performs union with path compression. + \pre The representations represent the same value and one can be + replaced by the other. + */ + template + static void unify( const H& h, const H& g) { + if ( find(h) != find(g)) { + if ( h.ptr_->union_size() > g.ptr_->union_size()) + unify_large_small( h, g); // make g point to h's rep. + else + unify_large_small( g, h); // make h point to g's rep. + } + } + + /*! \brief finds the currently valid representation for the handle \a h + and returns a pointer to its stored value of type \a T. Performs + path-compression to speed-up later union operations. + */ + template + static typename H::Rep_pointer find( const H& h) { + typedef typename H::Rep Rep; + if ( h.ptr_->is_forwarding()) { + // find new valid representation + Rep* new_rep = h.ptr_; + while ( new_rep->next != 0) + new_rep = static_cast(new_rep->next); + // path compression: assign new rep to all reps seen on the path + // update reference count properly: all reps on the path loose + // one reference, and the new_rep gains all of them unless + // the rep on the path get actually deleted. + Rep* rep = h.ptr_; + while ( rep != new_rep) { + Rep* tmp = static_cast(rep->next); + if ( rep->is_shared()) { + // rep survives the loss of one reference + // and new_rep gets one more reference + rep->remove_reference(); + if ( tmp != new_rep) { + // re-link rep to the new_rep + rep->next = new_rep; + new_rep->add_reference(); + } + } else { +#ifdef LiS_HANDLE_OLD_ALLOCATION + delete rep; // we have to delete the current rep +#else // LiS_HANDLE_OLD_ALLOCATION + h.delete_rep( rep); // we have to delete the current rep +#endif // LiS_HANDLE_OLD_ALLOCATION + } + rep = tmp; + } + // hook h to new_rep + h.ptr_ = new_rep; + new_rep->add_reference(); + } + return h.ptr_->base_ptr(); + } +}; + +/*!\brief Policy class for \c Handle_with_policy that implements unifying of + * identical representations \c T with trees and path compression. + * + * It also + * sets the unused representation immediately to the default constructed + * representation \c T(), which can help to free memory if the + * representation is dynamically allocated and potentially large, e.g., + * \c leda::real. This class is a model of the \c HandlePolicy concept. + */ +class Handle_policy_union_and_reset { +public: + /*!\brief + * A rebind mechanism to create the representation type. + */ + template + struct Rep_bind { + //! this default constructor contains some compile-time checks. + Rep_bind() { + Intern::Rep_bind_reference_counted_with_forwarding + check; + (void)check; + } + //! the representation type including a reference counter. + //! The handle allocates objects of this type. + typedef typename Intern::Rep_bind_reference_counted_with_forwarding::Rep Rep; + }; + + /*!\brief + * A rebind mechanism to access the base class for class hierarchies + * of representations. + * + * The base classes can be used directly, but this + * rebind mechamism allows the implementation of handle-rep classes + * that are parameterized with the policy class only and adapt to + * the necessary base class. + */ + template + struct Hierarchy_base { + //! type that can be used as base class for the representation type. + typedef Reference_counted_hierarchy_with_union Type; + }; + + // abbreviation to re-use its implementation below. + typedef Handle_policy_union U; + + /*! \brief unifies the representations of the two handles \a h and \a g. + Performs union with path compression and assigns a default + constructed value of the representation type \c Rep to the + superfluous representation. + \pre The representations represent the same value and one can be + replaced by the other. + */ + template + static void unify( const H& h, const H& g) { + if ( find(h) != find(g)) { + if ( h.ptr_->union_size() > g.ptr_->union_size()) { + // reset representation in g to default construction of T + if ( g.ptr_->is_shared()) + g.ptr_->clear(); + U::unify_large_small( h, g); // make g point to h's rep. + } else { + // reset representation in h to default construction of T + if ( h.ptr_->is_shared()) + h.ptr_->clear(); + U::unify_large_small( g, h); // make h point to g's rep. + } + } + } + + /*! \brief finds the currently valid representation for the handle \a h + and returns a pointer to its stored value of type \a T. Performs + path-compression to speed-up later union operations. + */ + template + static typename H::Rep_pointer find( const H& h) { return U::find(h); } +}; + + +/*! \brief the base class for handles of reference counted representations of + \c T. + + There are two fundamentally different usages of this base class: + + - with a single representation class. In this case the handle + manages allocation and deallocation and the type \c T can + be an arbitrary type---the handle adds the necessary reference + counter internally. + + - with a hierarchy of representation classes. Type \c T will be + the common base class of this hierarchy and it has to be derived + itself from either \c ::CGAL::Reference_counted_hierarchy or + \c ::CGAL::Reference_counted_hierarchy_with_union, both parameterized + with an allocator. The allocator in the handle will not be used in + this scenario, since the handle class does not allocate any + representations. Instead, the handle class derived from this handle + base class is allocating the different representations with the + \c new operator. In this case, the allocator in the base class + of \c T is used. + + The handle class distinguishes between these two alternative + usages by checking if \c T is derived from one of the two base + classes mentioned for the second alternative. If not, it picks the + first alternative. + + In the second alternative, the correct base class, \c + ::CGAL::Reference_counted_hierarchy_with_union, has to be used + if the policy class is one of \c class Handle_policy_union r \c + Handle_policy_union_and_reset. Otherwise, the other base class can + be used to save space. + + The policy class \c Handle_policy_in_place is incompatible with the class + hierarchy for representation classes since the pointer in the + handle class would be missing. + + The dependency of the base classes for \c T and the policy classes + is also encoded in the policy classes and can be used to write + generic handle-rep scheme classes. To do that one can derive \c T + from the expressions \c Policy::Hierarchy_base::Type + assuming that \c Policy is the handle policy and \c Alloc is the + allocator. Btw, the allocator is used as an allocator of character + arrays here. + + \see \link LiS_handle Handle for Reference Counting\endlink for + an example for each of the two alternative usages. + + The template parameters are: + - \b T: is one of the two following: + - an arbitrary type but it must be a model of the + \c DefaultConstructible concept if the default constructor + of the handle is used. + - a type derived from \c Reference_counted_hierarchy or + \c Reference_counted_hierarchy_with_union implementing + their virtual member function interface, namely a \c clone() + function. + + - \b HandlePolicy: a model of the \c HandlePolicy concept or the + \c Handle_policy_in_place class template that selects a specialized + implementation without reference counting. Has the + default \c Handle_policy_no_union. + + - \b Allocator_: a model of the \c Allocator concept, + has the default \c CGAL_ALLOCATOR(T). + + Uses \c LEDA_MEMORY if available. The old memory allocation can be + selected by defining the \c LiS_HANDLE_OLD_ALLOCATION macro. + Otherwise the allocator is used. +*/ +template +class Handle_with_policy { +public: + //! the handle type itself. + typedef Handle_with_policy< T, HandlePolicy, Allocator_> Self; + + //! the instantiated model of the \c HandlePolicy concept. + typedef HandlePolicy Handle_policy; + + //! the allocator type. + typedef Allocator_ Allocator; + + enum { is_class_hierarchy = + ::boost::is_base_and_derived< Reference_counted_hierarchy_base, T>::value || + ::boost::is_same < Reference_counted_hierarchy_base, T>::value }; + typedef typename Handle_policy::template Rep_bind< T, is_class_hierarchy > Bind; + // instantiate Rep_bind to activate compile time check in there + static Bind bind; + // Define type that is used for function matching + typedef typename ::boost::mpl::if_c< + is_class_hierarchy, + ::CGAL::Tag_true, + ::CGAL::Tag_false >::type + Class_hierarchy; + + //! the internal representation, i.e., \c T plus a reference count + //! (if needed), or just \c T if we derived from the base class to + //! support a class hierarchy for the representations. + typedef typename Bind::Rep Rep; + + typedef typename Rep::Rep_pointer Rep_pointer; + + typedef typename Allocator_::template rebind::other Rep_allocator; + + + //! integer type for identifying a representation. + typedef std::ptrdiff_t Id_type; + + friend class Handle_policy_no_union; + friend class Handle_policy_union; + friend class Handle_policy_union_and_reset; +private: + mutable Rep* ptr_; + + // We have to distinguish between allocating single representations + // and where we have a class hierarchy of representations, where the + // user is responsible for allocating the first representations + // and we can just \c clone and delete them. +#ifdef LiS_HANDLE_OLD_ALLOCATION + static Rep* new_rep( const Rep& rep) { + BOOST_STATIC_ASSERT( !( + ::boost::is_base_and_derived< Reference_counted_hierarchy_base, T >::value || + ::boost::is_same < Reference_counted_hierarchy_base, T >::value )); + + return new Rep(rep); + } + static void delete_rep( Rep* p) { delete p; } +#else // LiS_HANDLE_OLD_ALLOCATION + static Rep_allocator allocator; + + static Rep* new_rep( const Rep& rep) { + BOOST_STATIC_ASSERT( !( + ::boost::is_base_and_derived< Reference_counted_hierarchy_base, T >::value || + ::boost::is_same < Reference_counted_hierarchy_base, T >::value )); + Rep* p = allocator.allocate(1); + allocator.construct(p, rep); + return p; + } + static void delete_rep( Rep* p, ::CGAL::Tag_false ) { + allocator.destroy( p); + allocator.deallocate( p, 1); + } + static void delete_rep( Rep* p, ::CGAL::Tag_true ) { + delete p; + } + static void delete_rep( Rep* p) { delete_rep(p, Class_hierarchy()); } +#endif // LiS_HANDLE_OLD_ALLOCATION + + static Rep* clone_rep( Rep* p, ::CGAL::Tag_false ) { + return new_rep( *p); + } + static Rep* clone_rep( Rep* p, ::CGAL::Tag_true ) { + return static_cast(p->clone()); + } + static Rep* clone_rep( Rep* p) { return clone_rep( p, Class_hierarchy()); } + + void remove_reference() { + // cleans up the possible chain of forwarding reps + Handle_policy::find( *this); + if ( ! is_shared()) { + delete_rep( ptr_); + } else { + ptr_->remove_reference(); + ptr_->add_union_size( -1); + } + } + + template + Rep* make_from_single_arg( const TT& t, ::CGAL::Tag_false ) { + return new_rep( Rep( T(t))); + } + template + Rep* make_from_single_arg( TT t, ::CGAL::Tag_true ) { + Bind bind; // trigger compile-time check + (void)bind; + return t; // has to be a pointer convertible to Rep* + } + +protected: + //! protected access to the stored representation + T* ptr() { return static_cast(Handle_policy::find(*this));} + //! protected access to the stored representation + const T* ptr() const { + return static_cast(Handle_policy::find( *this)); + } + + //! unify two representations. \pre The two representations describe + //! the same value and one can be replaced by the other, i.e., the + //! values are immutable, or protected from changes with \c copy_on_write() + //! calls! + void unify( const Self& h) const { Handle_policy::unify( *this, h); } + + //! can be called before modifying a shared representation + //! to get an own copy of the representation which avoids effecting the + //! other sharing handles. Does nothing if representation is actually + //! not shared. + void copy_on_write() { + Handle_policy::find( *this); + if ( is_shared() ) { + Rep* tmp_ptr = clone_rep( ptr_); + ptr_->remove_reference(); + ptr_->add_union_size( -1); + ptr_ = tmp_ptr; + } + } + + //! used with special protected constructor + enum Use_with_initialize_with { + USE_WITH_INITIALIZE_WITH //!< used with special protected constructor + //!< of \c Handle_with_policy. + }; + + //! special constructor, postpones the construction of the representation + //! to one of the \c initialize_with() functions. An object is in an + //! invalid state (and will report a failed precondition later) if + //! it is not initialized with an \c initialize_with() function call + //! after this constructor. Applicable for single representation but + //! also for a class hierarchy of representations. + Handle_with_policy( Use_with_initialize_with) : ptr_( 0) {} + + //! constructor used for class hierarchies of representations, where + //! the handle class derived from this handle creates the different + //! representations itself with the \c new operator. Except for this + //! constructor, the the one with the \c Use_with_initialize_with + //! argument, and the single argument template constructor no other + //! constructor will work for class hierarchies of representations. + Handle_with_policy( Rep* p) : ptr_( p) { + BOOST_STATIC_ASSERT(( + ::boost::is_base_and_derived< Reference_counted_hierarchy_base, T >::value || + ::boost::is_same < Reference_counted_hierarchy_base, T >::value )); + Bind bind; // trigger compile-time check + (void)bind; + } + + //! initializes the representation after the constructor from + //! \c USE_WITH_INITIALIZE_WITH has been used. Applicable for a + //! class hierarchy of representations only, where the derived handle class + //! created the representation \c p with the \c new operator. No other + //! version of \c initialize_with is applicable in this case except + //! the template version with one argument. + void initialize_with( Rep* p) { + BOOST_STATIC_ASSERT(( + ::boost::is_base_and_derived< Reference_counted_hierarchy_base, T >::value || + ::boost::is_same < Reference_counted_hierarchy_base, T >::value )); + Bind bind; // trigger compile-time check + (void)bind; + CGAL_precondition_msg( ptr_ == 0, "Handle_with_policy::initialize_with(): the " + "representation has already been initialized."); + ptr_ = p; + } + + //! initializes the representation after the constructor from + //! \c USE_WITH_INITIALIZE_WITH has been used. + //! In case of the class hierarchy of representation classes, + //! this function is also chosen for pointers to newly allocated + //! representations that are types derived from \c T. In that case, + //! the pointer is just assigned to the internal pointer. + template + void initialize_with( const T1& t1) { + CGAL_precondition_msg( ptr_ == 0, "Handle_with_policy::initialize_with(): the " + "representation has already been initialized."); + ptr_ = make_from_single_arg( t1, Class_hierarchy()); + } + + //! initializes the representation after the constructor from + //! \c USE_WITH_INITIALIZE_WITH has been used. + template + void initialize_with( const T1& t1, const T2& t2) { + CGAL_precondition_msg( ptr_ == 0, "Handle_with_policy::initialize_with(): the " + "representation has already been initialized."); + ptr_ = new_rep( Rep( T(t1,t2))); + } + + //! initializes the representation after the constructor from + //! \c USE_WITH_INITIALIZE_WITH has been used. + template + void initialize_with( const T1& t1, const T2& t2, const T3& t3) { + CGAL_precondition_msg( ptr_ == 0, "Handle_with_policy::initialize_with(): the " + "representation has already been initialized."); + ptr_ = new_rep( Rep( T(t1,t2,t3))); + } + + //! initializes the representation after the constructor from + //! \c USE_WITH_INITIALIZE_WITH has been used. + template + void initialize_with( const T1& t1, const T2& t2, const T3& t3, + const T4& t4) { + CGAL_precondition_msg( ptr_ == 0, "Handle_with_policy::initialize_with(): the " + "representation has already been initialized."); + ptr_ = new_rep( Rep( T(t1,t2,t3,t4))); + } + + //! initializes the representation after the constructor from + //! \c USE_WITH_INITIALIZE_WITH has been used. + template + void initialize_with( const T1& t1, const T2& t2, const T3& t3, + const T4& t4, const T5& t5) { + CGAL_precondition_msg( ptr_ == 0, "Handle_with_policy::initialize_with(): the " + "representation has already been initialized."); + ptr_ = new_rep( Rep( T(t1,t2,t3,t4,t5))); + } + + //! initializes the representation after the constructor from + //! \c USE_WITH_INITIALIZE_WITH has been used. + template + void initialize_with( const T1& t1, const T2& t2, const T3& t3, + const T4& t4, const T5& t5, const T6& t6) { + CGAL_precondition_msg( ptr_ == 0, "Handle_with_policy::initialize_with(): the " + "representation has already been initialized."); + ptr_ = new_rep( Rep( T(t1,t2,t3,t4,t5,t6))); + } + + //! initializes the representation after the constructor from + //! \c USE_WITH_INITIALIZE_WITH has been used. + template + void initialize_with( const T1& t1, const T2& t2, const T3& t3, + const T4& t4, const T5& t5, const T6& t6, + const T7& t7) { + CGAL_precondition_msg( ptr_ == 0, "Handle_with_policy::initialize_with(): the " + "representation has already been initialized."); + ptr_ = new_rep( Rep( T(t1,t2,t3,t4,t5,t6,t7))); + } + + //! initializes the representation after the constructor from + //! \c USE_WITH_INITIALIZE_WITH has been used. + template + void initialize_with( const T1& t1, const T2& t2, const T3& t3, + const T4& t4, const T5& t5, const T6& t6, + const T7& t7, const T8& t8) { + CGAL_precondition_msg( ptr_ == 0, "Handle_with_policy::initialize_with(): the " + "representation has already been initialized."); + ptr_ = new_rep( Rep( T(t1,t2,t3,t4,t5,t6,t7,t8))); + } + + //! initializes the representation after the constructor from + //! \c USE_WITH_INITIALIZE_WITH has been used. + template + void initialize_with( const T1& t1, const T2& t2, const T3& t3, + const T4& t4, const T5& t5, const T6& t6, + const T7& t7, const T8& t8, const T9& t9) { + CGAL_precondition_msg( ptr_ == 0, "Handle_with_policy::initialize_with(): the " + "representation has already been initialized."); + ptr_ = new_rep( Rep( T(t1,t2,t3,t4,t5,t6,t7,t8,t9))); + } + +public: + //! default constructor. + Handle_with_policy() : ptr_( new_rep( Rep())) {} + + //! copy constructor, increments reference count. + Handle_with_policy(const Self& h) { + CGAL_precondition_msg( h.ptr_ != 0, "Handle_with_policy::Handle_with_policy( Self): probably " + "used special protected constructor and not the " + "'initialize_with()' function."); + Handle_policy::find( h); + ptr_ = h.ptr_; + ptr_->add_reference(); + ptr_->add_union_size( 1); + } + + //! forwarding constructor passing its parameter to the representation + //! constructor. In case of the class hierarchy of representation classes, + //! this constructor is also chosen for pointers to newly allocated + //! representations that are types derived from \c T. In that case, + //! the pointer is just assigned to the internal pointer. + template + explicit Handle_with_policy( const T1& t) + : ptr_( make_from_single_arg( t, Class_hierarchy())) {} + + //! forwarding constructor passing its parameters to the representation + //! constructor. + template + Handle_with_policy( const T1& t1, const T2& t2) : ptr_( new_rep( Rep( T( t1, t2)))) {} + + //! forwarding constructor passing its parameters to the representation + //! constructor. + template + Handle_with_policy( const T1& t1, const T2& t2, const T3& t3) + : ptr_( new_rep( Rep( T( t1, t2, t3)))) {} + + //! forwarding constructor passing its parameters to the representation + //! constructor. + template + Handle_with_policy( const T1& t1, const T2& t2, const T3& t3, const T4& t4) + : ptr_( new_rep( Rep( T( t1, t2, t3, t4)))) {} + + //! forwarding constructor passing its parameters to the representation + //! constructor. + template + Handle_with_policy( const T1& t1, const T2& t2, const T3& t3, const T4& t4, + const T5& t5) + : ptr_( new_rep( Rep( T( t1, t2, t3, t4, t5)))) {} + + //! forwarding constructor passing its parameters to the representation + //! constructor. + template + Handle_with_policy( const T1& t1, const T2& t2, const T3& t3, const T4& t4, + const T5& t5, const T6& t6) + : ptr_( new_rep( Rep( T( t1, t2, t3, t4, t5, t6)))) {} + + //! forwarding constructor passing its parameters to the representation + //! constructor. + template + Handle_with_policy( const T1& t1, const T2& t2, const T3& t3, const T4& t4, + const T5& t5, const T6& t6, const T7& t7) + : ptr_( new_rep( Rep( T( t1, t2, t3, t4, t5, t6, t7)))) {} + + //! forwarding constructor passing its parameters to the representation + //! constructor. + template + Handle_with_policy( const T1& t1, const T2& t2, const T3& t3, const T4& t4, + const T5& t5, const T6& t6, const T7& t7, const T8& t8) + : ptr_( new_rep( Rep( T( t1, t2, t3, t4, t5, t6, t7, t8)))) {} + + //! forwarding constructor passing its parameters to the representation + //! constructor. + template + Handle_with_policy( const T1& t1, const T2& t2, const T3& t3, const T4& t4, + const T5& t5, const T6& t6, const T7& t7, const T8& t8, + const T9& t9) + : ptr_( new_rep( Rep( T( t1, t2, t3, t4, t5, t6, t7, t8, t9)))) {} + + //! destructor, decrements reference count. + ~Handle_with_policy() { + Bind bind; // trigger compile-time check + (void)bind; + CGAL_precondition_msg( ptr_ != 0, "Handle_with_policy::~Handle_with_policy(): probably used " + "special protected constructor and not the " + "'initialize_with()' function."); + remove_reference(); + } + + //! assignment, updates reference count correspondingly. + Self& operator=( const Self& h) { + CGAL_precondition_msg( h.ptr_ != 0, "Handle_with_policy::operator=(): probably " + "used special protected constructor and not the " + "'initialize_with()' function."); + Handle_policy::find( h); + h.ptr_->add_reference(); + h.ptr_->add_union_size( 1); + remove_reference(); + ptr_ = h.ptr_; + return *this; + } + + //! returns \c true if both share the same representation. + bool is_identical( const Self& h) const { return ptr() == h.ptr(); } + + //! returns a unique id value. Two handles share their representation + //! is their id values are identical. + Id_type id() const { return reinterpret_cast(&*ptr()); } + + //! returns true if the representation is shared, i.e., the reference + //! counter is greater than one. + bool is_shared() const { return ptr_->is_shared(); } + + //! returns \c true if the representation is actually forwarding to + //! another equivalent representation (happens only with the + //! union-find policies). + bool is_forwarding() const { return ptr_->is_forwarding(); } + + //! returns the size of the union set including all reference counts that + //! have been accumulated so far for this representation. + int union_size() const { return ptr_->union_size(); } + + // backwards compatible + bool identical( const Self& h) const { return is_identical(h); } + +#ifdef HANDLE_WITH_POLICY_TEST + // provide access to pointer for testing only!! + const Rep* test_ptr() const { return ptr_; } + // provide access to pointer for testing only!! + bool test_identical_ptr( const Self& h) const { return ptr_ == h.ptr_; } +#endif // LiS_TEST_H + +#ifdef LiS_HANDLE_OLD_ALLOCATION +#ifdef CGAL_USE_LEDA + LEDA_MEMORY( Self) +#endif // CGAL_USE_LEDA +#endif // LiS_HANDLE_OLD_ALLOCATION +}; + +// instantiate Rep_bind to activate compile time check in there +template +typename Handle_with_policy::Bind Handle_with_policy::bind; + + +// LiS2CGAL: avaiblable also in CGFAL + +//! alternative syntax for \c h.id() to allow use with LEDA +/*! This is only provided for \c Handle_policy_no_union because + * ID numbers have to be fixed throughout an object's lifetime. + */ +template +unsigned long ID_Number(const Handle_with_policy& h) + { return h.id(); } + +#ifndef LiS_HANDLE_OLD_ALLOCATION +template +typename Handle_with_policy::Rep_allocator + Handle_with_policy::allocator; +#endif // LiS_HANDLE_OLD_ALLOCATION + + +/*! \brief specialization of the base class for handles for non-reference + counted representations. + Uses \c LEDA_MEMORY if available. +*/ +template +class Handle_with_policy { +public: + //! the handle type itself. + typedef Handle_with_policy< T, Handle_policy_in_place, Allocator_> Self; + + //! the model of the \c HandlePolicy concept. + typedef Handle_policy_in_place Handle_policy; + + //! the allocator type. + typedef Allocator_ Allocator; + + //! identify \c T with the internal representation \c Rep. + typedef T Rep; + + //! integer type for identifying a representation. + typedef std::ptrdiff_t Id_type; +private: + // store the rep in place + Rep rep; + +protected: + //! protected access to the stored representation + T* ptr() { return &rep; } + //! protected access to the stored representation + const T* ptr() const { return &rep; } + + //! unify two representations, a null op here. + void unify( const Self&) const {} + + //! can be called before modifying a shared representation + //! to get an own copy of the representation, a null op here. + void copy_on_write() {} + + //! used with special protected constructor + enum Use_with_initialize_with { + USE_WITH_INITIALIZE_WITH //!< used with special protected constructor + }; + + //! special constructor, postpones the construction of the representation + //! to one of the \c initialize_with() functions. Requires default + //! constructor for \c T. + Handle_with_policy( Use_with_initialize_with) {} + + //! initializes the representation after the constructor from + //! \c USE_WITH_INITIALIZE_WITH has been used. + template + void initialize_with( const T1& t1) { rep = Rep(t1); } + + //! initializes the representation after the constructor from + //! \c USE_WITH_INITIALIZE_WITH has been used. + template + void initialize_with( const T1& t1, const T2& t2) { rep = Rep(t1,t2); } + + //! initializes the representation after the constructor from + //! \c USE_WITH_INITIALIZE_WITH has been used. + template + void initialize_with( const T1& t1, const T2& t2, const T3& t3) { + rep = Rep(t1,t2,t3); + } + + //! initializes the representation after the constructor from + //! \c USE_WITH_INITIALIZE_WITH has been used. + template + void initialize_with( const T1& t1, const T2& t2, const T3& t3, + const T4& t4) { + rep = Rep(t1,t2,t3,t4); + } + + //! initializes the representation after the constructor from + //! \c USE_WITH_INITIALIZE_WITH has been used. + template + void initialize_with( const T1& t1, const T2& t2, const T3& t3, + const T4& t4, const T5& t5) { + rep = Rep(t1,t2,t3,t4,t5); + } + + //! initializes the representation after the constructor from + //! \c USE_WITH_INITIALIZE_WITH has been used. + template + void initialize_with( const T1& t1, const T2& t2, const T3& t3, + const T4& t4, const T5& t5, const T6& t6) { + rep = Rep(t1,t2,t3,t4,t5,t6); + } + + //! initializes the representation after the constructor from + //! \c USE_WITH_INITIALIZE_WITH has been used. + template + void initialize_with( const T1& t1, const T2& t2, const T3& t3, + const T4& t4, const T5& t5, const T6& t6, + const T7& t7) { + rep = Rep(t1,t2,t3,t4,t5,t6,t7); + } + + //! initializes the representation after the constructor from + //! \c USE_WITH_INITIALIZE_WITH has been used. + template + void initialize_with( const T1& t1, const T2& t2, const T3& t3, + const T4& t4, const T5& t5, const T6& t6, + const T7& t7, const T8& t8) { + rep = Rep(t1,t2,t3,t4,t5,t6,t7,t8); + } + + //! initializes the representation after the constructor from + //! \c USE_WITH_INITIALIZE_WITH has been used. + template + void initialize_with( const T1& t1, const T2& t2, const T3& t3, + const T4& t4, const T5& t5, const T6& t6, + const T7& t7, const T8& t8, const T9& t9) { + rep = Rep(t1,t2,t3,t4,t5,t6,t7,t8,t9); + } + +public: + //! default constructor. + Handle_with_policy() {} + + //! copy constructor. + Handle_with_policy(const Self& h) : rep( h.rep) {} + + //! forwarding constructor passing its parameter to the representation + //! constructor. + template + explicit Handle_with_policy( const T1& t) : rep( Rep(t)) {} + + //! forwarding constructor passing its parameters to the representation + //! constructor. + template + Handle_with_policy( const T1& t1, const T2& t2) : rep( Rep(t1,t2)) {} + + //! forwarding constructor passing its parameters to the representation + //! constructor. + template + Handle_with_policy( const T1& t1, const T2& t2, const T3& t3) : rep( Rep(t1,t2,t3)) {} + + //! forwarding constructor passing its parameters to the representation + //! constructor. + template + Handle_with_policy( const T1& t1, const T2& t2, const T3& t3, const T4& t4) + : rep( Rep( t1, t2, t3, t4)) {} + + //! forwarding constructor passing its parameters to the representation + //! constructor. + template + Handle_with_policy( const T1& t1, const T2& t2, const T3& t3, const T4& t4, + const T5& t5) + : rep( Rep( t1, t2, t3, t4, t5)) {} + + //! forwarding constructor passing its parameters to the representation + //! constructor. + template + Handle_with_policy( const T1& t1, const T2& t2, const T3& t3, const T4& t4, + const T5& t5, const T6& t6) + : rep( Rep( t1, t2, t3, t4, t5, t6)) {} + + //! forwarding constructor passing its parameters to the representation + //! constructor. + template + Handle_with_policy( const T1& t1, const T2& t2, const T3& t3, const T4& t4, + const T5& t5, const T6& t6, const T7& t7) + : rep( Rep( t1, t2, t3, t4, t5, t6, t7)) {} + + //! forwarding constructor passing its parameters to the representation + //! constructor. + template + Handle_with_policy( const T1& t1, const T2& t2, const T3& t3, const T4& t4, + const T5& t5, const T6& t6, const T7& t7, const T8& t8) + : rep( Rep( t1, t2, t3, t4, t5, t6, t7, t8)) {} + + //! forwarding constructor passing its parameters to the representation + //! constructor. + template + Handle_with_policy( const T1& t1, const T2& t2, const T3& t3, const T4& t4, + const T5& t5, const T6& t6, const T7& t7, const T8& t8, + const T9& t9) + : rep( Rep( t1, t2, t3, t4, t5, t6, t7, t8, t9)) {} + + //! returns \c true if both share the same representation. + bool is_identical( const Self& h) const { return this == &h; } + + //! returns a unique id value. Two handles share their representation + //! is their id values are identical. + Id_type id() const { return reinterpret_cast(this); } + + //! returns \c false since the representation is not shared for + //! this specialization. + bool is_shared() const { return false; } + + //! returns \c false since the representation is not forwarding for + //! this specialization. + bool is_forwarding() const { return false; } + + //! returns \c 1 as the union size for this specialization. + int union_size() const { return 1; } + + // backwards compatible + bool identical( const Self& h) const { return is_identical(h); } + +#ifdef HANDLE_WITH_POLICY_TEST + // provide access to pointer for testing only!! + const Rep* test_ptr() const { return *rep; } + // provide access to pointer for testing only!! + bool test_identical_ptr( const Self& h) const { return this == &h; } +#endif // HANDLE_WITH_POLICY_TEST + +#ifdef CGAL_USE_LEDA + LEDA_MEMORY( Self) +#endif +}; + +//@} + +CGAL_END_NAMESPACE + +#endif // CGAL_HANDLE_WITH_POLICY_H diff --git a/STL_Extension/include/CGAL/algorithm.h b/STL_Extension/include/CGAL/algorithm.h index 9e885c0ed59..4e6b6bc4836 100644 --- a/STL_Extension/include/CGAL/algorithm.h +++ b/STL_Extension/include/CGAL/algorithm.h @@ -17,7 +17,7 @@ // // $URL$ // $Id$ -// +// // // Author(s) : Michael Hoffmann // Lutz Kettner @@ -30,6 +30,8 @@ #include #include +#include + CGAL_BEGIN_NAMESPACE template @@ -63,6 +65,7 @@ min_max_element(ForwardIterator first, ForwardIterator last) } return result; } + template < class ForwardIterator, class CompareMin, class CompareMax > std::pair< ForwardIterator, ForwardIterator > min_max_element(ForwardIterator first, @@ -81,6 +84,7 @@ min_max_element(ForwardIterator first, } return result; } + template < class ForwardIterator, class Predicate > ForwardIterator min_element_if(ForwardIterator first, @@ -94,6 +98,7 @@ min_element_if(ForwardIterator first, result = first; return result; } + template < class ForwardIterator, class Compare, class Predicate > ForwardIterator min_element_if(ForwardIterator first, @@ -108,6 +113,7 @@ min_element_if(ForwardIterator first, result = first; return result; } + template < class ForwardIterator, class Predicate > ForwardIterator max_element_if(ForwardIterator first, @@ -121,6 +127,7 @@ max_element_if(ForwardIterator first, result = first; return result; } + template < class ForwardIterator, class Compare, class Predicate > ForwardIterator max_element_if(ForwardIterator first, @@ -137,6 +144,74 @@ max_element_if(ForwardIterator first, } + +/*! \brief lexicographic comparison of the two ranges using the \a cmp + function object. + + Compares the two ranges \c [first1,last1) and \c [first2,last2) + lexicographically and returns one of the \c CGAL::Comparison_result enum + values respectively: + - \c CGAL::SMALLER + - \c CGAL::EQUAL + - \c CGAL::LARGER + + \pre The \c value_type of \a InputIterator1 must be convertible + to the \c first_argument_type of \c BinaryFunction. + The \c value_type of \a InputIterator2 must be convertible + to the \c second_argument_type of \c BinaryFunction. + The \c result_type of \c BinaryFunction must be convertible to + \c CGAL::Comparison_result. + */ + +template +CGAL::Comparison_result +lexicographical_compare_three_valued( InputIterator1 first1, InputIterator1 last1, + InputIterator2 first2, InputIterator2 last2, + BinaryFunction cmp) { + while ( first1 != last1 && first2 != last2) { + CGAL::Comparison_result result = cmp( *first1, *first2); + if ( result != CGAL::EQUAL) + return result; + ++first1; + ++first2; + } + if ( first1 != last1) + return CGAL::LARGER; + if ( first2 != last2) + return CGAL::SMALLER; + return CGAL::EQUAL; +} + +/*! \brief output iterator range to a stream, with separators + + The iterator range \c [first,beyond) is written + to \c os (obeying EXACUS I/O modes). Each element is bracketed by + \c pre and \c post (default: empty string). Adjacent values are + spearated by \c sep (default: ", ", i.e. comma space). + The stream \c os is returned in its new state after output. + + Example: +
+    int a[] = {1, 2, 3};
+    output_range(std::cout, a, a+3, ":", "(", ")");
+
+ produces \c (1):(2):(3) + */ +template +std::ostream& output_range(std::ostream& os, + InputIterator first, InputIterator beyond, + const char* sep = ", ", const char* pre = "", const char* post = "" +) { + InputIterator it = first; + if (it != beyond) { + os << pre << oformat(*it) << post; + while (++it != beyond) os << sep << pre << oformat(*it) << post; + } + return os; +} + + + CGAL_END_NAMESPACE #endif // CGAL_ALGORITHM_H // diff --git a/STL_Extension/include/CGAL/assertions.h b/STL_Extension/include/CGAL/assertions.h index 62c9454b2e3..560d89c9cb3 100644 --- a/STL_Extension/include/CGAL/assertions.h +++ b/STL_Extension/include/CGAL/assertions.h @@ -17,7 +17,7 @@ // // $URL$ // $Id$ -// +// // // Author(s) : Geert-Jan Giezeman and Sven Schoenherr @@ -295,6 +295,8 @@ void warning_fail( const char*, const char*, int, const char*); # define CGAL_expensive_exactness_warning_code(CODE) CODE #endif // CGAL_KERNEL_NO_WARNINGS +// CGAL error +#define CGAL_error(MSG) ::CGAL::assertion_fail( "", __FILE__, __LINE__, MSG ) // failure handler declarations // ========================== diff --git a/STL_Extension/include/CGAL/tags.h b/STL_Extension/include/CGAL/tags.h index 400ca26d090..342671eb2dd 100644 --- a/STL_Extension/include/CGAL/tags.h +++ b/STL_Extension/include/CGAL/tags.h @@ -37,6 +37,9 @@ struct Tag_false {}; inline bool check_tag( Tag_true) {return true;} inline bool check_tag( Tag_false) {return false;} +struct Null_tag {}; +struct Null_functor {}; + // A function that asserts a specific compile time tag // forcing its two arguments to have equal type. diff --git a/STL_Extension/test/STL_Extension/test_Cache.C b/STL_Extension/test/STL_Extension/test_Cache.C new file mode 100644 index 00000000000..2c83733114a --- /dev/null +++ b/STL_Extension/test/STL_Extension/test_Cache.C @@ -0,0 +1,134 @@ +// ============================================================================ +// +// Copyright (c) 2001-2006 Max-Planck-Institut Saarbruecken (Germany). +// All rights reserved. +// +// This file is part of EXACUS (http://www.mpi-inf.mpg.de/projects/EXACUS/); +// you may redistribute it under the terms of the Q Public License version 1.0. +// See the file LICENSE.QPL distributed with EXACUS. +// +// 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. +// +// ---------------------------------------------------------------------------- +// +// Library : Support +// File : test/Cache.C +// SoX_release : $Name: $ +// Revision : $Revision$ +// Revision_date : $Date$ +// +// Author(s) : Michael Hemmer +// +// ============================================================================ + + +#include +#include +#include +#include +#include + +#include +#include + +struct Int_rep { + int val; + Int_rep( int i = 0) : val(i) {} + Int_rep( int i, int j) : val(i+j) {} + Int_rep( int i, int j, int k) : val(i+j+k) {} +}; + +template < class Unify> +struct Int_t : public CGAL::Handle_with_policy< Int_rep, Unify > { + typedef CGAL::Handle_with_policy< Int_rep, Unify > Base; + Int_t( int i = 0) : Base( i) {} + Int_t( int i, int j) : Base( i, j) {} // test template constructors + Int_t( int i, int j, int k) : Base( Base::USE_WITH_INITIALIZE_WITH) { + // test initialize_with + this->initialize_with( i, j + k); + } + int value() const { return this->ptr()->val; } + void set_value( int i) { + this->copy_on_write(); + this->ptr()->val = i; + } + bool operator==( const Int_t& i) const { + bool equal = (value() == i.value()); + if ( equal) + unify(i); + return equal; + } +}; + +void test_typedefs(){ + typedef CGAL::Cache Cache; + BOOST_STATIC_ASSERT(( ::boost::is_same< Cache::Input, int >::value )); + BOOST_STATIC_ASSERT(( ::boost::is_same< Cache::Output,double>::value )); + typedef CGAL::Creator_1 Creator_double; + BOOST_STATIC_ASSERT(( ::boost::is_same::value )); + typedef CGAL::Creator_1 Creator_int; + BOOST_STATIC_ASSERT(( ::boost::is_same::value )); + BOOST_STATIC_ASSERT(( ::boost::is_same >::value )); + BOOST_STATIC_ASSERT(( ::boost::is_same >::value )); +} +int main(){ + { + test_typedefs(); + { + typedef CGAL::Cache Cache; + double d; + Cache cache; + CGAL_test_assert(cache.is_empty()); + CGAL_test_assert(cache.size()==0); + d=cache(3); + CGAL_test_assert(d==double(3)); + CGAL_test_assert(cache.size()==1); + d=cache(4); + CGAL_test_assert(d==double(4)); + CGAL_test_assert(cache.size()==2); + d=cache(3); + CGAL_test_assert(d==double(3)); + CGAL_test_assert(cache.size()==2); + d=cache(2); + CGAL_test_assert(d==double(2)); + CGAL_test_assert(cache.size()==3); + + typedef Cache::Iterator Iterator; + typedef Cache::Const_iterator Const_iterator; + typedef Cache::Reverse_iterator Reverse_iterator; + typedef Cache::Const_reverse_iterator Const_reverse_iterator; + typedef Cache::Size_type Size_type; + + Iterator it; + d=0; + for(it=cache.begin();it!=cache.end();it++){ + CGAL_test_assert(d<(*it).second); + d=(*it).second; + } + cache.clear(); + CGAL_test_assert(cache.size()==0); + } + { + typedef Int_t< CGAL::Handle_policy_no_union > Int; + typedef CGAL::Cache Cache; + Int hi,hi2; + Cache cache; + CGAL_test_assert(cache.is_empty()); + CGAL_test_assert(cache.size()==0); + hi=cache(3); + CGAL_test_assert(hi==Int(3)); + CGAL_test_assert(cache.size()==1); + hi2=cache(4); + CGAL_test_assert(hi2==Int(4)); + CGAL_test_assert(cache.size()==2); + hi2=cache(3); + CGAL_test_assert(hi.id()==hi2.id()); + } + } + +return EXIT_SUCCESS; +} diff --git a/STL_Extension/test/STL_Extension/test_Flattening_iterator.C b/STL_Extension/test/STL_Extension/test_Flattening_iterator.C new file mode 100644 index 00000000000..7b51b92c021 --- /dev/null +++ b/STL_Extension/test/STL_Extension/test_Flattening_iterator.C @@ -0,0 +1,91 @@ +// ============================================================================ +// +// Copyright (c) 2001-2006 Max-Planck-Institut Saarbruecken (Germany). +// All rights reserved. +// +// This file is part of EXACUS (http://www.mpi-inf.mpg.de/projects/EXACUS/); +// you may redistribute it under the terms of the Q Public License version 1.0. +// See the file LICENSE.QPL distributed with EXACUS. +// +// 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. +// +// ---------------------------------------------------------------------------- +// +// Library : LiS +// File : test/Flattening_iterator.C +// LiS_release : $Name: $ +// Revision : $Revision$ +// Revision_date : $Date$ +// +// Author(s) : Arno Eigenwillig +// +// ============================================================================ + +#include +#include +#include +#include + +void test_const_flattening() { + typedef std::vector V1; + typedef std::vector V2; + typedef std::vector V3; + + V1 a1, a2, a3, a4, a5, a6; + + a1.push_back(1); a1.push_back(2); a1.push_back(3); a1.push_back(4); + a2.push_back(5); a2.push_back(6); a2.push_back(7); + a3.push_back(8); + a4.push_back(9); a4.push_back(10); a4.push_back(11); a4.push_back(12); + a5.push_back(13); a5.push_back(14); + a6.push_back(15); a6.push_back(16); a6.push_back(17); + + V2 b1, b2, b3; + + b1.push_back(a1); b1.push_back(a2); + b2.push_back(a3); + b3.push_back(a4); b3.push_back(a5); b3.push_back(a6); + + V3 c; + c.push_back(b1); c.push_back(b2); c.push_back(b3); + + int i; + + CGAL::Recursive_const_flattening<0, V1::const_iterator> + ::Recursive_flattening_iterator fi10, fi10_beyond; + fi10 = CGAL::recursive_const_flattener<0>( a1.end(),a1.begin() ); + fi10_beyond = CGAL::recursive_const_flattener<0>( a1.end(),a1.end() ); + for (i = 1; i <= 4; ++i, ++fi10) { + CGAL_test_assert(*fi10 == i); + } + CGAL_test_assert(fi10 == fi10_beyond); + + CGAL::Recursive_const_flattening<1, V2::const_iterator> + ::Recursive_flattening_iterator fi21, fi21_beyond; + fi21= CGAL::recursive_const_flattener<1>(const_cast(b1).end(), const_cast(b1).begin()); + fi21_beyond = CGAL::const_flattener(const_cast(b1).end(), const_cast(b1).end()); + for (i = 1; i <= 7; ++i, ++fi21) { + CGAL_test_assert(*fi21 == i); + } + CGAL_test_assert(fi21 == fi21_beyond); + + CGAL::Recursive_const_flattening<2, V3::iterator> + ::Recursive_flattening_iterator fi32, fi32_beyond; + fi32 = CGAL::recursive_const_flattener<2>(c.end(),c.begin()); + fi32_beyond = CGAL::recursive_const_flattener<2>(c.end(),c.end()); + for (i = 1; i <= 17; ++i, ++fi32) { + CGAL_test_assert(*fi32 == i); + } + CGAL_test_assert(fi32 == fi32_beyond); +} + +int main(int argc, char** argv) { + test_const_flattening(); + return 0; +} + +// EOF diff --git a/STL_Extension/test/STL_Extension/test_Handle_with_policy.C b/STL_Extension/test/STL_Extension/test_Handle_with_policy.C new file mode 100644 index 00000000000..a9542dec932 --- /dev/null +++ b/STL_Extension/test/STL_Extension/test_Handle_with_policy.C @@ -0,0 +1,501 @@ +// ============================================================================ +// +// Copyright (c) 2001-2006 Max-Planck-Institut Saarbruecken (Germany). +// All rights reserved. +// +// This file is part of EXACUS (http://www.mpi-inf.mpg.de/projects/EXACUS/); +// you may redistribute it under the terms of the Q Public License version 1.0. +// See the file LICENSE.QPL distributed with EXACUS. +// +// 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. +// +// ---------------------------------------------------------------------------- +// +// Library : LiS +// File : test/Handle.C +// LiS_release : $Name: $ +// Revision : $Revision$ +// Revision_date : $Date$ +// +// Author(s) : Michael Seel +// Arno Eigenwillig +// Lutz Kettner +// +// ============================================================================ + +#define HANDLE_WITH_POLICY_TEST + +#include +#include +#include + +#include +#include +#include + +struct Int_rep { + int val; + Int_rep( int i = 0) : val(i) {} + Int_rep( int i, int j) : val(i+j) {} + Int_rep( int i, int j, int k) : val(i+j+k) {} +}; + +template < class Unify> +struct Int_t : public ::CGAL::Handle_with_policy< Int_rep, Unify > { + typedef ::CGAL::Handle_with_policy< Int_rep, Unify > Base; + Int_t( int i = 0) : Base( i) {} + Int_t( int i, int j) : Base( i, j) {} // test template constructors + Int_t( int i, int j, int k) : Base( Base::USE_WITH_INITIALIZE_WITH) { + // test initialize_with + this->initialize_with( i, j + k); + } + int value() const { return this->ptr()->val; } + void set_value( int i) { + this->copy_on_write(); + this->ptr()->val = i; + } + bool operator==( const Int_t& i) const { + bool equal = (value() == i.value()); + if ( equal) + unify(i); + return equal; + } +}; + +void test_handle() { + { // test template constructor and initialize_with + typedef Int_t< ::CGAL::Handle_policy_no_union> Int; + Int i(5,6); + CGAL_test_assert( i == Int(11)); + Int j(5,6,7); + CGAL_test_assert( j == Int(18)); + } + { + typedef Int_t< ::CGAL::Handle_policy_in_place> Int; + Int i(5); + Int j(5); + Int k(6); + CGAL_test_assert( ! i.test_identical_ptr( j)); + CGAL_test_assert( ! i.test_identical_ptr( k)); + CGAL_test_assert( ! j.test_identical_ptr( k)); + CGAL_test_assert( i == j); + CGAL_test_assert( ! (i == k)); + CGAL_test_assert( ! i.test_identical_ptr( j)); + CGAL_test_assert( ! i.test_identical_ptr( k)); + CGAL_test_assert( ! j.test_identical_ptr( k)); + } + { + typedef Int_t< ::CGAL::Handle_policy_no_union> Int; + Int i(5); + Int j(5); + Int k(6); + CGAL_test_assert( ! i.test_identical_ptr( j)); + CGAL_test_assert( ! i.test_identical_ptr( k)); + CGAL_test_assert( ! j.test_identical_ptr( k)); + CGAL_test_assert( i == j); + CGAL_test_assert( ! (i == k)); + CGAL_test_assert( ! i.test_identical_ptr( j)); + CGAL_test_assert( ! i.test_identical_ptr( k)); + CGAL_test_assert( ! j.test_identical_ptr( k)); + CGAL_test_assert( (std::ptrdiff_t)(ID_Number(i)) == i.id() ); + } + { + typedef Int_t< ::CGAL::Handle_policy_union> Int; + Int i(5); + Int j(5); + Int k(6); + CGAL_test_assert( ! i.test_identical_ptr( j)); + CGAL_test_assert( ! i.test_identical_ptr( k)); + CGAL_test_assert( ! j.test_identical_ptr( k)); + CGAL_test_assert( i == j); + CGAL_test_assert( ! (i == k)); + CGAL_test_assert( i.test_identical_ptr( j)); + CGAL_test_assert( ! i.test_identical_ptr( k)); + CGAL_test_assert( ! j.test_identical_ptr( k)); + } + { + typedef Int_t< ::CGAL::Handle_policy_union_and_reset> Int; + Int i(5); + Int j(5); + Int k(6); + CGAL_test_assert( ! i.test_identical_ptr( j)); + CGAL_test_assert( ! i.test_identical_ptr( k)); + CGAL_test_assert( ! j.test_identical_ptr( k)); + CGAL_test_assert( i == j); + CGAL_test_assert( ! (i == k)); + CGAL_test_assert( i.test_identical_ptr( j)); + CGAL_test_assert( ! i.test_identical_ptr( k)); + CGAL_test_assert( ! j.test_identical_ptr( k)); + } + { + typedef Int_t< ::CGAL::Handle_policy_union> Int; + Int i(5); + Int j(5); + Int k(5); + Int l(5); + CGAL_test_assert( ! i.test_identical_ptr( j)); + CGAL_test_assert( ! i.test_identical_ptr( k)); + CGAL_test_assert( ! i.test_identical_ptr( l)); + CGAL_test_assert( ! j.test_identical_ptr( k)); + CGAL_test_assert( ! j.test_identical_ptr( l)); + CGAL_test_assert( ! k.test_identical_ptr( l)); + // pump up the union_size counter for j, k and l + Int j1(j); + CGAL_test_assert( j1.test_identical_ptr( j)); + Int k1(k); + Int k2(k); + Int k3(k); + Int l1(l); + Int l2(l); + Int l3(l); + Int l4(l); + Int l5(l); + Int l6(l); + Int l7(l); + Int l8(l); + CGAL_test_assert( ! i.is_forwarding()); + CGAL_test_assert( ! j.is_forwarding()); + CGAL_test_assert( ! k.is_forwarding()); + CGAL_test_assert( ! l.is_forwarding()); + CGAL_test_assert( i.union_size() == 2); + CGAL_test_assert( j.union_size() == 3); + CGAL_test_assert( k.union_size() == 5); + CGAL_test_assert( l.union_size() == 10); + CGAL_test_assert( ! i.test_identical_ptr( j)); + CGAL_test_assert( ! i.test_identical_ptr( k)); + CGAL_test_assert( ! i.test_identical_ptr( l)); + CGAL_test_assert( ! j.test_identical_ptr( k)); + CGAL_test_assert( ! j.test_identical_ptr( l)); + CGAL_test_assert( ! k.test_identical_ptr( l)); + // link i to j + CGAL_test_assert( i == j); + CGAL_test_assert( ! i.is_forwarding()); + CGAL_test_assert( ! j.is_forwarding()); + CGAL_test_assert( ! k.is_forwarding()); + CGAL_test_assert( ! l.is_forwarding()); + CGAL_test_assert( i.union_size() == 4); + CGAL_test_assert( j.union_size() == 4); + CGAL_test_assert( k.union_size() == 5); + CGAL_test_assert( l.union_size() == 10); + CGAL_test_assert( i.test_identical_ptr( j)); + CGAL_test_assert( i.test_identical_ptr( j1)); + CGAL_test_assert( ! i.test_identical_ptr( k)); + CGAL_test_assert( ! i.test_identical_ptr( l)); + CGAL_test_assert( ! j.test_identical_ptr( k)); + CGAL_test_assert( ! j.test_identical_ptr( l)); + CGAL_test_assert( ! k.test_identical_ptr( l)); + // link j to k + CGAL_test_assert( j == k); + CGAL_test_assert( i.is_forwarding()); + CGAL_test_assert( ! j.is_forwarding()); + CGAL_test_assert( ! k.is_forwarding()); + CGAL_test_assert( ! l.is_forwarding()); + CGAL_test_assert( i.union_size() == 3); + CGAL_test_assert( j.union_size() == 9); + CGAL_test_assert( k.union_size() == 9); + CGAL_test_assert( l.union_size() == 10); + CGAL_test_assert( ! i.test_identical_ptr( j)); + CGAL_test_assert( ! i.test_identical_ptr( k)); + CGAL_test_assert( ! i.test_identical_ptr( l)); + CGAL_test_assert( j.test_identical_ptr( k)); + CGAL_test_assert( ! j.test_identical_ptr( l)); + CGAL_test_assert( ! k.test_identical_ptr( l)); + // link k to l + CGAL_test_assert( k == l); + CGAL_test_assert( i.is_forwarding()); + CGAL_test_assert( j.is_forwarding()); + CGAL_test_assert( ! k.is_forwarding()); + CGAL_test_assert( ! l.is_forwarding()); + CGAL_test_assert( i.union_size() == 3); + CGAL_test_assert( j.union_size() == 8); + CGAL_test_assert( k.union_size() == 19); + CGAL_test_assert( l.union_size() == 19); + CGAL_test_assert( ! i.test_identical_ptr( j)); + CGAL_test_assert( ! i.test_identical_ptr( k)); + CGAL_test_assert( ! i.test_identical_ptr( l)); + CGAL_test_assert( ! j.test_identical_ptr( k)); + CGAL_test_assert( ! j.test_identical_ptr( l)); + CGAL_test_assert( k.test_identical_ptr( l)); + // find j, links it to k and l + CGAL_test_assert( j.value() == 5); + CGAL_test_assert( i.is_forwarding()); + CGAL_test_assert( ! j.is_forwarding()); + CGAL_test_assert( ! k.is_forwarding()); + CGAL_test_assert( ! l.is_forwarding()); + CGAL_test_assert( i.union_size() == 3); + CGAL_test_assert( j.union_size() == 19); + CGAL_test_assert( k.union_size() == 19); + CGAL_test_assert( l.union_size() == 19); + CGAL_test_assert( ! i.test_identical_ptr( j)); + CGAL_test_assert( ! i.test_identical_ptr( k)); + CGAL_test_assert( ! i.test_identical_ptr( l)); + CGAL_test_assert( j.test_identical_ptr( k)); + CGAL_test_assert( j.test_identical_ptr( l)); + CGAL_test_assert( k.test_identical_ptr( l)); + // find i, links it to j, k and l + CGAL_test_assert( i.value() == 5); + CGAL_test_assert( ! i.is_forwarding()); + CGAL_test_assert( ! j.is_forwarding()); + CGAL_test_assert( ! k.is_forwarding()); + CGAL_test_assert( ! l.is_forwarding()); + CGAL_test_assert( i.union_size() == 19); + CGAL_test_assert( j.union_size() == 19); + CGAL_test_assert( k.union_size() == 19); + CGAL_test_assert( l.union_size() == 19); + CGAL_test_assert( i.test_identical_ptr( j)); + CGAL_test_assert( i.test_identical_ptr( k)); + CGAL_test_assert( i.test_identical_ptr( l)); + CGAL_test_assert( j.test_identical_ptr( k)); + CGAL_test_assert( j.test_identical_ptr( l)); + CGAL_test_assert( k.test_identical_ptr( l)); + } +} + +// fully generic example to show, how allocator and policy can be transported +// from the templated handle to the templated rep. For hard-coded choices +// one could derive directly from one of the following base classes: +// -- struct Int_vrep : public ::CGAL::Reference_counted_hierarchy_with_union<> +// -- struct Int_vrep : public ::CGAL::Reference_counted_hierarchy<> + +template +struct Int_vrep : public Policy::template Hierarchy_base< Alloc>::Type { + int val; + virtual CGAL::Reference_counted_hierarchy* clone() { + return new Int_vrep( *this); + } + virtual int get_val() const { return val; } + virtual void set_val( int i) { val = i; } + Int_vrep( int i = 0) : val(i) {} +}; + +template +struct Int_vrep2 : public Int_vrep { + int val2; + virtual ::CGAL::Reference_counted_hierarchy* clone() { + return new Int_vrep2( *this); + } + virtual int get_val() const { return this->val + val2; } + virtual void set_val( int i) { this->val = i - val2; } + Int_vrep2( int i, int j) : Int_vrep(i), val2(j) {} +}; + +template +struct Int_vrep3 : public Int_vrep2 { + int val3; + virtual ::CGAL::Reference_counted_hierarchy* clone() { + return new Int_vrep3( *this); + } + virtual int get_val() const { return this->val + this->val2 + val3; } + virtual void set_val( int i) { this->val = i - this->val2 - val3; } + Int_vrep3( int i, int j, int k) : Int_vrep2(i,j), val3(k) {} +}; + +template < class Unify, class Alloc = CGAL_ALLOCATOR(char) > +struct Int_vt : public ::CGAL::Handle_with_policy< Int_vrep, Unify > { + typedef ::CGAL::Handle_with_policy< Int_vrep, Unify > Base; + Int_vt( int i = 0) : Base( new Int_vrep(i)) {} + Int_vt( int i, int j) : Base( new Int_vrep2(i,j)) {} + Int_vt( int i, int j, int k) : Base( new Int_vrep3(i,j,k)) {} + + int value() const { return this->ptr()->get_val(); } + void set_value( int i) { + this->copy_on_write(); + this->ptr()->set_val(i); + } + bool operator==( const Int_vt& i) const { + bool equal = (value() == i.value()); + if ( equal) + unify(i); + return equal; + } +}; + + + +void test_handle_with_class_hierarchy() { + { // test template constructor and initialize_with + typedef Int_vt< ::CGAL::Handle_policy_no_union> Int; + Int i(5,6); + CGAL_test_assert( i == Int(11)); + Int j(5,6,7); + CGAL_test_assert( j == Int(18)); + } + { + //typedef Int_vt< ::CGAL::Handle_policy_in_place> Int; // That's supposed to fail + } + { + typedef Int_vt< ::CGAL::Handle_policy_no_union> Int; + Int i(5); + Int j(5); + Int k(6); + CGAL_test_assert( ! i.test_identical_ptr( j)); + CGAL_test_assert( ! i.test_identical_ptr( k)); + CGAL_test_assert( ! j.test_identical_ptr( k)); + CGAL_test_assert( i == j); + CGAL_test_assert( ! (i == k)); + CGAL_test_assert( ! i.test_identical_ptr( j)); + CGAL_test_assert( ! i.test_identical_ptr( k)); + CGAL_test_assert( ! j.test_identical_ptr( k)); + CGAL_test_assert( (std::ptrdiff_t)(ID_Number(i)) == i.id() ); + } + { + typedef Int_vt< ::CGAL::Handle_policy_union> Int; + Int i(5); + Int j(5); + Int k(6); + CGAL_test_assert( ! i.test_identical_ptr( j)); + CGAL_test_assert( ! i.test_identical_ptr( k)); + CGAL_test_assert( ! j.test_identical_ptr( k)); + CGAL_test_assert( i == j); + CGAL_test_assert( ! (i == k)); + CGAL_test_assert( i.test_identical_ptr( j)); + CGAL_test_assert( ! i.test_identical_ptr( k)); + CGAL_test_assert( ! j.test_identical_ptr( k)); + } + { + typedef Int_vt< ::CGAL::Handle_policy_union_and_reset> Int; + Int i(5); + Int j(5); + Int k(6); + CGAL_test_assert( ! i.test_identical_ptr( j)); + CGAL_test_assert( ! i.test_identical_ptr( k)); + CGAL_test_assert( ! j.test_identical_ptr( k)); + CGAL_test_assert( i == j); + CGAL_test_assert( ! (i == k)); + CGAL_test_assert( i.test_identical_ptr( j)); + CGAL_test_assert( ! i.test_identical_ptr( k)); + CGAL_test_assert( ! j.test_identical_ptr( k)); + } + { + typedef Int_vt< ::CGAL::Handle_policy_union> Int; + Int i(5); + Int j(5); + Int k(5); + Int l(5); + CGAL_test_assert( ! i.test_identical_ptr( j)); + CGAL_test_assert( ! i.test_identical_ptr( k)); + CGAL_test_assert( ! i.test_identical_ptr( l)); + CGAL_test_assert( ! j.test_identical_ptr( k)); + CGAL_test_assert( ! j.test_identical_ptr( l)); + CGAL_test_assert( ! k.test_identical_ptr( l)); + // pump up the union_size counter for j, k and l + Int j1(j); + CGAL_test_assert( j1.test_identical_ptr( j)); + Int k1(k); + Int k2(k); + Int k3(k); + Int l1(l); + Int l2(l); + Int l3(l); + Int l4(l); + Int l5(l); + Int l6(l); + Int l7(l); + Int l8(l); + CGAL_test_assert( ! i.is_forwarding()); + CGAL_test_assert( ! j.is_forwarding()); + CGAL_test_assert( ! k.is_forwarding()); + CGAL_test_assert( ! l.is_forwarding()); + CGAL_test_assert( i.union_size() == 2); + CGAL_test_assert( j.union_size() == 3); + CGAL_test_assert( k.union_size() == 5); + CGAL_test_assert( l.union_size() == 10); + CGAL_test_assert( ! i.test_identical_ptr( j)); + CGAL_test_assert( ! i.test_identical_ptr( k)); + CGAL_test_assert( ! i.test_identical_ptr( l)); + CGAL_test_assert( ! j.test_identical_ptr( k)); + CGAL_test_assert( ! j.test_identical_ptr( l)); + CGAL_test_assert( ! k.test_identical_ptr( l)); + // link i to j + CGAL_test_assert( i == j); + CGAL_test_assert( ! i.is_forwarding()); + CGAL_test_assert( ! j.is_forwarding()); + CGAL_test_assert( ! k.is_forwarding()); + CGAL_test_assert( ! l.is_forwarding()); + CGAL_test_assert( i.union_size() == 4); + CGAL_test_assert( j.union_size() == 4); + CGAL_test_assert( k.union_size() == 5); + CGAL_test_assert( l.union_size() == 10); + CGAL_test_assert( i.test_identical_ptr( j)); + CGAL_test_assert( i.test_identical_ptr( j1)); + CGAL_test_assert( ! i.test_identical_ptr( k)); + CGAL_test_assert( ! i.test_identical_ptr( l)); + CGAL_test_assert( ! j.test_identical_ptr( k)); + CGAL_test_assert( ! j.test_identical_ptr( l)); + CGAL_test_assert( ! k.test_identical_ptr( l)); + // link j to k + CGAL_test_assert( j == k); + CGAL_test_assert( i.is_forwarding()); + CGAL_test_assert( ! j.is_forwarding()); + CGAL_test_assert( ! k.is_forwarding()); + CGAL_test_assert( ! l.is_forwarding()); + CGAL_test_assert( i.union_size() == 3); + CGAL_test_assert( j.union_size() == 9); + CGAL_test_assert( k.union_size() == 9); + CGAL_test_assert( l.union_size() == 10); + CGAL_test_assert( ! i.test_identical_ptr( j)); + CGAL_test_assert( ! i.test_identical_ptr( k)); + CGAL_test_assert( ! i.test_identical_ptr( l)); + CGAL_test_assert( j.test_identical_ptr( k)); + CGAL_test_assert( ! j.test_identical_ptr( l)); + CGAL_test_assert( ! k.test_identical_ptr( l)); + // link k to l + CGAL_test_assert( k == l); + CGAL_test_assert( i.is_forwarding()); + CGAL_test_assert( j.is_forwarding()); + CGAL_test_assert( ! k.is_forwarding()); + CGAL_test_assert( ! l.is_forwarding()); + CGAL_test_assert( i.union_size() == 3); + CGAL_test_assert( j.union_size() == 8); + CGAL_test_assert( k.union_size() == 19); + CGAL_test_assert( l.union_size() == 19); + CGAL_test_assert( ! i.test_identical_ptr( j)); + CGAL_test_assert( ! i.test_identical_ptr( k)); + CGAL_test_assert( ! i.test_identical_ptr( l)); + CGAL_test_assert( ! j.test_identical_ptr( k)); + CGAL_test_assert( ! j.test_identical_ptr( l)); + CGAL_test_assert( k.test_identical_ptr( l)); + // find j, links it to k and l + CGAL_test_assert( j.value() == 5); + CGAL_test_assert( i.is_forwarding()); + CGAL_test_assert( ! j.is_forwarding()); + CGAL_test_assert( ! k.is_forwarding()); + CGAL_test_assert( ! l.is_forwarding()); + CGAL_test_assert( i.union_size() == 3); + CGAL_test_assert( j.union_size() == 19); + CGAL_test_assert( k.union_size() == 19); + CGAL_test_assert( l.union_size() == 19); + CGAL_test_assert( ! i.test_identical_ptr( j)); + CGAL_test_assert( ! i.test_identical_ptr( k)); + CGAL_test_assert( ! i.test_identical_ptr( l)); + CGAL_test_assert( j.test_identical_ptr( k)); + CGAL_test_assert( j.test_identical_ptr( l)); + CGAL_test_assert( k.test_identical_ptr( l)); + // find i, links it to j, k and l + CGAL_test_assert( i.value() == 5); + CGAL_test_assert( ! i.is_forwarding()); + CGAL_test_assert( ! j.is_forwarding()); + CGAL_test_assert( ! k.is_forwarding()); + CGAL_test_assert( ! l.is_forwarding()); + CGAL_test_assert( i.union_size() == 19); + CGAL_test_assert( j.union_size() == 19); + CGAL_test_assert( k.union_size() == 19); + CGAL_test_assert( l.union_size() == 19); + CGAL_test_assert( i.test_identical_ptr( j)); + CGAL_test_assert( i.test_identical_ptr( k)); + CGAL_test_assert( i.test_identical_ptr( l)); + CGAL_test_assert( j.test_identical_ptr( k)); + CGAL_test_assert( j.test_identical_ptr( l)); + CGAL_test_assert( k.test_identical_ptr( l)); + } +} + +int main() { + test_handle(); + test_handle_with_class_hierarchy(); + return EXIT_SUCCESS; +} diff --git a/STL_Extension/test/STL_Extension/test_lexcompare_outputrange.C b/STL_Extension/test/STL_Extension/test_lexcompare_outputrange.C new file mode 100644 index 00000000000..8dee61de6d5 --- /dev/null +++ b/STL_Extension/test/STL_Extension/test_lexcompare_outputrange.C @@ -0,0 +1,95 @@ +// ============================================================================ +// +// Copyright (c) 2001-2006 Max-Planck-Institut Saarbruecken (Germany). +// All rights reserved. +// +// This file is part of EXACUS (http://www.mpi-inf.mpg.de/projects/EXACUS/); +// you may redistribute it under the terms of the Q Public License version 1.0. +// See the file LICENSE.QPL distributed with EXACUS. +// +// 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. +// +// ---------------------------------------------------------------------------- +// +// Library : LiS +// File : test/algorithm_test.C +// LiS_release : $Name: $ +// Revision : $Revision$ +// Revision_date : $Date$ +// +// Author(s) : Lutz Kettner +// Arno Eigenwillig +// +// ============================================================================ + +#include +#include +#include +#include +#include + +int A[] = {1,2,3,4,5}; + +int B1[] = {1,1,3}; +int B2[] = {1,2,3}; + +CGAL::Comparison_result compare( int i, int j) { + if ( ij) + return CGAL::LARGER; + return CGAL::EQUAL; +} + +void test_lex_compare() { + CGAL_test_assert( CGAL::EQUAL == CGAL::lexicographical_compare_three_valued( A, A+3, A, A+3, compare)); + CGAL_test_assert( CGAL::SMALLER == CGAL::lexicographical_compare_three_valued( A, A+3, A, A+4, compare)); + CGAL_test_assert( CGAL::SMALLER == CGAL::lexicographical_compare_three_valued( A, A+3, A, A+5, compare)); + CGAL_test_assert( CGAL::LARGER == CGAL::lexicographical_compare_three_valued( A, A+4, A, A+3, compare)); + CGAL_test_assert( CGAL::LARGER == CGAL::lexicographical_compare_three_valued( A, A+5, A, A+3, compare)); + + CGAL_test_assert( CGAL::SMALLER == CGAL::lexicographical_compare_three_valued( B1, B1+3, B2, B2+3, compare)); + CGAL_test_assert( CGAL::LARGER == CGAL::lexicographical_compare_three_valued( B2, B2+3, B1, B1+3, compare)); +} + +void test_output_range() { + std::ostringstream os; + std::ostream* sp; + CGAL::set_ascii_mode(os); + + CGAL_test_assert(os.str() == ""); + + sp = &(CGAL::output_range(os, A, A, ":", "(", ")")); + CGAL_test_assert(os.str() == ""); + CGAL_test_assert(sp == &os); + os.str(""); + + sp = &(CGAL::output_range(os, A, A+1, ":", "(", ")")); + CGAL_test_assert(os.str() == "(1)"); + CGAL_test_assert(sp == &os); + os.str(""); + + sp = &(CGAL::output_range(os, A, A+3, ":", "(", ")")); + CGAL_test_assert(os.str() == "(1):(2):(3)"); + CGAL_test_assert(sp == &os); + os.str(""); + + sp = &(CGAL::output_range(os, A, A+3)); + CGAL_test_assert(os.str() == "1, 2, 3"); + CGAL_test_assert(sp == &os); +} + + + +int main() { + test_lex_compare(); + test_output_range(); + + return EXIT_SUCCESS; +} + +// EOF diff --git a/Testsuite/include/CGAL/Testsuite/assert.h b/Testsuite/include/CGAL/Testsuite/assert.h index a6f33ec06c0..e54f986bf36 100644 --- a/Testsuite/include/CGAL/Testsuite/assert.h +++ b/Testsuite/include/CGAL/Testsuite/assert.h @@ -28,4 +28,7 @@ #define CGAL_test_assert(EX) \ ((EX)?(static_cast(0)): ::CGAL::assertion_fail( # EX , __FILE__, __LINE__, 0)) +#define CGAL_test_assert_msg(EX,MSG) \ + ((EX)?(static_cast(0)): ::CGAL::assertion_fail( # EX , __FILE__, __LINE__, MSG)) + #endif // CGAL_TESTSUITE_ASSERT_H diff --git a/iostream/include/CGAL/IO/io.h b/iostream/include/CGAL/IO/io.h index 745680c9d0c..e6441b98169 100644 --- a/iostream/include/CGAL/IO/io.h +++ b/iostream/include/CGAL/IO/io.h @@ -17,7 +17,7 @@ // // $URL$ // $Id$ -// +// // // Author(s) : Andreas Fabri @@ -26,6 +26,7 @@ #define CGAL_IO_H #include +#include #include #include @@ -35,9 +36,71 @@ CGAL_BEGIN_NAMESPACE class IO { public: static int mode; - enum Mode {ASCII = 0, PRETTY, BINARY}; + enum Mode {ASCII = 0, PRETTY, BENCHMARK, BINARY}; }; +template +class Output_rep { + const T& t; +public: + //! initialize with a const reference to \a t. + Output_rep( const T& tt) : t(tt) {} + //! perform the output, calls \c operator\<\< by default. + std::ostream& operator()( std::ostream& out) const { return (out << t); } +}; + +/*! \relates Output_rep + \brief stream output of the \c Output_rep calls its \c operator(). +*/ +template +std::ostream& +operator<<( std::ostream& out, Output_rep rep) { + return rep( out); +} + +//! generic IO output format manipulator. +template +Output_rep +oformat( const T& t) { return Output_rep(t); } + +//! generic IO output format manipulator with formatting tag. +template +Output_rep +oformat( const T& t, F) { return Output_rep(t); } + + + +/*!\brief + * input functor class created by the generic IO input manipulator. + * + * It holds a reference to the input object. Default implementation + * calls the stream input operator. Specializations can be written + * for external types not supporting our stream IO format. + */ +template +class Input_rep { + T& t; +public: + //! initialize with a reference to \a t. + Input_rep( T& tt) : t(tt) {} + //! perform the input, calls \c operator\>\> by default. + std::istream& operator()( std::istream& in) const { return (in >> t); } +}; + +/*! \relates Input_rep + \brief stream input to the \c Input_rep calls its \c operator(). +*/ +template +std::istream& +operator>>( std::istream& in, Input_rep rep) { + return rep( in); +} + +//! generic IO input format manipulator. +template +Input_rep +iformat( T& t) { return Input_rep(t); } + IO::Mode get_mode(std::ios& i); @@ -50,8 +113,12 @@ set_binary_mode(std::ios& i); IO::Mode set_pretty_mode(std::ios& i); +IO::Mode +set_benchmark_mode(std::ios& i); + IO::Mode set_mode(std::ios& i, IO::Mode m); + bool is_pretty(std::ios& i); @@ -61,6 +128,9 @@ is_ascii(std::ios& i); bool is_binary(std::ios& i); +bool +is_benchmark(std::ios& i); + inline io_Read_write io_tag(char){ return io_Read_write(); } @@ -78,7 +148,7 @@ inline void write(std::ostream& os, const T& t, const io_Operator&) { - os << t; + os << oformat(t); } @@ -114,7 +184,7 @@ inline void read(std::istream& is, T& t, const io_Operator&) { - is >> t; + is >> iformat(t); } @@ -141,8 +211,8 @@ std::ostream& operator<<( std::ostream& out, const Color& col) { switch(out.iword(IO::mode)) { case IO::ASCII : - return out << static_cast(col.red()) << ' ' - << static_cast(col.green()) << ' ' + return out << static_cast(col.red()) << ' ' + << static_cast(col.green()) << ' ' << static_cast(col.blue()); case IO::BINARY : write(out, static_cast(col.red())); @@ -150,7 +220,7 @@ std::ostream& operator<<( std::ostream& out, const Color& col) write(out, static_cast(col.blue())); return out; default: - return out << "Color(" << static_cast(col.red()) << ", " + return out << "Color(" << static_cast(col.red()) << ", " << static_cast(col.green()) << ", " << static_cast(col.blue()) << ')'; } @@ -178,6 +248,9 @@ std::istream &operator>>(std::istream &is, Color& col) return is; } +const char* mode_name( IO::Mode m ); + + CGAL_END_NAMESPACE #endif // CGAL_IO_H diff --git a/iostream/src/CGAL/io.cpp b/iostream/src/CGAL/io.cpp index 8710a1c861c..d670a79ba65 100644 --- a/iostream/src/CGAL/io.cpp +++ b/iostream/src/CGAL/io.cpp @@ -27,6 +27,7 @@ #include #include +#include CGAL_BEGIN_NAMESPACE @@ -65,6 +66,12 @@ set_pretty_mode(std::ios& i) return m; } +IO::Mode +set_benchmark_mode(std::ios& i) +{ + set_mode( i, IO::BENCHMARK ); +} + IO::Mode set_mode(std::ios& i, IO::Mode m) @@ -93,6 +100,19 @@ is_binary(std::ios& i) return i.iword(IO::mode) == IO::BINARY; } +bool +is_benchmark(std::ios& i) +{ + return i.iword(IO::mode) == IO::BENCHMARK; +} + +const char* mode_name( IO::Mode m) { + static const char* const names[] = {"ASCII", "PRETTY", "BENCHMARK", "BINARY" }; + CGAL_assertion( IO::ASCII <= m && m <= IO::BINARY ); + return names[m]; +} + + CGAL_END_NAMESPACE #endif // CGAL_IO_C diff --git a/iostream/test/iostream/data/io.cin b/iostream/test/iostream/data/io.cin new file mode 100644 index 00000000000..d81cc0710eb --- /dev/null +++ b/iostream/test/iostream/data/io.cin @@ -0,0 +1 @@ +42 diff --git a/iostream/test/iostream/test_ioformat.C b/iostream/test/iostream/test_ioformat.C new file mode 100644 index 00000000000..618b621b82e --- /dev/null +++ b/iostream/test/iostream/test_ioformat.C @@ -0,0 +1,41 @@ +// ============================================================================ +// +// Copyright (c) 2001-2006 Max-Planck-Institut Saarbruecken (Germany). +// All rights reserved. +// +// This file is part of EXACUS (http://www.mpi-inf.mpg.de/projects/EXACUS/); +// you may redistribute it under the terms of the Q Public License version 1.0. +// See the file LICENSE.QPL distributed with EXACUS. +// +// 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. +// +// ---------------------------------------------------------------------------- +// +// Library : LiS +// File : test/io.C +// LiS_release : $Name: $ +// Revision : $Revision$ +// Revision_date : $Date$ +// +// Author(s) : Lutz Kettner +// +// ============================================================================ + +#include +#include +#include +#include +#include + +int main() { + std::cout << CGAL::oformat(5) << std::endl; + std::cout << CGAL::oformat("Ok") << std::endl; + int i; + std::cin >> CGAL::iformat(i); + CGAL_test_assert( i == 42); + return EXIT_SUCCESS; +}