Spatial C++ Library
Generic Multi-Dimensional Containers and Spatial Operations
spatial_equal.hpp
1 // -*- C++ -*-
2 //
3 // Copyright Sylvain Bougerel 2009 - 2013.
4 // Distributed under the Boost Software License, Version 1.0.
5 // (See accompanying file COPYING or copy at
6 // http://www.boost.org/LICENSE_1_0.txt)
7 
15 #ifndef SPATIAL_EQUAL_HPP
16 #define SPATIAL_EQUAL_HPP
17 
18 #include "spatial_bidirectional.hpp"
19 #include "../traits.hpp"
20 #include "spatial_rank.hpp"
21 #include "spatial_except.hpp"
22 #include "spatial_compress.hpp"
23 #include "spatial_preorder.hpp"
24 
25 namespace spatial
26 {
27  namespace details
28  {
29  template <typename Container>
30  struct Equal : private Container::key_compare // empty member optimization
31  {
32  Equal() { }
33 
34  Equal(const typename Container::key_compare& cmp,
35  const typename Container::key_type& value_)
36  : Container::key_compare(cmp), value(value_) { }
37 
38  typename Container::key_compare key_comp() const
39  { return *static_cast<const typename Container::key_compare*>(this); }
40 
41  typename Container::key_type value;
42  };
43 
44  template <typename Container>
45  inline bool
46  right_traversal(typename Container::mode_type::const_node_ptr node,
47  dimension_type dim,
48  const Equal<Container>& equal)
49  {
50  return !equal.key_comp()(dim, equal.value, const_key(node));
51  }
52 
67  template <typename Container>
68  inline bool
69  stop_traversal(typename Container::mode_type::const_node_ptr node,
70  typename Container::rank_type rank,
71  const Equal<Container>& equal)
72  {
73  dimension_type i = 0;
74  for (; i < rank()
75  && !equal.key_comp()(i, const_key(node), equal.value)
76  && !equal.key_comp()(i, equal.value, const_key(node));
77  ++i) { }
78  return (i == rank());
79  }
80 
81  template <typename Container>
82  inline bool
83  left_traversal(typename Container::mode_type::const_node_ptr node,
84  dimension_type dim,
85  const Equal<Container>& equal,
87  {
88  return !equal.key_comp()(dim, const_key(node), equal.value);
89  }
90 
91  template <typename Container>
92  inline bool
93  left_traversal(typename Container::mode_type::const_node_ptr node,
94  dimension_type dim,
95  const Equal<Container>& equal,
97  {
98  return equal.key_comp()(dim, equal.value, const_key(node));
99  }
100 
101  template <typename Container>
102  inline bool
103  left_traversal(typename Container::mode_type::const_node_ptr node,
104  dimension_type dim,
105  const Equal<Container>& equal)
106  {
107  return left_traversal
108  (node, dim, equal,
109  typename Container::mode_type::invariant_category());
110  }
111 
112  } // namespace details
113 
122  template <typename Container>
125  <typename container_traits<Container>::mode_type,
126  typename container_traits<Container>::rank_type>
127  {
128  private:
130  typedef typename details::Bidirectional_iterator
133 
134  public:
135  using Base::node;
136  using Base::node_dim;
137  using Base::rank;
138 
141 
144 
147 
161  equal_iterator(Container& container, const key_type& value_,
163  : Base(container.rank(), iter.node, modulo(iter.node, container.rank())),
164  _query(container.key_comp(), value_) { }
165 
185  (Container& container, const key_type& value_, dimension_type dim,
187  : Base(container.rank(), ptr, dim), _query(container.key_comp(), value_)
188  { }
189 
193  {
194  details::assign(node, node_dim,
195  preorder_increment(node, node_dim, rank(), _query));
196  return *this;
197  }
198 
202  {
203  equal_iterator<Container> x(*this);
204  details::assign(node, node_dim,
205  preorder_increment(node, node_dim, rank(), _query));
206  return x;
207  }
208 
212  {
213  details::assign(node, node_dim,
214  preorder_decrement(node, node_dim, rank(), _query));
215  return *this;
216  }
217 
221  {
222  equal_iterator<Container> x(*this);
223  details::assign(node, node_dim,
224  preorder_decrement(node, node_dim, rank(), _query));
225  return x;
226  }
227 
229  key_type value() const { return _query.value; }
230 
232  key_compare key_comp() const { return _query.key_comp(); }
233 
234  private:
237  };
238 
248  template <typename Container>
249  class equal_iterator<const Container>
251  <typename container_traits<Container>::mode_type,
252  typename container_traits<Container>::rank_type>
253  {
254  private:
257  <typename container_traits<Container>::mode_type,
259 
260  public:
261  using Base::node;
262  using Base::node_dim;
263  using Base::rank;
264 
267 
270 
273 
287  equal_iterator(const Container& container, const key_type& value_,
289  : Base(container.rank(), iter.node, modulo(iter.node, container.rank())),
290  _query(container.key_comp(), value_) { }
291 
308  (const Container& container, const key_type& value_, dimension_type dim,
310  : Base(container.rank(), ptr, dim), _query(container.key_comp(), value_)
311  { }
312 
315  : Base(iter.rank(), iter.node, iter.node_dim),
316  _query(iter.key_comp(), iter.value()) { }
317 
321  {
322  details::assign(node, node_dim,
323  preorder_increment(node, node_dim, rank(), _query));
324  return *this;
325  }
326 
330  {
332  details::assign(node, node_dim,
333  preorder_increment(node, node_dim, rank(), _query));
334  return x;
335  }
336 
340  {
341  details::assign(node, node_dim,
342  preorder_decrement(node, node_dim, rank(), _query));
343  return *this;
344  }
345 
349  {
351  details::assign(node, node_dim,
352  preorder_decrement(node, node_dim, rank(), _query));
353  return x;
354  }
355 
357  key_type value() const { return _query.value; }
358 
360  key_compare key_comp() const { return _query.key_comp(); }
361 
362  private:
365  };
366 
367  template <typename Container>
369  equal_end(Container& container,
370  const typename equal_iterator<Container>::key_type& value)
371  {
373  (container, value, container.dimension() - 1,
374  container.end().node); // At header, dim = rank - 1
375  }
376 
377  template <typename Container>
378  inline equal_iterator<const Container>
379  equal_cend(const Container& container,
380  const typename equal_iterator<Container>::key_type& value)
381  { return equal_end(container, value); }
382 
392  template <typename Container>
394  inline equal_iterator<Container>
395  equal_begin(Container& container,
396  const typename equal_iterator<Container>::key_type& value)
397  {
398  if (container.empty()) return equal_end(container, value);
400  = container.end().node->parent;
401  dimension_type dim;
402  details::assign(node, dim,
403  first_equal(node, 0, container.rank(),
404  container.key_comp(), value));
405  return equal_iterator<Container>(container, value, dim, node);
406  }
407 
408  template <typename Container>
409  inline equal_iterator<const Container>
410  equal_cbegin(const Container& container,
411  const typename equal_iterator<Container>::key_type& value)
412  { return equal_begin(container, value); }
414 
415  namespace details
416  {
417  template <typename NodePtr, typename Rank, typename KeyCompare, typename Key>
418  inline std::pair<NodePtr, dimension_type>
419  first_equal(NodePtr node, dimension_type dim, Rank rank,
420  KeyCompare key_comp, const Key& key)
421  {
422  // Write in pre-order fashion
423  NodePtr end = node->parent;
424  dimension_type end_dim = decr_dim(rank, dim);
425  for (;;)
426  {
427  // Test coordinates of node's key, retain results for dim
428  bool walk_left = !key_comp(dim, const_key(node), key);
429  bool walk_right = !key_comp(dim, key, const_key(node));
430  if (walk_left && walk_right)
431  {
432  dimension_type test = 0;
433  for (; test < dim && !(key_comp(test, key, const_key(node))
434  || key_comp(test, const_key(node), key)); ++test);
435  if (test == dim)
436  {
437  test = dim + 1;
438  for (; test < rank() && !(key_comp(test, key, const_key(node))
439  || key_comp(test, const_key(node), key)); ++test);
440  if (test == rank())
441  { return std::make_pair(node, dim); }
442  }
443  }
444  // Walk the tree to find an equal target
445  if (walk_left && node->left != 0)
446  {
447  if (walk_right && node->right != 0)
448  {
449  // Go recursively in this case only, left first
450  NodePtr other;
451  dimension_type other_dim;
452  assign(other, other_dim,
453  first_equal(node->left, incr_dim(rank, dim),
454  rank, key_comp, key));
455  if (other != node)
456  { return std::make_pair(other, other_dim); }
457  else
458  { node = node->right; dim = incr_dim(rank, dim); }
459  }
460  else
461  { node = node->left; dim = incr_dim(rank, dim); }
462  }
463  else if (walk_right && node->right != 0)
464  { node = node->right; dim = incr_dim(rank, dim); }
465  else { return std::make_pair(end, end_dim); }
466  }
467  }
468 
469  } // namespace details
470 } // namespace spatial
471 
472 #endif // SPATIAL_EQUAL_HPP
equal_iterator(const Container &container, const key_type &value_, typename container_traits< Container >::const_iterator iter)
Build an equal iterator from a container's iterator type.
bool stop_traversal(typename Container::mode_type::const_node_ptr node, typename Container::rank_type rank, const Equal< Container > &equal)
Return a boolean indicating whether all of x's coordinates are equal to y's coordinates.
std::pair< NodePtr, dimension_type > first_equal(NodePtr node, dimension_type dim, Rank rank, KeyCompare key_comp, const Key &key)
equal_iterator()
Constructs an empty, uninitialized object.
const rank_type & rank() const
Return the current Rank type used by the iterator.
bool right_traversal(typename Container::mode_type::const_node_ptr node, dimension_type dim, const Equal< Container > &equal)
node_ptr node
The pointer to the current node.
equal_iterator< const Container > & operator--()
Decrements the iterator and returns the decremented value.
Tp::key_compare key_compare
Comparison functor used to compare two instances of key_type.
Definition: traits.hpp:98
equal_iterator< Container > operator++(int)
Increments the iterator but returns the value of the iterator before the increment.
details::Equal< Container > _query
The model key used to find equal keys in the container.
Container::key_compare key_comp() const
key_compare key_comp() const
Returns the functor used to compare keys in this iterator.
This type provides an iterator to iterate through all elements of a container that match a given key...
This type provides an iterator to iterate through all elements of a container that match a given key...
Tp::iterator iterator
The type used to iterate a container.
Definition: traits.hpp:117
Tp::key_type key_type
The type representing the key managed by the container.
Definition: traits.hpp:48
const Kdtree_link< Value, Value >::key_type & const_key(const Node< Kdtree_link< Value, Value > > *node)
This function converts a pointer on a node into a key for a Kdtree_link type.
dimension_type node_dim
The dimension of the current node.
container_traits< Container >::key_compare key_compare
The comparison functor used to compare keys.
Container::key_type value
details::Equal< Container > _query
The model key used to find equal keys in the container.
equal_iterator()
Constructs an empty, uninitialized object.
equal_iterator< const Container > operator++(int)
Increments the iterator but returns the value of the iterator before the increment.
equal_iterator< Container > & operator--()
Decrements the iterator and returns the decremented value.
Equal(const typename Container::key_compare &cmp, const typename Container::key_type &value_)
Tp::const_iterator const_iterator
The type used to iterate a constant container.
Definition: traits.hpp:123
key_compare key_comp() const
Return the functor used to compare keys in this iterator.
The traits type for all containers in the spatial namespace.
Definition: traits.hpp:42
Tp::mode_type mode_type
The Link Mode type that is associated with the container.
Definition: traits.hpp:82
std::size_t dimension_type
Defines the type for the dimension as being a size.
Definition: spatial.hpp:71
equal_iterator(const equal_iterator< Container > &iter)
Convertion of an iterator into a const_iterator is permitted.
Tp::rank_type rank_type
The type used to represent the rank of the container.
Definition: traits.hpp:111
container_traits< Container >::key_compare key_compare
The comparison functor used to compare keys.
details::Bidirectional_iterator< typename container_traits< Container >::mode_type, typename container_traits< Container >::rank_type > Base
The preorder iterator without its criterion.
The category of invariants for a k-d tree node: strict or relaxed.
equal_iterator< Container > & operator++()
Increments the iterator and returns the incremented value.
void assign(Type1 &first, Type2 &second, const std::pair< Type1, Type2 > &pair)
key_type value() const
Return the value of key used to find equal keys in the container.
The main namespace used in the library.
Definition: algorithm.hpp:23
dimension_type decr_dim(Rank rank, dimension_type node_dim)
Decrement dimension node_dim, given rank.
equal_iterator(Container &container, const key_type &value_, typename container_traits< Container >::iterator iter)
Build an equal iterator from a container's iterator type.
equal_iterator< const Container > operator--(int)
Decrements the iterator but returns the value of the iterator before the decrement.
equal_iterator< const Container > equal_cbegin(const Container &container, const typename equal_iterator< Container >::key_type &value)
Find the first element in container that compares equally to value, using container's key_compare com...
equal_iterator< Container > equal_end(Container &container, const typename equal_iterator< Container >::key_type &value)
equal_iterator< const Container > equal_cend(const Container &container, const typename equal_iterator< Container >::key_type &value)
A common template for constant bidirectional iterators that work on identical modes of linking...
A common template for bidirectional iterators that work on identical modes of linking.
equal_iterator< const Container > & operator++()
Increments the iterator and returns the incremented value.
details::Const_bidirectional_iterator< typename container_traits< Container >::mode_type, typename container_traits< Container >::rank_type > Base
The preorder iterator without its criterion.
container_traits< Container >::key_type key_type
The type used to store the model key to be looked up in the container.
equal_iterator< Container > operator--(int)
Decrements the iterator but returns the value of the iterator before the decrement.
equal_iterator< Container > equal_begin(Container &container, const typename equal_iterator< Container >::key_type &value)
Find the first element in container that compares equally to value, using container's key_compare com...
container_traits< Container >::key_type key_type
The type used to store the model key to be looked up in the container.
dimension_type incr_dim(Rank rank, dimension_type node_dim)
Increment dimension node_dim, given rank.
bool left_traversal(typename Container::mode_type::const_node_ptr node, dimension_type dim, const Equal< Container > &equal, relaxed_invariant_tag)
key_type value() const
Returns the value used to find equivalent keys in the container.