mirror of https://github.com/CGAL/cgal
193 lines
6.1 KiB
C++
193 lines
6.1 KiB
C++
// ============================================================================
|
|
//
|
|
// Copyright (c) 1997, 1998, 1999 The CGAL Consortium
|
|
//
|
|
// This software and related documentation is part of an INTERNAL release
|
|
// of the Computational Geometry Algorithms Library (CGAL). It is not
|
|
// intended for general use.
|
|
//
|
|
// ----------------------------------------------------------------------------
|
|
//
|
|
// release : $CGAL_Revision: $
|
|
// release_date : $CGAL_Date: $
|
|
//
|
|
// file : Inverse_index.h
|
|
// chapter : $CGAL_Chapter: STL Extensions for CGAL $
|
|
// package : $CGAL_Package: STL_Extension $
|
|
// source : stl_extension.fw
|
|
// revision : $Revision$
|
|
// revision_date : $Date$
|
|
// author(s) : Michael Hoffmann <hoffmann@inf.ethz.ch>
|
|
// Lutz Kettner <kettner@inf.ethz.ch>
|
|
//
|
|
// coordinator : INRIA, Sophia Antipolis
|
|
//
|
|
// Inverse_Index adaptor enumerates sequences.
|
|
// ============================================================================
|
|
|
|
#ifndef CGAL_INVERSE_INDEX_H
|
|
#define CGAL_INVERSE_INDEX_H 1
|
|
#include <CGAL/circulator.h> // Needed for circulator categories.
|
|
#include <map>
|
|
|
|
CGAL_BEGIN_NAMESPACE
|
|
|
|
template < class IC>
|
|
class Inverse_index {
|
|
|
|
// DEFINITION
|
|
//
|
|
// The class Inverse_index<IC,T> constructs an inverse index for a
|
|
// given range [i,j) of two iterators or circulators of type `IC' with the
|
|
// value type `T'. The first element I in the
|
|
// range [i,j) has the index 0. Consecutive elements are numbered
|
|
// incrementally. The inverse index provides a query for a given iterator
|
|
// or circulator k to retrieve its index number. For random access
|
|
// iterators or circulators, it is done in constant time by subtracting i.
|
|
// For other iterator categories, an STL `map' is used, which results in a
|
|
// log j-i query time. A comparison operator `operator<' is needed for
|
|
// `T*'.
|
|
//
|
|
// CREATION
|
|
|
|
protected:
|
|
typedef std::map< const void*, std::size_t, std::less<const void*> >
|
|
Index;
|
|
Index idx;
|
|
IC start;
|
|
typedef typename Index::iterator Index_iterator;
|
|
typedef typename Index::const_iterator Index_const_iterator;
|
|
typedef typename Index::value_type Item;
|
|
|
|
private:
|
|
void ini_idx( IC i, const IC& j, std::input_iterator_tag);
|
|
void ini_idx( const IC& i, const IC& j, std::forward_iterator_tag){
|
|
ini_idx( i, j, std::input_iterator_tag());
|
|
}
|
|
void ini_idx(const IC& i,const IC& j, std::bidirectional_iterator_tag){
|
|
ini_idx( i, j, std::input_iterator_tag());
|
|
}
|
|
void ini_idx( const IC& i, const IC& j, Forward_circulator_tag) {
|
|
ini_idx( i, j, std::input_iterator_tag());
|
|
}
|
|
void ini_idx( const IC& i, const IC& j, Bidirectional_circulator_tag){
|
|
ini_idx( i, j, std::input_iterator_tag());
|
|
}
|
|
void ini_idx( const IC&, const IC&, std::random_access_iterator_tag){}
|
|
void ini_idx( const IC&, const IC&, Random_access_circulator_tag){}
|
|
|
|
public:
|
|
void init_index( const IC& i, const IC& j) {
|
|
#if !defined(CGAL_CFG_NO_ITERATOR_TRAITS) || \
|
|
defined(CGAL_LIMITED_ITERATOR_TRAITS_SUPPORT)
|
|
typedef typename std::iterator_traits<IC>::iterator_category ICC;
|
|
ini_idx( i, j, ICC());
|
|
#else
|
|
ini_idx( i, j, std::iterator_category( i));
|
|
#endif
|
|
}
|
|
|
|
private:
|
|
void push_back( const IC& k, std::input_iterator_tag) {
|
|
std::size_t d = idx.size();
|
|
idx[ &*k] = d;
|
|
}
|
|
void push_back( const IC& k, std::forward_iterator_tag){
|
|
push_back( k, std::input_iterator_tag());
|
|
}
|
|
void push_back( const IC& k, std::bidirectional_iterator_tag){
|
|
push_back( k, std::input_iterator_tag());
|
|
}
|
|
void push_back( const IC& k, Forward_circulator_tag){
|
|
push_back( k, std::input_iterator_tag());
|
|
}
|
|
void push_back( const IC& k, Bidirectional_circulator_tag){
|
|
push_back( k, std::input_iterator_tag());
|
|
}
|
|
void push_back( const IC&, std::random_access_iterator_tag){}
|
|
void push_back( const IC&, Random_access_circulator_tag){}
|
|
|
|
public:
|
|
void push_back( const IC& k) {
|
|
// adds k at the end of the indices.
|
|
#if !defined(CGAL_CFG_NO_ITERATOR_TRAITS) || \
|
|
defined(CGAL_LIMITED_ITERATOR_TRAITS_SUPPORT)
|
|
typedef typename std::iterator_traits<IC>::iterator_category ICC;
|
|
push_back( k, ICC());
|
|
#else
|
|
push_back( k, std::iterator_category( k));
|
|
#endif
|
|
}
|
|
|
|
std::size_t find( const IC& k, std::random_access_iterator_tag) const {
|
|
return std::size_t(k - start);
|
|
}
|
|
std::size_t find( const IC& k, Random_access_circulator_tag) const {
|
|
return std::size_t(k - start);
|
|
}
|
|
std::size_t find( const IC& k, std::input_iterator_tag) const {
|
|
// returns inverse index of k.
|
|
Index_const_iterator i = idx.find( &*k);
|
|
CGAL_assertion( i != idx.end());
|
|
return (*i).second;
|
|
}
|
|
std::size_t find( const IC& k, std::forward_iterator_tag) const {
|
|
return find( k, std::input_iterator_tag());
|
|
}
|
|
std::size_t find( const IC& k, std::bidirectional_iterator_tag) const {
|
|
return find( k, std::input_iterator_tag());
|
|
}
|
|
std::size_t find( const IC& k, Forward_circulator_tag) const {
|
|
return find( k, std::input_iterator_tag());
|
|
}
|
|
std::size_t find( const IC& k, Bidirectional_circulator_tag) const {
|
|
return find( k, std::input_iterator_tag());
|
|
}
|
|
|
|
typedef IC iterator;
|
|
typedef IC Circulator;
|
|
typedef std::size_t size_type;
|
|
|
|
Inverse_index() : start(IC()) {}
|
|
// invalid index.
|
|
|
|
Inverse_index( const IC& i) : start(i) {};
|
|
// empty inverse index initialized to start at i.
|
|
|
|
Inverse_index( const IC& i, const IC& j) : start(i) {
|
|
// inverse index initialized with range [i,j).
|
|
init_index( i, j);
|
|
}
|
|
|
|
// OPERATIONS
|
|
|
|
std::size_t operator[]( const IC& k) const {
|
|
// returns inverse index of k.
|
|
#if !defined(CGAL_CFG_NO_ITERATOR_TRAITS) || \
|
|
defined(CGAL_LIMITED_ITERATOR_TRAITS_SUPPORT)
|
|
typedef typename std::iterator_traits<IC>::iterator_category
|
|
category;
|
|
return find( k, category());
|
|
#else
|
|
return find( k, std::iterator_category( k));
|
|
#endif
|
|
}
|
|
};
|
|
|
|
template < class IC>
|
|
void
|
|
Inverse_index< IC>::ini_idx( IC i, const IC& j, std::input_iterator_tag) {
|
|
std::size_t n = 0;
|
|
Index_iterator hint = idx.begin();
|
|
if ( ! is_empty_range( i, j)) {
|
|
do {
|
|
hint = idx.insert( hint, Item( &*i, n));
|
|
n++;
|
|
} while ((++i) != (j));
|
|
}
|
|
}
|
|
|
|
CGAL_END_NAMESPACE
|
|
#endif // CGAL_INVERSE_INDEX_H //
|
|
// EOF //
|