mirror of https://github.com/CGAL/cgal
392 lines
16 KiB
TeX
392 lines
16 KiB
TeX
% +------------------------------------------------------------------------+
|
|
% | CGAL Reference Manual: circulator.tex
|
|
% +------------------------------------------------------------------------+
|
|
% | Requirements for circulators in analogy to STL iterators.
|
|
% | Adaptors between circulators and iterators.
|
|
% | Proposal for CGAL.
|
|
% |
|
|
% | 11.10.1996 Lutz Kettner
|
|
% |
|
|
\RCSdef{\circRev}{$Id$}
|
|
\RCSdefDate{\circDate}{$Date$}
|
|
% +------------------------------------------------------------------------+
|
|
|
|
\gdef\lciIfHtmlClassLinks{\lcFalse}
|
|
\gdef\lciIfHtmlRefLinks{\lcFalse}
|
|
\gdef\lciIfHtmlLinks{\lcFalse}
|
|
|
|
\section{Circulators}
|
|
%\label{chapterCirculators}
|
|
|
|
%\ccChapterRelease{\circRev. \ \circDate}\\
|
|
%\ccChapterAuthor{Lutz Kettner}
|
|
|
|
An introduction to the concept of circulators is given here. A couple
|
|
of adaptors are presented that convert between iterators and
|
|
circulators. Some useful functions for circulators follow. This
|
|
chapter concludes with a discussion of the design decisions taken. For
|
|
the full description of the circulator requirements, the provided base
|
|
classes, the circulator tags, and the support for generic algorithms
|
|
that work for iterators as well as for circulators please refer to the
|
|
reference pages. Note that circulators are not part of \stl, but of \cgal.
|
|
|
|
% +-----------------------------------------------------+
|
|
\subsection{Introduction\label{sectionIntroduction}}
|
|
\label{sectionCirculatorWarning}
|
|
|
|
The concept of iterators in \stl\ is tailored for linear
|
|
sequences~\cite{cgal:ansi-is14882-98,cgal:ms-strg-96}. In contrast, circular
|
|
sequences occur naturally in many combinatorial and geometric
|
|
structures. Examples are polyhedral surfaces and planar maps, where
|
|
the edges emanating from a vertex or the edges around a facet form a
|
|
circular sequence.
|
|
|
|
Since circular sequences do not allow for efficient iterators, we have
|
|
introduced the new concept of {\em circulators}. They share most of
|
|
the requirements of iterators, while the main difference is the lack
|
|
of a past-the-end position in the sequence. Appropriate adaptors are
|
|
provided between iterators and circulators to integrate circulators
|
|
smoothly into the framework of \stl. An example of a generic {\tt
|
|
contains} function illustrates the use of circulators. As usual for
|
|
circular structures, a {\tt do}-{\tt while} loop is preferable, such
|
|
that for the specific input, {\tt c == d}, all elements in the
|
|
sequence are reached.
|
|
|
|
\begin{ccExampleCode}
|
|
template <class Circulator, class T>
|
|
bool contains( Circulator c, Circulator d, const T& value) {
|
|
if (c != 0) {
|
|
do {
|
|
if (*c == value)
|
|
return true;
|
|
} while (++c != d);
|
|
}
|
|
return false;
|
|
}
|
|
\end{ccExampleCode}
|
|
|
|
\noindent
|
|
Three circulator categories are defined: forward, bidirectional and
|
|
random-access circulators. Given a circulator {\tt c}, the operation
|
|
{\tt *c} denotes the item the circulator refers to. The operation {\tt
|
|
++c} advances the circulator by one item and {\tt --c} steps a
|
|
bidirectional circulator one item backwards. For random-access
|
|
circulators {\tt c+n} advances the circulator {\tt n} steps. Two
|
|
circulators can be compared for equality.
|
|
|
|
Circulators have a different notion of reachability and ranges than
|
|
iterators. A circulator {\tt d} is called {\em reachable\/} from a
|
|
circulator {\tt c} if {\tt c} can be made equal to {\tt d} with
|
|
finitely many applications of the operator {\tt ++}. Due to the
|
|
circularity of the sequence this is always true if both circulators
|
|
refer to items of the same sequence. In particular, {\tt c} is always
|
|
reachable from {\tt c}. Given two circulators {\tt c} and {\tt d}, the
|
|
range {\tt [c,d)} denotes all circulators obtained by starting with
|
|
{\tt c} and advancing {\tt c} until {\tt d} is reached, but does not
|
|
include {\tt d}, for {\tt d} $\neq$ {\tt c}. So far it is the same
|
|
range definition as for iterators. The difference lies in the use of
|
|
{\tt [c,c)} to denote all items in the circular sequence, whereas for
|
|
an iterator {\tt i} the range {\tt [i,i)} denotes the empty range. As
|
|
long as {\tt c != d} the range {\tt[c,d)} behaves like an iterator
|
|
range and could be used in \stl\ algorithms. For circulators however,
|
|
an additional test {\tt c == NULL} is required that returns true if
|
|
and only if the circular sequence is empty. As for
|
|
\CC, we recommend the use of 0 instead of {\tt NULL}.
|
|
|
|
Besides the conceptual cleanness, the main reason for inventing a new
|
|
concept with a similar intent as iterators is efficiency. An iterator
|
|
is supposed to be a light-weight object -- merely a pointer and a
|
|
single indirection to advance the iterator. Although iterators could
|
|
be written for circular sequences, we do not know of an efficient
|
|
solution. The missing past-the-end situation in circular sequences can
|
|
be solved with an arbitrary sentinel in the cyclic order, but this
|
|
would destroy the natural symmetry in the structure (which is in
|
|
itself a bad idea) and additional bookkeeping in the items and
|
|
checking in the iterator advance method reduces efficiency. Another
|
|
solution may use more bookkeeping in the iterator, e.g.~with a start
|
|
item, a current item, and a kind of winding-number that is zero for
|
|
the {\tt begin()}-iterator and one for the past-the-end
|
|
situation\footnote{This is currently implemented as the
|
|
adaptor class which provides a pair of iterators for a given
|
|
circulator.}. We have introduced the concept of circulators
|
|
that allows light-weight implementations and the \cgal\ support
|
|
library provides adaptor classes that convert between iterators and
|
|
circulators (with the corresponding penalty in efficiency), so as to
|
|
integrate this new concept into the framework of \stl.
|
|
|
|
A serious design problem is the slight change of the semantic for
|
|
circulator ranges as compared to iterator ranges. Since this semantic
|
|
is defined by the intuitive operators {\tt ++} and {\tt ==}, which we
|
|
would like to keep for circulators as well, circulator ranges can be
|
|
used in \stl\ algorithms. This is in itself a useful feature, if there
|
|
would not be the definition of a full range $\left[c, c\right)$ that
|
|
an \stl\ algorithm will treat as an empty range. However, the
|
|
likelihood of a mistake may be overestimated, since for a container
|
|
{\tt C} supporting circulators there is no {\tt end()} member
|
|
function, and an expression such as {\tt std::sort( C.begin(),
|
|
C.end())} will fail. It is easy to distinguish iterators and
|
|
circulators at compile time, which allows for generic algorithms
|
|
supporting both as arguments. It is also possible to protect
|
|
algorithms against inappropriate arguments using the same technique,
|
|
see the reference pages for circulators, specifically the
|
|
\ccc{Assert_iterator} and \ccc{is_empty_range} functions.
|
|
|
|
{\bf Warning:} Please note that the definition of a range is different
|
|
from that of iterators. An interface of a data structure must declare
|
|
whether it works with iterators, circulators, or both. \stl\
|
|
algorithms always specify only iterators in their interfaces. A range
|
|
$\left[c, d\right)$ of circulators used in an interface for iterators
|
|
will work as expected as long as $c\; !\!= d$. A range $\left[c,
|
|
c\right)$ will be interpreted as the empty range like for iterators,
|
|
which is different than the full range that it should denote for
|
|
circulators.
|
|
|
|
% +---------------------------------------------+
|
|
\begin{ccHtmlClassFile}{Circulator.html}{Requirements for Circulators}
|
|
\ccHtmlNoClassLinks
|
|
\begin{ccClass}{Circulator}
|
|
\subsection{Forward Circulator}
|
|
|
|
A class \ccClassName\ that satisfies the requirements of a forward
|
|
circulator with the value type \ccStyle{T}, supports the following
|
|
operations. See the reference pages for the full set of requirements.
|
|
Note that the stated return values are not required, only a return
|
|
value that is convertible to the stated type is required. As for \CC,
|
|
we recommend the use of 0 instead of {\tt NULL}.
|
|
|
|
\ccTypes
|
|
\ccSetTwoColumns{Circulator:: iterator_category}{}
|
|
|
|
\ccNestedType{value_type}{the value type \ccStyle{T}.}
|
|
\ccGlue
|
|
\ccNestedType{reference}{either reference or const reference to \ccStyle{T}.}
|
|
\ccGlue
|
|
\ccNestedType{pointer}{either pointer or const pointer to \ccStyle{T}.}
|
|
\ccGlue
|
|
\ccNestedType{size_type}{unsigned integral type that can hold the size
|
|
of the sequence.}
|
|
\ccGlue
|
|
\ccNestedType{difference_type}{signed integral type that can hold the
|
|
distance between two circulators.}
|
|
\ccGlue
|
|
\ccNestedType{iterator_category}{circulator category
|
|
\ccc{Forward_circulator_tag}.}
|
|
|
|
\ccCreation
|
|
\ccCreationVariable{c}
|
|
%\ccSetThreeColumns{Circulator&}{int n + Circulator d}{}
|
|
\ccSetThreeColumns{difference_type}{difference_type n += d}{}
|
|
\ccPropagateThreeToTwoColumns
|
|
|
|
\ccConstructor{Circulator();}{a circulator equal to \ccc{NULL} denoting
|
|
an empty sequence.}
|
|
\ccGlue
|
|
\ccConstructor{Circulator(const Circulator& d);}{a circulator equal to $d$.}
|
|
|
|
\ccOperations
|
|
|
|
\ccMethod{Circulator& operator=(const Circulator &d);}
|
|
{Assignment.}
|
|
\ccGlue
|
|
\ccMethod{bool operator==(NULL) const;}
|
|
{Test for emptiness.}
|
|
\ccGlue
|
|
\ccMethod{bool operator!=(NULL) const;}
|
|
{Test for non-emptiness, i.e.~ \ccStyle{!(c == NULL)}.}
|
|
\ccGlue
|
|
\ccMethod{bool operator==(const Circulator &d) const;}
|
|
{$c$ is equal to $d$ if they refer to the same item.}
|
|
\ccGlue
|
|
\ccMethod{bool operator!=(const Circulator &d) const;}
|
|
{Test for inequality, i.e.~\ccStyle{!(c == d)}.}
|
|
|
|
\ccMethod{reference operator*();}
|
|
{Returns the value of the circulator.
|
|
If \ccClassName\ is mutable \ccStyle{*c = t} is valid.
|
|
\ccPrecond \ccVar\ is dereferenceable.}
|
|
|
|
\ccMethod{pointer operator->();}
|
|
{Returns a pointer to the value of the circulator.
|
|
\ccPrecond \ccVar\ is dereferenceable.}
|
|
|
|
\ccMethod{Circulator& operator++();}
|
|
{Prefix increment operation.
|
|
\ccPrecond \ccVar\ is dereferenceable.
|
|
\ccPostcond \ccVar\ is dereferenceable.}
|
|
|
|
\ccMethod{const Circulator& operator++(int);}
|
|
{Postfix increment operation. The result is the same as that of:
|
|
\ccStyle{Circulator tmp = c; ++c; return tmp;}~.}
|
|
|
|
\end{ccClass}
|
|
|
|
|
|
% +---------------------------------------------+
|
|
\ccHtmlNoClassLinks
|
|
\ccHtmlNoClassIndex
|
|
\begin{ccClass}{Circulator}
|
|
\subsection{Bidirectional Circulator}
|
|
|
|
A class \ccClassName\ that satisfies the requirements of a bidirectional
|
|
circulator with the value type \ccStyle{T}, supports the following operations
|
|
in addition to the operations supported by a forward circulator.
|
|
|
|
\ccTypes
|
|
\ccSetTwoColumns{Circulator:: iterator_category}{}
|
|
|
|
\ccNestedType{iterator_category}{circulator category
|
|
\ccc{Bidirectional_circulator_tag}.}
|
|
|
|
\ccSetThreeColumns{difference_type}{difference_type n += d}{}
|
|
\ccPropagateThreeToTwoColumns
|
|
\ccCreationVariable{c}
|
|
\ccOperations
|
|
|
|
\ccMethod{Circulator& operator--();}
|
|
{Prefix decrement operation.
|
|
\ccPrecond \ccVar\ is dereferenceable. \ccPostcond\ccVar\ is dereferenceable.}
|
|
|
|
\ccMethod{const Circulator& operator--(int);}
|
|
{Postfix decrement operation. The result is the same as that of
|
|
\ccStyle{Circulator tmp = c; --c; return tmp;}~.}
|
|
|
|
\end{ccClass}
|
|
|
|
|
|
% +---------------------------------------------+
|
|
\ccHtmlNoClassLinks
|
|
\ccHtmlNoClassIndex
|
|
\begin{ccClass}{Circulator}
|
|
\subsection{Random Access Circulator\label{sectionRandomAccessCirculatorRequ}}
|
|
|
|
A class \ccClassName\ that satisfies the requirements of a random
|
|
access Circulator for the value type \ccStyle{T}, supports the
|
|
following operations in addition to the operations supported by a
|
|
bidirectional Circulator. In contrast to random access iterators,
|
|
no comparison operators are available for
|
|
random access circulators.
|
|
|
|
\ccTypes
|
|
\ccSetTwoColumns{Circulator:: iterator_category}{}
|
|
|
|
\ccNestedType{iterator_category}{circulator category
|
|
\ccc{Random_access_circulator_tag}.}
|
|
|
|
\ccSetThreeColumns{difference_type}{difference_type n += d}{}
|
|
\ccPropagateThreeToTwoColumns
|
|
\ccCreationVariable{c}
|
|
\ccOperations
|
|
|
|
\ccMethod{Circulator& operator+=(difference_type n);}
|
|
{The result is the same as if the prefix increment operation
|
|
was applied $n$ times, but it is computed in constant time.}
|
|
|
|
\ccMethod{Circulator operator+(difference_type n);}
|
|
{Same as above, but returns a new circulator.}
|
|
|
|
\def\ccTagRmEigenClassName{\ccTrue}
|
|
\ccFunction{Circulator operator+(difference_type n, Circulator c);}
|
|
{Same as above.}
|
|
\def\ccTagRmEigenClassName{\ccFalse}
|
|
|
|
\ccMethod{Circulator& operator-=(difference_type n);}
|
|
{The result is the same as if the prefix decrement operation
|
|
was applied $n$ times, but it is computed in constant time.}
|
|
|
|
\ccMethod{Circulator operator-(difference_type n);}
|
|
{Same as above, but returns a new circulator.}
|
|
|
|
|
|
\ccMethod{reference operator[](difference_type n);}
|
|
{Returns \ccStyle{*(c + n)}.}
|
|
|
|
\ccMethod{difference_type operator-(const Circulator& d) const;}
|
|
{returns the difference between the two circulators. The value will be
|
|
in the interval $\left[ 1-s , s-1 \right]$ if $s$ is the size of the
|
|
total sequence. The difference for a fixed circulator \ccVar\ (or
|
|
$d$) with all other circulators $d$ (or \ccVar) is a consistent
|
|
ordering of the elements in the data structure. There has to be a
|
|
minimal circulator $d_{\mbox{\footnotesize min}}$ for which the
|
|
difference \ccVar $- d_{\mbox{\footnotesize min}}$ to all other
|
|
circulators \ccVar\ is non-negative.}
|
|
|
|
\ccMethod{Circulator min_circulator() const;}
|
|
{Returns the minimal circulator $c_{\mbox{\footnotesize min}}$
|
|
in constant time.}
|
|
|
|
\end{ccClass}
|
|
\end{ccHtmlClassFile}
|
|
|
|
% +-----------------------------------------------------+
|
|
\subsection{Adaptors Between Iterators and Circulators\label{sectionCirculatorAdaptor}}
|
|
|
|
Algorithms working on iterator ranges can not be applied to circulator
|
|
ranges in full generality, only to subranges (see the warning in
|
|
Section~\ref{sectionCirculatorWarning}). The following adaptors
|
|
convert circulators to iterators and vice versa (with the unavoidable
|
|
space and time penalty) to reestablish this generality.
|
|
|
|
\ccInclude{CGAL/circulator.h}
|
|
|
|
\begin{tabbing}
|
|
\ccc{Container_from_circulator}\ \ \ \=
|
|
container-like class with iterators built from a circulator\\
|
|
\ccc{Circulator_from_iterator} \>
|
|
circulator over a range of two iterators\\
|
|
\ccc{Circulator_from_container} \>
|
|
circulator for a container
|
|
\end{tabbing}
|
|
|
|
The following example applies the generic {\tt std::reverse()} algorithm
|
|
from \stl\ to a sequence given by a bidirectional circulator {\tt c}.
|
|
It uses the \ccc{Container_from_circulator} adaptor.
|
|
|
|
\begin{ccExampleCode}
|
|
Circulator c; // c must be at least bidirectional.
|
|
CGAL::Container_from_circulator<Circulator> container(c);
|
|
std::reverse( container.begin(), container.end());
|
|
\end{ccExampleCode}
|
|
|
|
Another example defines a circulator \ccc{c} for a vector of
|
|
\ccc{int}'s. However, since there are no elements in the vector, the
|
|
circulator denotes an empty sequence. If there were elements in the
|
|
vector, the circulator would implement a random access modulus the
|
|
size of the sequence.
|
|
|
|
\begin{ccExampleCode}
|
|
std::vector<int> v;
|
|
typedef CGAL::Circulator_from_iterator<
|
|
std::vector<int>::iterator > Circulator;
|
|
Circulator c( v.begin(), v.end());
|
|
\end{ccExampleCode}
|
|
|
|
% +-----------------------------------------------------+
|
|
\subsection{Functions on Circulators\label{sectionCirculatorFunctions}}
|
|
|
|
A few functions deal with circulators and circulator ranges. The type
|
|
\ccc{C} denotes a circulator. The type \ccc{IC} denotes either a circulator
|
|
or an iterator. More on algorithms that work with circulators as well with
|
|
iterators can be found in the reference pages.
|
|
|
|
\ccInclude{CGAL/circulator.h}
|
|
|
|
\begin{tabbing}
|
|
\ccTexHtml{\ccc{Forward_container_from_circulator}\ \ \ \= \kill}{}
|
|
\ccc{circulator_size(C c)} \>
|
|
size of the sequence reachable by \ccc{c}\\
|
|
\ccc{circulator_distance(C c, C d)} \>
|
|
number of elements in the range $\left[c, d\right)$ \\
|
|
\ccc{iterator_distance(IC ic1, IC ic2)} \>
|
|
number of elements in the range $\left[\ccc{ic2}, \ccc{ic1}\right)$ \\
|
|
\ccc{is_empty_range( IC ic1, IC ic2)} \>
|
|
test the range $\left[\ccc{ic2}, \ccc{ic1}\right)$ for emptiness
|
|
\end{tabbing}
|
|
|
|
\gdef\lciIfHtmlClassLinks{\lcTrue}
|
|
\gdef\lciIfHtmlRefLinks{\lcTrue}
|
|
\gdef\lciIfHtmlLinks{\lcTrue}
|
|
|
|
|
|
% +-----------------------------------------------------+
|
|
% EOF
|