PPL  1.2
swapping_sort_templates.hh
Go to the documentation of this file.
1 /* Sorting objects for which copies cost more than swaps.
2  Copyright (C) 2001-2010 Roberto Bagnara <bagnara@cs.unipr.it>
3  Copyright (C) 2010-2016 BUGSENG srl (http://bugseng.com)
4 
5 This file is part of the Parma Polyhedra Library (PPL).
6 
7 The PPL is free software; you can redistribute it and/or modify it
8 under the terms of the GNU General Public License as published by the
9 Free Software Foundation; either version 3 of the License, or (at your
10 option) any later version.
11 
12 The PPL is distributed in the hope that it will be useful, but WITHOUT
13 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
15 for more details.
16 
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software Foundation,
19 Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1307, USA.
20 
21 For the most up-to-date information see the Parma Polyhedra Library
22 site: http://bugseng.com/products/ppl/ . */
23 
24 #ifndef PPL_swapping_sort_templates_hh
25 #define PPL_swapping_sort_templates_hh 1
26 
27 #include <vector>
28 #include <algorithm>
29 
30 namespace Parma_Polyhedra_Library {
31 
32 namespace Implementation {
33 
34 template <typename RA_Container, typename Compare>
36  typedef typename RA_Container::size_type size_type;
37 
38  Indirect_Sort_Compare(const RA_Container& cont,
39  size_type base = 0,
40  Compare comp = Compare())
41  : container(cont), base_index(base), compare(comp) {
42  }
43 
44  bool operator()(size_type i, size_type j) const {
45  return compare(container[base_index + i], container[base_index + j]);
46  }
47 
48  const RA_Container& container;
49  const size_type base_index;
50  const Compare compare;
51 }; // struct Indirect_Sort_Compare
52 
53 template <typename RA_Container>
55  typedef typename RA_Container::size_type size_type;
56 
57  Indirect_Unique_Compare(const RA_Container& cont, size_type base = 0)
58  : container(cont), base_index(base) {
59  }
60 
61  bool operator()(size_type i, size_type j) const {
62  return container[base_index + i] == container[base_index + j];
63  }
64 
65  const RA_Container& container;
66  const size_type base_index;
67 }; // struct Indirect_Unique_Compare
68 
69 template <typename RA_Container>
71  typedef typename RA_Container::size_type size_type;
72 
73  Indirect_Swapper(RA_Container& cont, size_type base = 0)
74  : container(cont), base_index(base) {
75  }
76 
77  void operator()(size_type i, size_type j) const {
78  using std::swap;
80  }
81 
82  RA_Container& container;
83  const size_type base_index;
84 }; // struct Indirect_Swapper
85 
86 template <typename RA_Container1, typename RA_Container2>
88  typedef typename RA_Container1::size_type size_type;
89 
90  Indirect_Swapper2(RA_Container1& cont1, RA_Container2& cont2)
91  : container1(cont1), container2(cont2) {
92  }
93 
94  void operator()(size_type i, size_type j) const {
95  using std::swap;
96  swap(container1[i], container1[j]);
97  swap(container2[i], container2[j]);
98  }
99 
100  RA_Container1& container1;
101  RA_Container2& container2;
102 }; // struct Indirect_Swapper2
103 
104 template <typename Sort_Comparer, typename Unique_Comparer, typename Swapper>
105 typename Sort_Comparer::size_type
106 indirect_sort_and_unique(typename Sort_Comparer::size_type num_elems,
107  Sort_Comparer sort_cmp,
108  Unique_Comparer unique_cmp,
109  Swapper indirect_swap) {
110  typedef typename Sort_Comparer::size_type index_type;
111  // `iv' is a vector of indices for the portion of rows to be sorted.
112  PPL_ASSERT(num_elems >= 2);
113  std::vector<index_type> iv;
114  iv.reserve(num_elems);
115  for (index_type i = 0, i_end = num_elems; i != i_end; ++i) {
116  iv.push_back(i);
117  }
118 
119  typedef typename std::vector<index_type>::iterator Iter;
120  const Iter iv_begin = iv.begin();
121  Iter iv_end = iv.end();
122 
123  // Sort `iv' by comparing the rows indexed by its elements.
124  std::sort(iv_begin, iv_end, sort_cmp);
125 
126  // Swap the indexed rows according to `iv':
127  // for each index `i', the element that should be placed in
128  // position dst = i is the one placed in position src = iv[i].
129  for (index_type i = num_elems; i-- > 0; ) {
130  if (i != iv[i]) {
131  index_type dst = i;
132  index_type src = iv[i];
133  do {
134  indirect_swap(src, dst);
135  iv[dst] = dst;
136  dst = src;
137  src = iv[dst];
138  } while (i != src);
139  iv[dst] = dst;
140  }
141  }
142 
143  // Restore `iv' indices to 0 .. num_elems-1 for the call to unique.
144  for (index_type i = num_elems; i-- > 0; ) {
145  iv[i] = i;
146  }
147 
148  // Unique `iv' by comparing the rows indexed by its elements.
149  iv_end = std::unique(iv_begin, iv_end, unique_cmp);
150 
151  const index_type num_sorted = static_cast<index_type>(iv_end - iv_begin);
152  const index_type num_duplicates = num_elems - num_sorted;
153  if (num_duplicates == 0) {
154  return 0;
155  }
156 
157  // There were duplicates: swap the rows according to `iv'.
158  index_type dst = 0;
159  while (dst < num_sorted && dst == iv[dst]) {
160  ++dst;
161  }
162  if (dst == num_sorted) {
163  return num_duplicates;
164  }
165  do {
166  const index_type src = iv[dst];
167  indirect_swap(src, dst);
168  ++dst;
169  }
170  while (dst < num_sorted);
171  return num_duplicates;
172 }
173 
174 template <typename Iter>
175 Iter
176 swapping_unique(Iter first, Iter last) {
177  return swapping_unique(first, last, std::iter_swap<Iter, Iter>);
178 }
179 
180 } // namespace Implementation
181 
182 } // namespace Parma_Polyhedra_Library
183 
184 #endif // !defined(PPL_swapping_sort_templates_hh)
void swap(CO_Tree &x, CO_Tree &y)
Indirect_Unique_Compare(const RA_Container &cont, size_type base=0)
The entire library is confined to this namespace.
Definition: version.hh:61
Indirect_Swapper2(RA_Container1 &cont1, RA_Container2 &cont2)
Sort_Comparer::size_type indirect_sort_and_unique(typename Sort_Comparer::size_type num_elems, Sort_Comparer sort_cmp, Unique_Comparer unique_cmp, Swapper indirect_swap)
Indirect_Sort_Compare(const RA_Container &cont, size_type base=0, Compare comp=Compare())