2 * This program is free software: you can redistribute it and/or modify
3 * it under the terms of the GNU Lesser General Public License as
4 * published by the Free Software Foundation, either version 3 of the
5 * License, or (at your option) any later version.
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
12 * You should have received a copy of the GNU General Public License
13 * along with this program. If not, see <http://www.gnu.org/licenses/>.
18 * @file IteratorFunctions.ih
19 * @author Tristan Roussillon (\c tristan.roussillon@liris.cnrs.fr )
20 * Laboratoire d'InfoRmatique en Image et Systèmes d'information - LIRIS (CNRS, UMR 5205), CNRS, France
24 * Implementation of inline methods defined in IteratorFunctions.h
26 * This file is part of the DGtal library.
30//////////////////////////////////////////////////////////////////////////////
32//////////////////////////////////////////////////////////////////////////////
34///////////////////////////////////////////////////////////////////////////////
35// IMPLEMENTATION of inline methods.
36///////////////////////////////////////////////////////////////////////////////
38//-----------------------------------------------------------------------------
40bool DGtal::isEmpty( const IC& itb, const IC& ite )
42 return !detail::isNotEmpty<IC>( itb, ite, typename IteratorCirculatorTraits<IC>::Type() );
45//-----------------------------------------------------------------------------
47bool DGtal::isNotEmpty( const IC& itb, const IC& ite )
49 return detail::isNotEmpty<IC>( itb, ite, typename IteratorCirculatorTraits<IC>::Type() );
52//-----------------------------------------------------------------------------
53template< typename IC >
54bool DGtal::detail::isNotEmpty( const IC& itb, const IC& ite, IteratorType )
59//-----------------------------------------------------------------------------
60template< typename IC >
61bool DGtal::detail::isNotEmpty( const IC& c1, const IC& c2, CirculatorType )
63 // Using isValid method does not work adapters of circulators
64 // (eg. reverse circulators), which does not have any isValid method
65 // That's why we choose the following method:
66 IC c; //c is necessarily not valid
67 //if c1 or c2 is equal to a not valid circulator,
68 //then the underlying range is necessarily empty
69 return ( (c1 != c) && (c2 != c) );
72//-----------------------------------------------------------------------------
74void DGtal::advanceIterator(IC& ic,
75 typename IteratorCirculatorTraits<IC>::Difference n)
77 BOOST_CONCEPT_ASSERT(( boost_concepts::ForwardTraversalConcept<IC> ));
79 typedef typename IteratorCirculatorTraits<IC>::Category Category;
80 DGtal::detail::advanceIterator( ic, n, Category() );
83//-----------------------------------------------------------------------------
85void DGtal::detail::advanceIterator(IC& ic,
86 typename IteratorCirculatorTraits<IC>::Difference n,
89 BOOST_CONCEPT_ASSERT(( boost_concepts::ForwardTraversalConcept<IC> ));
100//-----------------------------------------------------------------------------
102void DGtal::detail::advanceIterator(IC& ic,
103 typename IteratorCirculatorTraits<IC>::Difference n,
104 RandomAccessCategory)
106 BOOST_CONCEPT_ASSERT(( boost_concepts::RandomAccessTraversalConcept<IC> ));
111//-----------------------------------------------------------------------------
113typename DGtal::IteratorCirculatorTraits<IC>::Difference
114DGtal::rangeSize(const IC& itb, const IC& ite)
116 BOOST_CONCEPT_ASSERT(( boost_concepts::ForwardTraversalConcept<IC> ));
118 typedef typename IteratorCirculatorTraits<IC>::Type Type;
119 typedef typename IteratorCirculatorTraits<IC>::Category Category;
120 return DGtal::detail::rangeSize( itb, ite, Type(), Category() );
123//-----------------------------------------------------------------------------
125typename DGtal::IteratorCirculatorTraits<IC>::Difference
126DGtal::subRangeSize(const IC& itb, const IC& ite)
128 BOOST_CONCEPT_ASSERT(( boost_concepts::ForwardTraversalConcept<IC> ));
130 typedef typename IteratorCirculatorTraits<IC>::Category Category;
131 return DGtal::detail::rangeSize( itb, ite, IteratorType(), Category() );
134//-----------------------------------------------------------------------------
136typename DGtal::IteratorCirculatorTraits<I>::Difference
137DGtal::detail::rangeSize(const I& itb, const I& ite, IteratorType, ForwardCategory)
139 BOOST_CONCEPT_ASSERT(( boost_concepts::ForwardTraversalConcept<I> ));
143 typename DGtal::IteratorCirculatorTraits<I>::Difference counter = 0;
152//-----------------------------------------------------------------------------
154typename DGtal::IteratorCirculatorTraits<C>::Difference
155DGtal::detail::rangeSize(const C& cb, const C& ce, CirculatorType, ForwardCategory)
157 BOOST_CONCEPT_ASSERT(( boost_concepts::ForwardTraversalConcept<C> ));
159 if (isNotEmpty(cb, ce))
163 typename DGtal::IteratorCirculatorTraits<C>::Difference counter = 0;
177//-----------------------------------------------------------------------------
179typename DGtal::IteratorCirculatorTraits<I>::Difference
180DGtal::detail::rangeSize(const I& itb, const I& ite, IteratorType, RandomAccessCategory)
182 BOOST_CONCEPT_ASSERT(( boost_concepts::RandomAccessTraversalConcept<I> ));
183 ASSERT( itb <= ite );
188//-----------------------------------------------------------------------------
190typename DGtal::IteratorCirculatorTraits<C>::Difference
191DGtal::detail::rangeSize(const C& cb, const C& ce, CirculatorType, RandomAccessCategory)
193 BOOST_CONCEPT_ASSERT(( boost_concepts::RandomAccessTraversalConcept<C> ));
195 if (isNotEmpty(cb, ce))
201 return ( (ce - c) + 1 );
214//-----------------------------------------------------------------------------
216IC DGtal::rangeMiddle(const IC& itb, const IC& ite)
218 BOOST_CONCEPT_ASSERT(( boost_concepts::ForwardTraversalConcept<IC> ));
220 typedef typename IteratorCirculatorTraits<IC>::Type Type;
221 typedef typename IteratorCirculatorTraits<IC>::Category Category;
222 return DGtal::detail::rangeMiddle( itb, ite, Type(), Category() );
225//-----------------------------------------------------------------------------
227IC DGtal::subRangeMiddle(const IC& itb, const IC& ite)
229 BOOST_CONCEPT_ASSERT(( boost_concepts::ForwardTraversalConcept<IC> ));
231 typedef typename IteratorCirculatorTraits<IC>::Category Category;
232 return DGtal::detail::rangeMiddle( itb, ite, IteratorType(), Category() );
235//-----------------------------------------------------------------------------
237I DGtal::detail::rangeMiddle(const I& itb, const I& ite, IteratorType, ForwardCategory)
239 BOOST_CONCEPT_ASSERT(( boost_concepts::ForwardTraversalConcept<I> ));
242 typename DGtal::IteratorCirculatorTraits<I>::Difference s
243 = DGtal::detail::rangeSize(itb, ite, IteratorType(), ForwardCategory());
245 typename DGtal::IteratorCirculatorTraits<I>::Difference m
247 //advance until the middle
249 DGtal::detail::advanceIterator(i, m, ForwardCategory());
253//-----------------------------------------------------------------------------
255C DGtal::detail::rangeMiddle(const C& cb, const C& ce, CirculatorType, ForwardCategory)
257 BOOST_CONCEPT_ASSERT(( boost_concepts::ForwardTraversalConcept<C> ));
260 typename DGtal::IteratorCirculatorTraits<C>::Difference s
261 = DGtal::detail::rangeSize(cb, ce, CirculatorType(), ForwardCategory());
263 typename DGtal::IteratorCirculatorTraits<C>::Difference m
265 //advance until the middle
267 DGtal::detail::advanceIterator(c, m, ForwardCategory());
271//-----------------------------------------------------------------------------
273I DGtal::detail::rangeMiddle(const I& itb, const I& ite, IteratorType, BidirectionalCategory)
275 BOOST_CONCEPT_ASSERT(( boost_concepts::BidirectionalTraversalConcept<I> ));
293//-----------------------------------------------------------------------------
295C DGtal::detail::rangeMiddle(const C& cb, const C& ce, CirculatorType, BidirectionalCategory)
297 BOOST_CONCEPT_ASSERT(( boost_concepts::BidirectionalTraversalConcept<C> ));
299 if (isNotEmpty(cb, ce))
321//-----------------------------------------------------------------------------
323I DGtal::detail::rangeMiddle(const I& itb, const I& ite, IteratorType, RandomAccessCategory)
325 BOOST_CONCEPT_ASSERT(( boost_concepts::RandomAccessTraversalConcept<I> ));
326 ASSERT( itb <= ite );
328 return ( itb + (ite-itb)/2 );
331//-----------------------------------------------------------------------------
333C DGtal::detail::rangeMiddle(const C& cb, const C& ce, CirculatorType, RandomAccessCategory)
335 BOOST_CONCEPT_ASSERT(( boost_concepts::RandomAccessTraversalConcept<C> ));
337 typename DGtal::IteratorCirculatorTraits<C>::Difference s
338 = DGtal::detail::rangeSize(cb, ce, CirculatorType(), RandomAccessCategory());
339 return ( cb + (s/2) );
343///////////////////////////////////////////////////////////////////////////////