gravatar
alpar (Alpar Juttner)
alpar@cs.elte.hu
Doc improvements and source unification in radix_sort (#72)
0 2 0
default
2 files changed with 176 insertions and 174 deletions:
↑ Collapse diff ↑
Show white space 6 line context
1
/* -*- C++ -*-
1
/* -*- mode: C++; indent-tabs-mode: nil; -*-
2 2
 *
3
 * This file is a part of LEMON, a generic C++ optimization library
3
 * This file is a part of LEMON, a generic C++ optimization library.
4 4
 *
... ...
@@ -39,3 +39,3 @@
39 39
      const Value& operator()(const Value& val) {
40
	return val;
40
        return val;
41 41
      }
... ...
@@ -45,9 +45,9 @@
45 45
    template <typename Value, typename Iterator, typename Functor>
46
    Iterator radixSortPartition(Iterator first, Iterator last, 
47
				Functor functor, Value mask) {
46
    Iterator radixSortPartition(Iterator first, Iterator last,
47
                                Functor functor, Value mask) {
48 48
      while (first != last && !(functor(*first) & mask)) {
49
	++first;
49
        ++first;
50 50
      }
51 51
      if (first == last) {
52
	return first;
52
        return first;
53 53
      }
... ...
@@ -55,6 +55,6 @@
55 55
      while (first != last && (functor(*last) & mask)) {
56
	--last;
56
        --last;
57 57
      }
58 58
      if (first == last) {
59
	return first;
59
        return first;
60 60
      }
... ...
@@ -63,17 +63,17 @@
63 63
      if (!(first < last)) {
64
	return first;
64
        return first;
65 65
      }
66 66
      while (true) {
67
	while (!(functor(*first) & mask)) {
68
	  ++first;
69
	}
70
	--last;
71
	while (functor(*last) & mask) {
72
	  --last;
73
	}
74
	if (!(first < last)) {
75
	  return first;
76
	}
77
	std::iter_swap(first, last);
78
	++first;
67
        while (!(functor(*first) & mask)) {
68
          ++first;
69
        }
70
        --last;
71
        while (functor(*last) & mask) {
72
          --last;
73
        }
74
        if (!(first < last)) {
75
          return first;
76
        }
77
        std::iter_swap(first, last);
78
        ++first;
79 79
      }
... ...
@@ -82,9 +82,9 @@
82 82
    template <typename Iterator, typename Functor>
83
    Iterator radixSortSignPartition(Iterator first, Iterator last, 
84
				    Functor functor) {
83
    Iterator radixSortSignPartition(Iterator first, Iterator last,
84
                                    Functor functor) {
85 85
      while (first != last && functor(*first) < 0) {
86
	++first;
86
        ++first;
87 87
      }
88 88
      if (first == last) {
89
	return first;
89
        return first;
90 90
      }
... ...
@@ -92,6 +92,6 @@
92 92
      while (first != last && functor(*last) >= 0) {
93
	--last;
93
        --last;
94 94
      }
95 95
      if (first == last) {
96
	return first;
96
        return first;
97 97
      }
... ...
@@ -100,17 +100,17 @@
100 100
      if (!(first < last)) {
101
	return first;
101
        return first;
102 102
      }
103 103
      while (true) {
104
	while (functor(*first) < 0) {
105
	  ++first;
106
	}
107
	--last;
108
	while (functor(*last) >= 0) {
109
	  --last;
110
	}
111
	if (!(first < last)) {
112
	  return first;
113
	}
114
	std::iter_swap(first, last);
115
	++first;
104
        while (functor(*first) < 0) {
105
          ++first;
106
        }
107
        --last;
108
        while (functor(*last) >= 0) {
109
          --last;
110
        }
111
        if (!(first < last)) {
112
          return first;
113
        }
114
        std::iter_swap(first, last);
115
        ++first;
116 116
      }
... ...
@@ -119,9 +119,9 @@
119 119
    template <typename Value, typename Iterator, typename Functor>
120
    void radixIntroSort(Iterator first, Iterator last, 
121
			Functor functor, Value mask) {
120
    void radixIntroSort(Iterator first, Iterator last,
121
                        Functor functor, Value mask) {
122 122
      while (mask != 0 && last - first > 1) {
123
	Iterator cut = radixSortPartition(first, last, functor, mask);
124
	mask >>= 1;
125
	radixIntroSort(first, cut, functor, mask);
126
	first = cut;
123
        Iterator cut = radixSortPartition(first, last, functor, mask);
124
        mask >>= 1;
125
        radixIntroSort(first, cut, functor, mask);
126
        first = cut;
127 127
      }
... ...
@@ -140,6 +140,6 @@
140 140
      for (it = first; it != cut; ++it) {
141
	while ((mask & functor(*it)) != mask) {
142
	  ++max_digit;
143
	  mask <<= 1;
144
	}
141
        while ((mask & functor(*it)) != mask) {
142
          ++max_digit;
143
          mask <<= 1;
144
        }
145 145
      }
... ...
@@ -149,6 +149,6 @@
149 149
      for (it = cut; it != last; ++it) {
150
	while ((mask | functor(*it)) != mask) {
151
	  ++max_digit;
152
	  mask <<= 1; mask |= 1;
153
	}
150
        while ((mask | functor(*it)) != mask) {
151
          ++max_digit;
152
          mask <<= 1; mask |= 1;
153
        }
154 154
      }
... ...
@@ -165,6 +165,6 @@
165 165
      for (it = first; it != last; ++it) {
166
	while ((mask | functor(*it)) != mask) {
167
	  ++max_digit;
168
	  mask <<= 1; mask |= 1;
169
	}
166
        while ((mask | functor(*it)) != mask) {
167
          ++max_digit;
168
          mask <<= 1; mask |= 1;
169
        }
170 170
      }
... ...
@@ -174,4 +174,4 @@
174 174

	
175
    template <typename Value, 
176
	      bool sign = std::numeric_limits<Value>::is_signed >
175
    template <typename Value,
176
              bool sign = std::numeric_limits<Value>::is_signed >
177 177
    struct RadixSortSelector {
... ...
@@ -179,3 +179,3 @@
179 179
      static void sort(Iterator first, Iterator last, Functor functor) {
180
	radixSignedSort<Value>(first, last, functor);
180
        radixSignedSort<Value>(first, last, functor);
181 181
      }
... ...
@@ -187,3 +187,3 @@
187 187
      static void sort(Iterator first, Iterator last, Functor functor) {
188
	radixUnsignedSort<Value>(first, last, functor);
188
        radixUnsignedSort<Value>(first, last, functor);
189 189
      }
... ...
@@ -197,16 +197,17 @@
197 197
  ///
198
  /// The \c radixSort sorts the STL compatible range into ascending
199
  /// order.  The radix sort algorithm can sort the items which mapped
200
  /// to an integer with an adaptable unary function \c functor and the
201
  /// order will be ascending by these mapped values. As function
202
  /// specialization it is possible to use a normal function instead
203
  /// of the functor object or if the functor is not given it will use
204
  /// an identity function instead.
198
  /// The \c radixSort sorts an STL compatible range into ascending
199
  /// order.  The radix sort algorithm can sort items which are mapped
200
  /// to integers with an adaptable unary function \c functor and the
201
  /// order will be ascending according to these mapped values.
205 202
  ///
206
  /// This implemented radix sort is a special quick sort which pivot
207
  /// value is choosen to partite the items on the next
208
  /// bit. Therefore, let be \c c the maximal capacity and \c n the
209
  /// number of the items in the container, the time complexity of the
210
  /// algorithm is \f$ O(\log(c)n) \f$ and the additional space
211
  /// complexity is \f$ O(\log(c)) \f$.
203
  /// It is also possible to use a normal function instead
204
  /// of the functor object. If the functor is not given it will use
205
  /// the identity function instead.
206
  ///
207
  /// This is a special quick sort algorithm where the pivot
208
  /// values to split the items are choosen to be \f$ 2^k \f$ for each \c k.
209
  /// Therefore, the time complexity of the
210
  /// algorithm is \f$ O(\log(c)n) \f$ and it uses \f$ O(\log(c)) \f$,
211
  /// additional space, where \c c is the maximal value and \c n is the
212
  /// number of the items in the container.
212 213
  ///
... ...
@@ -217,2 +218,4 @@
217 218
  /// signed or unsigned.
219
  ///
220
  /// \sa counterSort()
218 221
  template <typename Iterator, typename Functor>
... ...
@@ -263,9 +266,9 @@
263 266
    template <typename Functor, typename Key>
264
    void counterIntroSort(Key *first, Key *last, Key *target, 
265
			  int byte, Functor functor) {
266
      const int size = 
267
	unsigned(std::numeric_limits<unsigned char>::max()) + 1;
267
    void counterIntroSort(Key *first, Key *last, Key *target,
268
                          int byte, Functor functor) {
269
      const int size =
270
        unsigned(std::numeric_limits<unsigned char>::max()) + 1;
268 271
      std::vector<int> counter(size);
269 272
      for (int i = 0; i < size; ++i) {
270
	counter[i] = 0;
273
        counter[i] = 0;
271 274
      }
... ...
@@ -273,4 +276,4 @@
273 276
      while (first != last) {
274
	++counter[valueByte(functor(*first), byte)]; 
275
	++first;
277
        ++counter[valueByte(functor(*first), byte)];
278
        ++first;
276 279
      }
... ...
@@ -278,9 +281,9 @@
278 281
      for (int i = 0; i < size; ++i) {
279
	prev = num;
280
	num += counter[i];
281
	counter[i] = prev;
282
        prev = num;
283
        num += counter[i];
284
        counter[i] = prev;
282 285
      }
283 286
      while (it != last) {
284
	target[counter[valueByte(functor(*it), byte)]++] = *it;
285
	++it;
287
        target[counter[valueByte(functor(*it), byte)]++] = *it;
288
        ++it;
286 289
      }
... ...
@@ -289,9 +292,9 @@
289 292
    template <typename Functor, typename Key>
290
    void signedCounterIntroSort(Key *first, Key *last, Key *target, 
291
				int byte, Functor functor) {
292
      const int size = 
293
	unsigned(std::numeric_limits<unsigned char>::max()) + 1;
293
    void signedCounterIntroSort(Key *first, Key *last, Key *target,
294
                                int byte, Functor functor) {
295
      const int size =
296
        unsigned(std::numeric_limits<unsigned char>::max()) + 1;
294 297
      std::vector<int> counter(size);
295 298
      for (int i = 0; i < size; ++i) {
296
	counter[i] = 0;
299
        counter[i] = 0;
297 300
      }
... ...
@@ -299,4 +302,4 @@
299 302
      while (first != last) {
300
	counter[valueByte(functor(*first), byte)]++;
301
	++first;
303
        counter[valueByte(functor(*first), byte)]++;
304
        ++first;
302 305
      }
... ...
@@ -304,14 +307,14 @@
304 307
      for (int i = size / 2; i < size; ++i) {
305
	prev = num;
306
	num += counter[i];
307
	counter[i] = prev;
308
        prev = num;
309
        num += counter[i];
310
        counter[i] = prev;
308 311
      }
309 312
      for (int i = 0; i < size / 2; ++i) {
310
	prev = num;
311
	num += counter[i];
312
	counter[i] = prev;
313
        prev = num;
314
        num += counter[i];
315
        counter[i] = prev;
313 316
      }
314 317
      while (it != last) {
315
	target[counter[valueByte(functor(*it), byte)]++] = *it;
316
	++it;
318
        target[counter[valueByte(functor(*it), byte)]++] = *it;
319
        ++it;
317 320
      }
... ...
@@ -319,3 +322,3 @@
319 322

	
320
  
323

	
321 324
    template <typename Value, typename Iterator, typename Functor>
... ...
@@ -330,26 +333,26 @@
330 333
      try {
331
	bool dir = true;
332
	std::copy(first, last, buffer);
333
	for (int i = 0; i < int(sizeof(Value)) - 1; ++i) {
334
	  if (dir) {
335
	    counterIntroSort(buffer, buffer + length, buffer + length, 
336
			     i, functor);
337
	  } else {
338
	    counterIntroSort(buffer + length, buffer + 2 * length, buffer, 
339
			     i, functor);
340
	  }
341
	  dir = !dir;
342
	}
343
	if (dir) {
344
	  signedCounterIntroSort(buffer, buffer + length, buffer + length, 
345
				 sizeof(Value) - 1, functor);
346
	  std::copy(buffer + length, buffer + 2 * length, first);
347
	}	else {
348
	  signedCounterIntroSort(buffer + length, buffer + 2 * length, buffer, 
349
				 sizeof(Value) - 1, functor);
350
	  std::copy(buffer, buffer + length, first);
351
	}
334
        bool dir = true;
335
        std::copy(first, last, buffer);
336
        for (int i = 0; i < int(sizeof(Value)) - 1; ++i) {
337
          if (dir) {
338
            counterIntroSort(buffer, buffer + length, buffer + length,
339
                             i, functor);
340
          } else {
341
            counterIntroSort(buffer + length, buffer + 2 * length, buffer,
342
                             i, functor);
343
          }
344
          dir = !dir;
345
        }
346
        if (dir) {
347
          signedCounterIntroSort(buffer, buffer + length, buffer + length,
348
                                 sizeof(Value) - 1, functor);
349
          std::copy(buffer + length, buffer + 2 * length, first);
350
        }        else {
351
          signedCounterIntroSort(buffer + length, buffer + 2 * length, buffer,
352
                                 sizeof(Value) - 1, functor);
353
          std::copy(buffer, buffer + length, first);
354
        }
352 355
      } catch (...) {
353
	allocator.deallocate(buffer, 2 * length);
354
	throw;
356
        allocator.deallocate(buffer, 2 * length);
357
        throw;
355 358
      }
... ...
@@ -368,22 +371,22 @@
368 371
      try {
369
	bool dir = true;
370
	std::copy(first, last, buffer);
371
	for (int i = 0; i < int(sizeof(Value)); ++i) {
372
	  if (dir) {
373
	    counterIntroSort(buffer, buffer + length, 
374
			     buffer + length, i, functor);
375
	  } else {
376
	    counterIntroSort(buffer + length, buffer + 2 * length, 
377
			     buffer, i, functor);
378
	  }
379
	  dir = !dir;
380
	}
381
	if (dir) {
382
	  std::copy(buffer, buffer + length, first);
383
	}	else {
384
	  std::copy(buffer + length, buffer + 2 * length, first);
385
	}
372
        bool dir = true;
373
        std::copy(first, last, buffer);
374
        for (int i = 0; i < int(sizeof(Value)); ++i) {
375
          if (dir) {
376
            counterIntroSort(buffer, buffer + length,
377
                             buffer + length, i, functor);
378
          } else {
379
            counterIntroSort(buffer + length, buffer + 2 * length,
380
                             buffer, i, functor);
381
          }
382
          dir = !dir;
383
        }
384
        if (dir) {
385
          std::copy(buffer, buffer + length, first);
386
        }        else {
387
          std::copy(buffer + length, buffer + 2 * length, first);
388
        }
386 389
      } catch (...) {
387
	allocator.deallocate(buffer, 2 * length);
388
	throw;
390
        allocator.deallocate(buffer, 2 * length);
391
        throw;
389 392
      }
... ...
@@ -394,4 +397,4 @@
394 397

	
395
    template <typename Value, 
396
	      bool sign = std::numeric_limits<Value>::is_signed >
398
    template <typename Value,
399
              bool sign = std::numeric_limits<Value>::is_signed >
397 400
    struct CounterSortSelector {
... ...
@@ -399,3 +402,3 @@
399 402
      static void sort(Iterator first, Iterator last, Functor functor) {
400
	counterSignedSort<Value>(first, last, functor);
403
        counterSignedSort<Value>(first, last, functor);
401 404
      }
... ...
@@ -407,3 +410,3 @@
407 410
      static void sort(Iterator first, Iterator last, Functor functor) {
408
	counterUnsignedSort<Value>(first, last, functor);
411
        counterUnsignedSort<Value>(first, last, functor);
409 412
      }
... ...
@@ -415,25 +418,23 @@
415 418
  ///
416
  /// \brief Sorts stable the STL compatible range into ascending order.
419
  /// \brief Sorts the STL compatible range into ascending order in a stable
420
  /// way.
417 421
  ///
418
  /// The \c counterSort sorts the STL compatible range into ascending
419
  /// order.  The counter sort algorithm can sort the items which
420
  /// mapped to an integer with an adaptable unary function \c functor
421
  /// and the order will be ascending by these mapped values. As
422
  /// function specialization it is possible to use a normal function
423
  /// instead of the functor object or if the functor is not given it
424
  /// will use an identity function instead.
422
  /// This function sorts an STL compatible range into ascending
423
  /// order according to an integer mapping in the same as radixSort() does.
425 424
  ///
426
  /// The implemented counter sort use a radix forward sort on the
425
  /// This sorting algorithm is stable, i.e. the order of two equal
426
  /// element remains the same after the sorting.
427
  ///
428
  /// This sort algorithm  use a radix forward sort on the
427 429
  /// bytes of the integer number. The algorithm sorts the items
428
  /// byte-by-byte, first it counts how many times occurs a byte value
429
  /// in the containerm, and with the occurence number the container
430
  /// can be copied to an other in asceding order in \c O(n) time.
431
  /// Let be \c c the maximal capacity of the integer type and \c n
432
  /// the number of the items in the container, the time complexity of
433
  /// the algorithm is \f$ O(\log(c)n) \f$ and the additional space
434
  /// complexity is \f$ O(n) \f$.
430
  /// byte-by-byte. First, it counts how many times a byte value occurs
431
  /// in the container, then it copies the corresponding items to
432
  /// another container in asceding order in \c O(n) time.
435 433
  ///
436
  /// The sorting algorithm is stable, i.e. the order of two equal
437
  /// element remains the same.
434
  /// The time complexity of the algorithm is \f$ O(\log(c)n) \f$ and
435
  /// it uses \f$ O(n) \f$, additional space, where \c c is the
436
  /// maximal value and \c n is the number of the items in the
437
  /// container.
438 438
  ///
439

	
439 440
  /// \param first The begin of the given range.
... ...
@@ -443,2 +444,3 @@
443 444
  /// signed or unsigned.
445
  /// \sa radixSort()
444 446
  template <typename Iterator, typename Functor>
Ignore white space 6 line context
1
/* -*- C++ -*-
1
/* -*- mode: C++; indent-tabs-mode: nil; -*-
2 2
 *
3
 * This file is a part of LEMON, a generic C++ optimization library
3
 * This file is a part of LEMON, a generic C++ optimization library.
4 4
 *
... ...
@@ -83,4 +83,4 @@
83 83

	
84
  } 
85
  
84
  }
85

	
86 86
  {
... ...
@@ -123,3 +123,3 @@
123 123
    }
124
  } 
124
  }
125 125

	
... ...
@@ -142,3 +142,3 @@
142 142

	
143
  checkRadixSort();  
143
  checkRadixSort();
144 144
  checkCounterSort();
0 comments (0 inline)