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