lemon/radix_sort.h
author alpar
Tue, 17 Oct 2006 11:02:30 +0000
changeset 2252 133028e83940
parent 2042 bdc953f2a449
child 2386 81b47fc5c444
permissions -rw-r--r--
A trial to make the last test platform independent.
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@1956
     5
 * Copyright (C) 2003-2006
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@1833
   140
    mask = 0; max_digit = 0;
deba@1833
   141
    for (it = first; it != cut; ++it) {
deba@1833
   142
      if ((mask | functor(*it)) != ~0) {
deba@1833
   143
	++max_digit;
deba@1833
   144
	mask <<= 1; 
deba@1833
   145
	mask |= 1;
deba@1833
   146
      }
deba@1833
   147
    }
deba@1833
   148
    radixIntroSort(first, cut, functor, 1 << max_digit);
deba@1833
   149
deba@1833
   150
    mask = ~0; max_digit = 0;
deba@1833
   151
    for (it = cut; it != last; ++it) {
deba@1833
   152
      if (mask & functor(*it)) {
deba@1833
   153
	++max_digit;
deba@1833
   154
	mask <<= 1;
deba@1833
   155
      }
deba@1833
   156
    }
deba@1833
   157
    radixIntroSort(cut, last, functor, 1 << max_digit);
deba@1833
   158
  }
deba@1833
   159
deba@1833
   160
  template <typename Value, typename Iterator, typename Functor>
deba@1833
   161
  void radixUnsignedSort(Iterator first, Iterator last, Functor functor) {
deba@1833
   162
deba@1833
   163
    Value mask = ~0;
deba@1833
   164
    int max_digit = 0;
deba@1833
   165
deba@1833
   166
    Iterator it;
deba@1833
   167
    for (it = first; it != last; ++it) {
deba@1833
   168
      if (mask & functor(*it)) {
deba@1833
   169
	++max_digit;
deba@1833
   170
	mask <<= 1;
deba@1833
   171
      }
deba@1833
   172
    }
deba@1833
   173
    radixIntroSort(first, last, functor, 1 << max_digit);
deba@1833
   174
  }
deba@1833
   175
deba@1833
   176
  namespace _radix_sort_bits {
deba@1833
   177
deba@1833
   178
    template <typename Value, 
deba@1833
   179
	      bool sign = std::numeric_limits<Value>::is_signed >
deba@1833
   180
    struct RadixSortSelector {
deba@1833
   181
      template <typename Iterator, typename Functor>
deba@1833
   182
      static void sort(Iterator first, Iterator last, Functor functor) {
deba@1833
   183
	radixSignedSort<Value>(first, last, functor);
deba@1833
   184
      }
deba@1833
   185
    };
deba@1833
   186
deba@1833
   187
    template <typename Value>
deba@1833
   188
    struct RadixSortSelector<Value, false> {
deba@1833
   189
      template <typename Iterator, typename Functor>
deba@1833
   190
      static void sort(Iterator first, Iterator last, Functor functor) {
deba@1833
   191
	radixUnsignedSort<Value>(first, last, functor);
deba@1833
   192
      }
deba@1833
   193
    };
deba@1833
   194
deba@1833
   195
  }
deba@1833
   196
deba@2084
   197
  /// \ingroup auxalg
deba@1833
   198
  ///
deba@1833
   199
  /// \brief Sorts the stl compatible range into ascending order.
deba@1833
   200
  ///
deba@1833
   201
  /// The \c radixSort sorts the stl compatible range into ascending order.
deba@1833
   202
  /// The radix sort algorithm can sort the items which mapped to an
deba@1833
   203
  /// integer by the adaptable unary function \c functor and the order
deba@1833
   204
  /// will be ascending by these mapped values. As function specialization
deba@1833
   205
  /// there is possible to use a normal function as the functor object
deba@1833
   206
  /// or if the functor is not given it will use an identity function instead.
deba@1833
   207
  ///
deba@1833
   208
  /// This implemented radix sort is a special quick sort which pivot value
deba@1833
   209
  /// is choosen to partite the items on the next bit. This way, let be
deba@1833
   210
  /// \c c the maximal capacity and \c n the number of the items in
deba@2042
   211
  /// the container, the time complexity of the algorithm 
deba@2042
   212
  /// \f$ O(\log(c)n) \f$ and the additional space complexity is 
deba@2042
   213
  /// \f$ O(\log(c)) \f$.
deba@1833
   214
  ///
deba@1833
   215
  /// \param first The begin of the given range.
deba@1833
   216
  /// \param last The end of the given range.
deba@1833
   217
  /// \param functor An adaptible unary function or a normal function which
deba@1833
   218
  /// maps the items to any integer type which can be wheter signed or 
deba@1833
   219
  /// unsigned.
deba@1833
   220
  template <typename Iterator, typename Functor>
deba@1833
   221
  void radixSort(Iterator first, Iterator last, Functor functor) {
deba@1833
   222
    using namespace _radix_sort_bits;
deba@1833
   223
    typedef typename Functor::result_type Value;
deba@1833
   224
    RadixSortSelector<Value>::sort(first, last, functor);
deba@1833
   225
  }
deba@1833
   226
deba@1833
   227
  template <typename Iterator, typename Value, typename Key>
deba@1833
   228
  void radixSort(Iterator first, Iterator last, Value (*functor)(Key)) {
deba@1833
   229
    using namespace _radix_sort_bits;
deba@1833
   230
    RadixSortSelector<Value>::sort(first, last, functor);
deba@1833
   231
  }
deba@1833
   232
deba@1833
   233
  template <typename Iterator, typename Value, typename Key>
deba@1833
   234
  void radixSort(Iterator first, Iterator last, Value& (*functor)(Key)) {
deba@1833
   235
    using namespace _radix_sort_bits;
deba@1833
   236
    RadixSortSelector<Value>::sort(first, last, functor);
deba@1833
   237
  }
deba@1833
   238
deba@1833
   239
  template <typename Iterator, typename Value, typename Key>
deba@1833
   240
  void radixSort(Iterator first, Iterator last, Value (*functor)(Key&)) {
deba@1833
   241
    using namespace _radix_sort_bits;
deba@1833
   242
    RadixSortSelector<Value>::sort(first, last, functor);
deba@1833
   243
  }
deba@1833
   244
deba@1833
   245
  template <typename Iterator, typename Value, typename Key>
deba@1833
   246
  void radixSort(Iterator first, Iterator last, Value& (*functor)(Key&)) {
deba@1833
   247
    using namespace _radix_sort_bits;
deba@1833
   248
    RadixSortSelector<Value>::sort(first, last, functor);
deba@1833
   249
  }
deba@1833
   250
deba@1833
   251
  template <typename Iterator>
deba@1833
   252
  void radixSort(Iterator first, Iterator last) {
deba@1833
   253
    using namespace _radix_sort_bits;
deba@1833
   254
    typedef typename std::iterator_traits<Iterator>::value_type Value;
deba@1833
   255
    RadixSortSelector<Value>::sort(first, last, Identity<Value>());
deba@1833
   256
  }
deba@1833
   257
deba@1833
   258
  template <typename Value>
deba@1833
   259
  unsigned char valueByte(Value value, int byte) {
deba@1844
   260
    return value >> (std::numeric_limits<unsigned char>::digits * byte);
deba@1833
   261
  }
deba@1833
   262
deba@1833
   263
  template <typename Functor, typename Key>
deba@1833
   264
  void counterIntroSort(Key *first, Key *last, Key *target, 
deba@1833
   265
		       int byte, Functor functor) {
deba@1833
   266
    const int size = 
deba@1833
   267
      (unsigned int)std::numeric_limits<unsigned char>::max() + 1;
deba@1979
   268
    std::vector<int> counter(size);
deba@1833
   269
    for (int i = 0; i < size; ++i) {
deba@1833
   270
      counter[i] = 0;
deba@1833
   271
    }
deba@1833
   272
    Key *it = first;
deba@1833
   273
    while (first != last) {
deba@1833
   274
      ++counter[valueByte(functor(*first), byte)]; 
deba@1833
   275
      ++first;
deba@1833
   276
    }
deba@1833
   277
    int prev, num = 0;
deba@1833
   278
    for (int i = 0; i < size; ++i) {
deba@1833
   279
      prev = num;
deba@1833
   280
      num += counter[i];
deba@1833
   281
      counter[i] = prev;
deba@1833
   282
    }
deba@1833
   283
    while (it != last) {
deba@1833
   284
      target[counter[valueByte(functor(*it), byte)]++] = *it;
deba@1833
   285
      ++it;
deba@1833
   286
    }
deba@1833
   287
  }
deba@1833
   288
deba@1833
   289
  template <typename Functor, typename Key>
deba@1833
   290
  void signedCounterIntroSort(Key *first, Key *last, Key *target, 
deba@1833
   291
			     int byte, Functor functor) {
deba@1833
   292
    const int size = 
deba@1833
   293
      (unsigned int)std::numeric_limits<unsigned char>::max() + 1;
deba@1979
   294
    std::vector<int> counter(size);
deba@1833
   295
    for (int i = 0; i < size; ++i) {
deba@1833
   296
      counter[i] = 0;
deba@1833
   297
    }
deba@1833
   298
    Key *it = first;
deba@1833
   299
    while (first != last) {
deba@1833
   300
      counter[valueByte(functor(*first), byte)]++;
deba@1833
   301
      ++first;
deba@1833
   302
    }
deba@1833
   303
    int prev, num = 0;
deba@1833
   304
    for (int i = size / 2; i < size; ++i) {
deba@1833
   305
      prev = num;
deba@1833
   306
      num += counter[i];
deba@1833
   307
      counter[i] = prev;
deba@1833
   308
    }
deba@1833
   309
    for (int i = 0; i < size / 2; ++i) {
deba@1833
   310
      prev = num;
deba@1833
   311
      num += counter[i];
deba@1833
   312
      counter[i] = prev;
deba@1833
   313
    }
deba@1833
   314
    while (it != last) {
deba@1833
   315
      target[counter[valueByte(functor(*it), byte)]++] = *it;
deba@1833
   316
      ++it;
deba@1833
   317
    }
deba@1833
   318
  }
deba@1833
   319
deba@1833
   320
  
deba@1833
   321
  template <typename Value, typename Iterator, typename Functor>
deba@1833
   322
  void counterSignedSort(Iterator first, Iterator last, Functor functor) {
deba@1904
   323
    if (first == last) return;
deba@1833
   324
    typedef typename std::iterator_traits<Iterator>::value_type Key;
deba@1833
   325
    typedef std::allocator<Key> Allocator;
deba@1833
   326
    Allocator allocator;
deba@1833
   327
deba@1833
   328
    int length = std::distance(first, last);
deba@2033
   329
    Key* buffer = allocator.allocate(2 * length);
deba@1833
   330
    try {
deba@1833
   331
      bool dir = true;
deba@1833
   332
      std::copy(first, last, buffer);
deba@1833
   333
      for (int i = 0; i < (int)sizeof(Value) - 1; ++i) {
deba@1833
   334
	if (dir) {
deba@1833
   335
	  counterIntroSort(buffer, buffer + length, buffer + length, 
deba@1833
   336
			   i, functor);
deba@1833
   337
	} else {
deba@1833
   338
	  counterIntroSort(buffer + length, buffer + 2 * length, buffer, 
deba@1833
   339
			   i, functor);
deba@1833
   340
	}
deba@1833
   341
	dir = !dir;
deba@1833
   342
      }
deba@1833
   343
      if (dir) {
deba@1833
   344
	signedCounterIntroSort(buffer, buffer + length, buffer + length, 
deba@1833
   345
			       sizeof(Value) - 1, functor);
deba@1833
   346
	std::copy(buffer + length, buffer + 2 * length, first);
deba@1833
   347
      }	else {
deba@1833
   348
	signedCounterIntroSort(buffer + length, buffer + 2 * length, buffer, 
deba@1833
   349
			       sizeof(Value) - 1, functor);
deba@1833
   350
	std::copy(buffer, buffer + length, first);
deba@1833
   351
      }
deba@1833
   352
    } catch (...) {
deba@1833
   353
      allocator.deallocate(buffer, 2 * length);
deba@1833
   354
      throw;
deba@1833
   355
    }
deba@1833
   356
    allocator.deallocate(buffer, 2 * length);
deba@1833
   357
  }
deba@1833
   358
deba@1833
   359
  template <typename Value, typename Iterator, typename Functor>
deba@1833
   360
  void counterUnsignedSort(Iterator first, Iterator last, Functor functor) {
deba@1904
   361
    if (first == last) return;
deba@1833
   362
    typedef typename std::iterator_traits<Iterator>::value_type Key;
deba@1833
   363
    typedef std::allocator<Key> Allocator;
deba@1833
   364
    Allocator allocator;
deba@1833
   365
deba@1833
   366
    int length = std::distance(first, last);
deba@2033
   367
    Key *buffer = allocator.allocate(2 * length);
deba@1833
   368
    try {
deba@1833
   369
      bool dir = true;
deba@1833
   370
      std::copy(first, last, buffer);
deba@1844
   371
      for (int i = 0; i < (int)sizeof(Value); ++i) {
deba@1833
   372
	if (dir) {
deba@2033
   373
	  counterIntroSort(buffer, buffer + length, 
deba@2033
   374
                           buffer + length, i, functor);
deba@1833
   375
	} else {
deba@2033
   376
	  counterIntroSort(buffer + length, buffer + 2 * length, 
deba@2033
   377
                           buffer, i, functor);
deba@1833
   378
	}
deba@1833
   379
	dir = !dir;
deba@1833
   380
      }
deba@1833
   381
      if (dir) {
deba@1833
   382
	std::copy(buffer, buffer + length, first);
deba@1833
   383
      }	else {
deba@1833
   384
	std::copy(buffer + length, buffer + 2 * length, first);
deba@1833
   385
      }
deba@1833
   386
    } catch (...) {
deba@1833
   387
      allocator.deallocate(buffer, 2 * length);
deba@1833
   388
      throw;
deba@1833
   389
    }
deba@1833
   390
    allocator.deallocate(buffer, 2 * length);
deba@1833
   391
  }
deba@1833
   392
deba@1833
   393
  namespace _radix_sort_bits {
deba@1833
   394
deba@1833
   395
    template <typename Value, 
deba@1833
   396
	      bool sign = std::numeric_limits<Value>::is_signed >
deba@1833
   397
    struct CounterSortSelector {
deba@1833
   398
      template <typename Iterator, typename Functor>
deba@1833
   399
      static void sort(Iterator first, Iterator last, Functor functor) {
deba@1833
   400
	counterSignedSort<Value>(first, last, functor);
deba@1833
   401
      }
deba@1833
   402
    };
deba@1833
   403
deba@1833
   404
    template <typename Value>
deba@1833
   405
    struct CounterSortSelector<Value, false> {
deba@1833
   406
      template <typename Iterator, typename Functor>
deba@1833
   407
      static void sort(Iterator first, Iterator last, Functor functor) {
deba@1833
   408
	counterUnsignedSort<Value>(first, last, functor);
deba@1833
   409
      }
deba@1833
   410
    };
deba@1833
   411
deba@1833
   412
  }
deba@1833
   413
deba@2084
   414
  /// \ingroup auxalg
deba@1833
   415
  ///
deba@1833
   416
  /// \brief Sorts stable the stl compatible range into ascending order.
deba@1833
   417
  ///
deba@1833
   418
  /// The \c counterSort sorts the stl compatible range into ascending order.
deba@1833
   419
  /// The counter sort algorithm can sort the items which mapped to an
deba@1833
   420
  /// integer by the adaptable unary function \c functor and the order
deba@1833
   421
  /// will be ascending by these mapped values. As function specialization
deba@1833
   422
  /// there is possible to use a normal function as the functor object
deba@1833
   423
  /// or if the functor is not given it will use an identity function instead.
deba@1833
   424
  ///
deba@1833
   425
  /// This implemented counter sort use a radix forward sort on the bytes of
deba@1833
   426
  /// the integer. The algorithm can sort the items on a given byte. 
deba@1833
   427
  /// First time it counts how many times occurs a byte value in the container.
deba@1833
   428
  /// By the occurence number it is possible to copy the container
deba@1833
   429
  /// in the right order in \c O(n) time. The algorithm sorts the container
deba@1833
   430
  /// by each bytes in forward direction which sorts the container by the
deba@1844
   431
  /// whole value. This way, let be \c c the maximal capacity of the integer 
deba@1844
   432
  /// type and \c n the number of the items in
deba@2042
   433
  /// the container, the time complexity of the algorithm \f$ O(\log(c)n) \f$
deba@2042
   434
  /// and the additional space complexity is \f$ O(n) \f$.
deba@1833
   435
  ///
deba@1833
   436
  /// This sorting algorithm is stable so the order of two equal element
deba@1833
   437
  /// stay in the same order.
deba@1833
   438
  ///
deba@1833
   439
  /// \param first The begin of the given range.
deba@1833
   440
  /// \param last The end of the given range.
deba@1833
   441
  /// \param functor An adaptible unary function or a normal function which
deba@1833
   442
  /// maps the items to any integer type which can be wheter signed or 
deba@1833
   443
  /// unsigned.
deba@1833
   444
  template <typename Iterator, typename Functor>
deba@1833
   445
  void counterSort(Iterator first, Iterator last, Functor functor) {
deba@1833
   446
    using namespace _radix_sort_bits;
deba@1833
   447
    typedef typename Functor::result_type Value;
deba@1833
   448
    CounterSortSelector<Value>::sort(first, last, functor);
deba@1833
   449
  }
deba@1833
   450
deba@1833
   451
  template <typename Iterator, typename Value, typename Key>
deba@1833
   452
  void counterSort(Iterator first, Iterator last, Value (*functor)(Key)) {
deba@1833
   453
    using namespace _radix_sort_bits;
deba@1833
   454
    CounterSortSelector<Value>::sort(first, last, functor);
deba@1833
   455
  }
deba@1833
   456
deba@1833
   457
  template <typename Iterator, typename Value, typename Key>
deba@1833
   458
  void counterSort(Iterator first, Iterator last, Value& (*functor)(Key)) {
deba@1833
   459
    using namespace _radix_sort_bits;
deba@1833
   460
    CounterSortSelector<Value>::sort(first, last, functor);
deba@1833
   461
  }
deba@1833
   462
deba@1833
   463
  template <typename Iterator, typename Value, typename Key>
deba@1833
   464
  void counterSort(Iterator first, Iterator last, Value (*functor)(Key&)) {
deba@1833
   465
    using namespace _radix_sort_bits;
deba@1833
   466
    CounterSortSelector<Value>::sort(first, last, functor);
deba@1833
   467
  }
deba@1833
   468
deba@1833
   469
  template <typename Iterator, typename Value, typename Key>
deba@1833
   470
  void counterSort(Iterator first, Iterator last, Value& (*functor)(Key&)) {
deba@1833
   471
    using namespace _radix_sort_bits;
deba@1833
   472
    CounterSortSelector<Value>::sort(first, last, functor);
deba@1833
   473
  }
deba@1833
   474
deba@1833
   475
  template <typename Iterator>
deba@1833
   476
  void counterSort(Iterator first, Iterator last) {
deba@1833
   477
    using namespace _radix_sort_bits;
deba@1833
   478
    typedef typename std::iterator_traits<Iterator>::value_type Value;
deba@1833
   479
    CounterSortSelector<Value>::sort(first, last, Identity<Value>());
deba@1833
   480
  }
deba@1833
   481
deba@1833
   482
}
deba@1833
   483
deba@1833
   484
deba@1833
   485
deba@1833
   486
#endif