lemon/radix_sort.h
author deba
Tue, 04 Dec 2007 14:08:27 +0000
changeset 2531 426a4e35e167
parent 2478 bf783151bc92
child 2553 bfced05fa852
permissions -rw-r--r--
rename graphs script
deba@1833
     1
/* -*- C++ -*-
deba@1833
     2
 *
alpar@1956
     3
 * This file is a part of LEMON, a generic C++ optimization library
alpar@1956
     4
 *
alpar@2391
     5
 * Copyright (C) 2003-2007
alpar@1956
     6
 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
deba@1833
     7
 * (Egervary Research Group on Combinatorial Optimization, EGRES).
deba@1833
     8
 *
deba@1833
     9
 * Permission to use, modify and distribute this software is granted
deba@1833
    10
 * provided that this copyright notice appears in all copies. For
deba@1833
    11
 * precise terms see the accompanying LICENSE file.
deba@1833
    12
 *
deba@1833
    13
 * This software is provided "AS IS" with no warranty of any kind,
deba@1833
    14
 * express or implied, and with no claim as to its suitability for any
deba@1833
    15
 * purpose.
deba@1833
    16
 *
deba@1833
    17
 */
deba@1833
    18
deba@1833
    19
#ifndef RADIX_SORT_H
deba@1833
    20
#define RADIX_SORT_H
deba@1833
    21
deba@2084
    22
/// \ingroup auxalg
deba@1833
    23
/// \file
deba@1833
    24
/// \brief Radix sort
deba@1833
    25
///
deba@1833
    26
deba@1833
    27
#include <vector>
deba@1833
    28
#include <limits>
deba@1833
    29
#include <iterator>
deba@1833
    30
#include <algorithm>
deba@1833
    31
deba@1833
    32
#include <lemon/error.h>
deba@1833
    33
deba@1833
    34
namespace lemon {
deba@1833
    35
deba@1833
    36
  namespace _radix_sort_bits {
deba@1833
    37
deba@1833
    38
    template <typename Value>
deba@1833
    39
    struct Identity {
deba@1833
    40
      const Value& operator()(const Value& val) {
deba@1833
    41
	return val;
deba@1833
    42
      }
deba@1833
    43
    };
deba@1833
    44
deba@1833
    45
  }
deba@1833
    46
deba@1833
    47
  template <typename Value, typename Iterator, typename Functor>
deba@1833
    48
  Iterator radixSortPartition(Iterator first, Iterator last, 
deba@1833
    49
			      Functor functor, Value mask) {
deba@1833
    50
    while (first != last && !(functor(*first) & mask)) {
deba@1833
    51
      ++first;
deba@1833
    52
    }
deba@1833
    53
    if (first == last) {
deba@1833
    54
      return first;
deba@1833
    55
    }
deba@1833
    56
    --last;
deba@1833
    57
    while (first != last && (functor(*last) & mask)) {
deba@1833
    58
      --last;
deba@1833
    59
    }
deba@1833
    60
    if (first == last) {
deba@1833
    61
      return first;
deba@1833
    62
    }
deba@1833
    63
    std::iter_swap(first, last);
deba@1833
    64
    ++first;
deba@1833
    65
    if (!(first < last)) {
deba@1833
    66
      return first;
deba@1833
    67
    }
deba@1833
    68
    while (true) {
deba@1833
    69
      while (!(functor(*first) & mask)) {
deba@1833
    70
	++first;
deba@1833
    71
      }
deba@1833
    72
      --last;
deba@1833
    73
      while (functor(*last) & mask) {
deba@1833
    74
	--last;
deba@1833
    75
      }
deba@1833
    76
      if (!(first < last)) {
deba@1833
    77
	return first;
deba@1833
    78
      }
deba@1833
    79
      std::iter_swap(first, last);
deba@1833
    80
      ++first;
deba@1833
    81
    }
deba@1833
    82
  }
deba@1833
    83
deba@1833
    84
  template <typename Iterator, typename Functor>
deba@1833
    85
  Iterator radixSortSignPartition(Iterator first, Iterator last, 
deba@1833
    86
				  Functor functor) {
deba@1833
    87
    while (first != last && functor(*first) < 0) {
deba@1833
    88
      ++first;
deba@1833
    89
    }
deba@1833
    90
    if (first == last) {
deba@1833
    91
      return first;
deba@1833
    92
    }
deba@1833
    93
    --last;
deba@1833
    94
    while (first != last && functor(*last) >= 0) {
deba@1833
    95
      --last;
deba@1833
    96
    }
deba@1833
    97
    if (first == last) {
deba@1833
    98
      return first;
deba@1833
    99
    }
deba@1833
   100
    std::iter_swap(first, last);
deba@1833
   101
    ++first;
deba@1833
   102
    if (!(first < last)) {
deba@1833
   103
      return first;
deba@1833
   104
    }
deba@1833
   105
    while (true) {
deba@1833
   106
      while (functor(*first) < 0) {
deba@1833
   107
	++first;
deba@1833
   108
      }
deba@1833
   109
      --last;
deba@1833
   110
      while (functor(*last) >= 0) {
deba@1833
   111
	--last;
deba@1833
   112
      }
deba@1833
   113
      if (!(first < last)) {
deba@1833
   114
	return first;
deba@1833
   115
      }
deba@1833
   116
      std::iter_swap(first, last);
deba@1833
   117
      ++first;
deba@1833
   118
    }
deba@1833
   119
  }
deba@1833
   120
deba@1833
   121
  template <typename Value, typename Iterator, typename Functor>
deba@1833
   122
  void radixIntroSort(Iterator first, Iterator last, 
deba@1833
   123
		      Functor functor, Value mask) {
deba@1833
   124
    while (mask != 0 && last - first > 1) {
deba@1833
   125
      Iterator cut = radixSortPartition(first, last, functor, mask);
deba@1833
   126
      mask >>= 1;
deba@1833
   127
      radixIntroSort(first, cut, functor, mask);
deba@1833
   128
      first = cut;
deba@1833
   129
    }
deba@1833
   130
  }
deba@1833
   131
deba@1833
   132
  template <typename Value, typename Iterator, typename Functor>
deba@1833
   133
  void radixSignedSort(Iterator first, Iterator last, Functor functor) {
deba@1833
   134
    Iterator cut = radixSortSignPartition(first, last, functor);
deba@1833
   135
deba@1833
   136
    Value mask;
deba@1833
   137
    int max_digit;
deba@1833
   138
    Iterator it;
deba@1833
   139
deba@2479
   140
    mask = ~0; max_digit = 0;
deba@1833
   141
    for (it = first; it != cut; ++it) {
deba@2479
   142
      while ((mask & functor(*it)) != mask) {
deba@1833
   143
	++max_digit;
deba@2479
   144
	mask <<= 1;
deba@1833
   145
      }
deba@1833
   146
    }
deba@1833
   147
    radixIntroSort(first, cut, functor, 1 << max_digit);
deba@1833
   148
deba@2479
   149
    mask = 0; max_digit = 0;
deba@1833
   150
    for (it = cut; it != last; ++it) {
deba@2479
   151
      while ((mask | functor(*it)) != mask) {
deba@1833
   152
	++max_digit;
deba@2479
   153
	mask <<= 1; mask |= 1;
deba@1833
   154
      }
deba@1833
   155
    }
deba@1833
   156
    radixIntroSort(cut, last, functor, 1 << max_digit);
deba@1833
   157
  }
deba@1833
   158
deba@1833
   159
  template <typename Value, typename Iterator, typename Functor>
deba@1833
   160
  void radixUnsignedSort(Iterator first, Iterator last, Functor functor) {
deba@1833
   161
deba@2479
   162
    Value mask = 0;
deba@1833
   163
    int max_digit = 0;
deba@1833
   164
deba@1833
   165
    Iterator it;
deba@1833
   166
    for (it = first; it != last; ++it) {
deba@2479
   167
      while ((mask | functor(*it)) != mask) {
deba@1833
   168
	++max_digit;
deba@2479
   169
	mask <<= 1; mask |= 1;
deba@1833
   170
      }
deba@1833
   171
    }
deba@1833
   172
    radixIntroSort(first, last, functor, 1 << max_digit);
deba@1833
   173
  }
deba@1833
   174
deba@1833
   175
  namespace _radix_sort_bits {
deba@1833
   176
deba@1833
   177
    template <typename Value, 
deba@1833
   178
	      bool sign = std::numeric_limits<Value>::is_signed >
deba@1833
   179
    struct RadixSortSelector {
deba@1833
   180
      template <typename Iterator, typename Functor>
deba@1833
   181
      static void sort(Iterator first, Iterator last, Functor functor) {
deba@1833
   182
	radixSignedSort<Value>(first, last, functor);
deba@1833
   183
      }
deba@1833
   184
    };
deba@1833
   185
deba@1833
   186
    template <typename Value>
deba@1833
   187
    struct RadixSortSelector<Value, false> {
deba@1833
   188
      template <typename Iterator, typename Functor>
deba@1833
   189
      static void sort(Iterator first, Iterator last, Functor functor) {
deba@1833
   190
	radixUnsignedSort<Value>(first, last, functor);
deba@1833
   191
      }
deba@1833
   192
    };
deba@1833
   193
deba@1833
   194
  }
deba@1833
   195
deba@2084
   196
  /// \ingroup auxalg
deba@1833
   197
  ///
deba@1833
   198
  /// \brief Sorts the stl compatible range into ascending order.
deba@1833
   199
  ///
deba@1833
   200
  /// The \c radixSort sorts the stl compatible range into ascending order.
deba@1833
   201
  /// The radix sort algorithm can sort the items which mapped to an
deba@1833
   202
  /// integer by the adaptable unary function \c functor and the order
deba@1833
   203
  /// will be ascending by these mapped values. As function specialization
deba@1833
   204
  /// there is possible to use a normal function as the functor object
deba@1833
   205
  /// or if the functor is not given it will use an identity function instead.
deba@1833
   206
  ///
deba@1833
   207
  /// This implemented radix sort is a special quick sort which pivot value
deba@1833
   208
  /// is choosen to partite the items on the next bit. This way, let be
deba@1833
   209
  /// \c c the maximal capacity and \c n the number of the items in
deba@2042
   210
  /// the container, the time complexity of the algorithm 
deba@2042
   211
  /// \f$ O(\log(c)n) \f$ and the additional space complexity is 
deba@2042
   212
  /// \f$ O(\log(c)) \f$.
deba@1833
   213
  ///
deba@1833
   214
  /// \param first The begin of the given range.
deba@1833
   215
  /// \param last The end of the given range.
deba@1833
   216
  /// \param functor An adaptible unary function or a normal function which
deba@1833
   217
  /// maps the items to any integer type which can be wheter signed or 
deba@1833
   218
  /// unsigned.
deba@1833
   219
  template <typename Iterator, typename Functor>
deba@1833
   220
  void radixSort(Iterator first, Iterator last, Functor functor) {
deba@1833
   221
    using namespace _radix_sort_bits;
deba@1833
   222
    typedef typename Functor::result_type Value;
deba@1833
   223
    RadixSortSelector<Value>::sort(first, last, functor);
deba@1833
   224
  }
deba@1833
   225
deba@1833
   226
  template <typename Iterator, typename Value, typename Key>
deba@1833
   227
  void radixSort(Iterator first, Iterator last, Value (*functor)(Key)) {
deba@1833
   228
    using namespace _radix_sort_bits;
deba@1833
   229
    RadixSortSelector<Value>::sort(first, last, functor);
deba@1833
   230
  }
deba@1833
   231
deba@1833
   232
  template <typename Iterator, typename Value, typename Key>
deba@1833
   233
  void radixSort(Iterator first, Iterator last, Value& (*functor)(Key)) {
deba@1833
   234
    using namespace _radix_sort_bits;
deba@1833
   235
    RadixSortSelector<Value>::sort(first, last, functor);
deba@1833
   236
  }
deba@1833
   237
deba@1833
   238
  template <typename Iterator, typename Value, typename Key>
deba@1833
   239
  void radixSort(Iterator first, Iterator last, Value (*functor)(Key&)) {
deba@1833
   240
    using namespace _radix_sort_bits;
deba@1833
   241
    RadixSortSelector<Value>::sort(first, last, functor);
deba@1833
   242
  }
deba@1833
   243
deba@1833
   244
  template <typename Iterator, typename Value, typename Key>
deba@1833
   245
  void radixSort(Iterator first, Iterator last, Value& (*functor)(Key&)) {
deba@1833
   246
    using namespace _radix_sort_bits;
deba@1833
   247
    RadixSortSelector<Value>::sort(first, last, functor);
deba@1833
   248
  }
deba@1833
   249
deba@1833
   250
  template <typename Iterator>
deba@1833
   251
  void radixSort(Iterator first, Iterator last) {
deba@1833
   252
    using namespace _radix_sort_bits;
deba@1833
   253
    typedef typename std::iterator_traits<Iterator>::value_type Value;
deba@1833
   254
    RadixSortSelector<Value>::sort(first, last, Identity<Value>());
deba@1833
   255
  }
deba@1833
   256
deba@1833
   257
  template <typename Value>
deba@1833
   258
  unsigned char valueByte(Value value, int byte) {
deba@1844
   259
    return value >> (std::numeric_limits<unsigned char>::digits * byte);
deba@1833
   260
  }
deba@1833
   261
deba@1833
   262
  template <typename Functor, typename Key>
deba@1833
   263
  void counterIntroSort(Key *first, Key *last, Key *target, 
deba@1833
   264
		       int byte, Functor functor) {
deba@1833
   265
    const int size = 
deba@2386
   266
      unsigned(std::numeric_limits<unsigned char>::max()) + 1;
deba@1979
   267
    std::vector<int> counter(size);
deba@1833
   268
    for (int i = 0; i < size; ++i) {
deba@1833
   269
      counter[i] = 0;
deba@1833
   270
    }
deba@1833
   271
    Key *it = first;
deba@1833
   272
    while (first != last) {
deba@1833
   273
      ++counter[valueByte(functor(*first), byte)]; 
deba@1833
   274
      ++first;
deba@1833
   275
    }
deba@1833
   276
    int prev, num = 0;
deba@1833
   277
    for (int i = 0; i < size; ++i) {
deba@1833
   278
      prev = num;
deba@1833
   279
      num += counter[i];
deba@1833
   280
      counter[i] = prev;
deba@1833
   281
    }
deba@1833
   282
    while (it != last) {
deba@1833
   283
      target[counter[valueByte(functor(*it), byte)]++] = *it;
deba@1833
   284
      ++it;
deba@1833
   285
    }
deba@1833
   286
  }
deba@1833
   287
deba@1833
   288
  template <typename Functor, typename Key>
deba@1833
   289
  void signedCounterIntroSort(Key *first, Key *last, Key *target, 
deba@1833
   290
			     int byte, Functor functor) {
deba@1833
   291
    const int size = 
deba@2386
   292
      unsigned(std::numeric_limits<unsigned char>::max()) + 1;
deba@1979
   293
    std::vector<int> counter(size);
deba@1833
   294
    for (int i = 0; i < size; ++i) {
deba@1833
   295
      counter[i] = 0;
deba@1833
   296
    }
deba@1833
   297
    Key *it = first;
deba@1833
   298
    while (first != last) {
deba@1833
   299
      counter[valueByte(functor(*first), byte)]++;
deba@1833
   300
      ++first;
deba@1833
   301
    }
deba@1833
   302
    int prev, num = 0;
deba@1833
   303
    for (int i = size / 2; i < size; ++i) {
deba@1833
   304
      prev = num;
deba@1833
   305
      num += counter[i];
deba@1833
   306
      counter[i] = prev;
deba@1833
   307
    }
deba@1833
   308
    for (int i = 0; i < size / 2; ++i) {
deba@1833
   309
      prev = num;
deba@1833
   310
      num += counter[i];
deba@1833
   311
      counter[i] = prev;
deba@1833
   312
    }
deba@1833
   313
    while (it != last) {
deba@1833
   314
      target[counter[valueByte(functor(*it), byte)]++] = *it;
deba@1833
   315
      ++it;
deba@1833
   316
    }
deba@1833
   317
  }
deba@1833
   318
deba@1833
   319
  
deba@1833
   320
  template <typename Value, typename Iterator, typename Functor>
deba@1833
   321
  void counterSignedSort(Iterator first, Iterator last, Functor functor) {
deba@1904
   322
    if (first == last) return;
deba@1833
   323
    typedef typename std::iterator_traits<Iterator>::value_type Key;
deba@1833
   324
    typedef std::allocator<Key> Allocator;
deba@1833
   325
    Allocator allocator;
deba@1833
   326
deba@1833
   327
    int length = std::distance(first, last);
deba@2033
   328
    Key* buffer = allocator.allocate(2 * length);
deba@1833
   329
    try {
deba@1833
   330
      bool dir = true;
deba@1833
   331
      std::copy(first, last, buffer);
deba@2386
   332
      for (int i = 0; i < int(sizeof(Value)) - 1; ++i) {
deba@1833
   333
	if (dir) {
deba@1833
   334
	  counterIntroSort(buffer, buffer + length, buffer + length, 
deba@1833
   335
			   i, functor);
deba@1833
   336
	} else {
deba@1833
   337
	  counterIntroSort(buffer + length, buffer + 2 * length, buffer, 
deba@1833
   338
			   i, functor);
deba@1833
   339
	}
deba@1833
   340
	dir = !dir;
deba@1833
   341
      }
deba@1833
   342
      if (dir) {
deba@1833
   343
	signedCounterIntroSort(buffer, buffer + length, buffer + length, 
deba@1833
   344
			       sizeof(Value) - 1, functor);
deba@1833
   345
	std::copy(buffer + length, buffer + 2 * length, first);
deba@1833
   346
      }	else {
deba@1833
   347
	signedCounterIntroSort(buffer + length, buffer + 2 * length, buffer, 
deba@1833
   348
			       sizeof(Value) - 1, functor);
deba@1833
   349
	std::copy(buffer, buffer + length, first);
deba@1833
   350
      }
deba@1833
   351
    } catch (...) {
deba@1833
   352
      allocator.deallocate(buffer, 2 * length);
deba@1833
   353
      throw;
deba@1833
   354
    }
deba@1833
   355
    allocator.deallocate(buffer, 2 * length);
deba@1833
   356
  }
deba@1833
   357
deba@1833
   358
  template <typename Value, typename Iterator, typename Functor>
deba@1833
   359
  void counterUnsignedSort(Iterator first, Iterator last, Functor functor) {
deba@1904
   360
    if (first == last) return;
deba@1833
   361
    typedef typename std::iterator_traits<Iterator>::value_type Key;
deba@1833
   362
    typedef std::allocator<Key> Allocator;
deba@1833
   363
    Allocator allocator;
deba@1833
   364
deba@1833
   365
    int length = std::distance(first, last);
deba@2033
   366
    Key *buffer = allocator.allocate(2 * length);
deba@1833
   367
    try {
deba@1833
   368
      bool dir = true;
deba@1833
   369
      std::copy(first, last, buffer);
deba@2386
   370
      for (int i = 0; i < int(sizeof(Value)); ++i) {
deba@1833
   371
	if (dir) {
deba@2033
   372
	  counterIntroSort(buffer, buffer + length, 
deba@2033
   373
                           buffer + length, i, functor);
deba@1833
   374
	} else {
deba@2033
   375
	  counterIntroSort(buffer + length, buffer + 2 * length, 
deba@2033
   376
                           buffer, i, functor);
deba@1833
   377
	}
deba@1833
   378
	dir = !dir;
deba@1833
   379
      }
deba@1833
   380
      if (dir) {
deba@1833
   381
	std::copy(buffer, buffer + length, first);
deba@1833
   382
      }	else {
deba@1833
   383
	std::copy(buffer + length, buffer + 2 * length, first);
deba@1833
   384
      }
deba@1833
   385
    } catch (...) {
deba@1833
   386
      allocator.deallocate(buffer, 2 * length);
deba@1833
   387
      throw;
deba@1833
   388
    }
deba@1833
   389
    allocator.deallocate(buffer, 2 * length);
deba@1833
   390
  }
deba@1833
   391
deba@1833
   392
  namespace _radix_sort_bits {
deba@1833
   393
deba@1833
   394
    template <typename Value, 
deba@1833
   395
	      bool sign = std::numeric_limits<Value>::is_signed >
deba@1833
   396
    struct CounterSortSelector {
deba@1833
   397
      template <typename Iterator, typename Functor>
deba@1833
   398
      static void sort(Iterator first, Iterator last, Functor functor) {
deba@1833
   399
	counterSignedSort<Value>(first, last, functor);
deba@1833
   400
      }
deba@1833
   401
    };
deba@1833
   402
deba@1833
   403
    template <typename Value>
deba@1833
   404
    struct CounterSortSelector<Value, false> {
deba@1833
   405
      template <typename Iterator, typename Functor>
deba@1833
   406
      static void sort(Iterator first, Iterator last, Functor functor) {
deba@1833
   407
	counterUnsignedSort<Value>(first, last, functor);
deba@1833
   408
      }
deba@1833
   409
    };
deba@1833
   410
deba@1833
   411
  }
deba@1833
   412
deba@2084
   413
  /// \ingroup auxalg
deba@1833
   414
  ///
deba@1833
   415
  /// \brief Sorts stable the stl compatible range into ascending order.
deba@1833
   416
  ///
deba@1833
   417
  /// The \c counterSort sorts the stl compatible range into ascending order.
deba@1833
   418
  /// The counter sort algorithm can sort the items which mapped to an
deba@1833
   419
  /// integer by the adaptable unary function \c functor and the order
deba@1833
   420
  /// will be ascending by these mapped values. As function specialization
deba@1833
   421
  /// there is possible to use a normal function as the functor object
deba@1833
   422
  /// or if the functor is not given it will use an identity function instead.
deba@1833
   423
  ///
deba@1833
   424
  /// This implemented counter sort use a radix forward sort on the bytes of
deba@1833
   425
  /// the integer. The algorithm can sort the items on a given byte. 
deba@1833
   426
  /// First time it counts how many times occurs a byte value in the container.
deba@1833
   427
  /// By the occurence number it is possible to copy the container
deba@1833
   428
  /// in the right order in \c O(n) time. The algorithm sorts the container
deba@1833
   429
  /// by each bytes in forward direction which sorts the container by the
deba@1844
   430
  /// whole value. This way, let be \c c the maximal capacity of the integer 
deba@1844
   431
  /// type and \c n the number of the items in
deba@2042
   432
  /// the container, the time complexity of the algorithm \f$ O(\log(c)n) \f$
deba@2042
   433
  /// and the additional space complexity is \f$ O(n) \f$.
deba@1833
   434
  ///
deba@1833
   435
  /// This sorting algorithm is stable so the order of two equal element
deba@1833
   436
  /// stay in the same order.
deba@1833
   437
  ///
deba@1833
   438
  /// \param first The begin of the given range.
deba@1833
   439
  /// \param last The end of the given range.
deba@1833
   440
  /// \param functor An adaptible unary function or a normal function which
deba@1833
   441
  /// maps the items to any integer type which can be wheter signed or 
deba@1833
   442
  /// unsigned.
deba@1833
   443
  template <typename Iterator, typename Functor>
deba@1833
   444
  void counterSort(Iterator first, Iterator last, Functor functor) {
deba@1833
   445
    using namespace _radix_sort_bits;
deba@1833
   446
    typedef typename Functor::result_type Value;
deba@1833
   447
    CounterSortSelector<Value>::sort(first, last, functor);
deba@1833
   448
  }
deba@1833
   449
deba@1833
   450
  template <typename Iterator, typename Value, typename Key>
deba@1833
   451
  void counterSort(Iterator first, Iterator last, Value (*functor)(Key)) {
deba@1833
   452
    using namespace _radix_sort_bits;
deba@1833
   453
    CounterSortSelector<Value>::sort(first, last, functor);
deba@1833
   454
  }
deba@1833
   455
deba@1833
   456
  template <typename Iterator, typename Value, typename Key>
deba@1833
   457
  void counterSort(Iterator first, Iterator last, Value& (*functor)(Key)) {
deba@1833
   458
    using namespace _radix_sort_bits;
deba@1833
   459
    CounterSortSelector<Value>::sort(first, last, functor);
deba@1833
   460
  }
deba@1833
   461
deba@1833
   462
  template <typename Iterator, typename Value, typename Key>
deba@1833
   463
  void counterSort(Iterator first, Iterator last, Value (*functor)(Key&)) {
deba@1833
   464
    using namespace _radix_sort_bits;
deba@1833
   465
    CounterSortSelector<Value>::sort(first, last, functor);
deba@1833
   466
  }
deba@1833
   467
deba@1833
   468
  template <typename Iterator, typename Value, typename Key>
deba@1833
   469
  void counterSort(Iterator first, Iterator last, Value& (*functor)(Key&)) {
deba@1833
   470
    using namespace _radix_sort_bits;
deba@1833
   471
    CounterSortSelector<Value>::sort(first, last, functor);
deba@1833
   472
  }
deba@1833
   473
deba@1833
   474
  template <typename Iterator>
deba@1833
   475
  void counterSort(Iterator first, Iterator last) {
deba@1833
   476
    using namespace _radix_sort_bits;
deba@1833
   477
    typedef typename std::iterator_traits<Iterator>::value_type Value;
deba@1833
   478
    CounterSortSelector<Value>::sort(first, last, Identity<Value>());
deba@1833
   479
  }
deba@1833
   480
deba@1833
   481
}
deba@1833
   482
deba@1833
   483
deba@1833
   484
deba@1833
   485
#endif