COIN-OR::LEMON - Graph Library

Ticket #72: 31d224a3c0af.patch

File 31d224a3c0af.patch, 18.2 KB (added by Alpar Juttner, 16 years ago)
  • lemon/radix_sort.h

    # HG changeset patch
    # User Alpar Juttner <alpar@cs.elte.hu>
    # Date 1228213050 0
    # Node ID 31d224a3c0af0f0ae35ac7264d0a90eb1871648e
    # Parent  4f7224faf3bd0bf460965b685cd503a838251df9
    Doc improvements and source unification in radix_sort (#72)
    
    diff --git a/lemon/radix_sort.h b/lemon/radix_sort.h
    a b  
    1 /* -*- C++ -*-
     1/* -*- mode: C++; indent-tabs-mode: nil; -*-
    22 *
    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.
    44 *
    55 * Copyright (C) 2003-2008
    66 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
     
    3737    template <typename Value>
    3838    struct Identity {
    3939      const Value& operator()(const Value& val) {
    40         return val;
     40        return val;
    4141      }
    4242    };
    4343
    4444
    4545    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) {
    4848      while (first != last && !(functor(*first) & mask)) {
    49         ++first;
     49        ++first;
    5050      }
    5151      if (first == last) {
    52         return first;
     52        return first;
    5353      }
    5454      --last;
    5555      while (first != last && (functor(*last) & mask)) {
    56         --last;
     56        --last;
    5757      }
    5858      if (first == last) {
    59         return first;
     59        return first;
    6060      }
    6161      std::iter_swap(first, last);
    6262      ++first;
    6363      if (!(first < last)) {
    64         return first;
     64        return first;
    6565      }
    6666      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;
    7979      }
    8080    }
    8181
    8282    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) {
    8585      while (first != last && functor(*first) < 0) {
    86         ++first;
     86        ++first;
    8787      }
    8888      if (first == last) {
    89         return first;
     89        return first;
    9090      }
    9191      --last;
    9292      while (first != last && functor(*last) >= 0) {
    93         --last;
     93        --last;
    9494      }
    9595      if (first == last) {
    96         return first;
     96        return first;
    9797      }
    9898      std::iter_swap(first, last);
    9999      ++first;
    100100      if (!(first < last)) {
    101         return first;
     101        return first;
    102102      }
    103103      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;
    116116      }
    117117    }
    118118
    119119    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) {
    122122      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;
    127127      }
    128128    }
    129129
     
    138138
    139139      mask = ~0; max_digit = 0;
    140140      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        }
    145145      }
    146146      radixIntroSort(first, cut, functor, 1 << max_digit);
    147147
    148148      mask = 0; max_digit = 0;
    149149      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        }
    154154      }
    155155      radixIntroSort(cut, last, functor, 1 << max_digit);
    156156    }
     
    163163
    164164      Iterator it;
    165165      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        }
    170170      }
    171171      radixIntroSort(first, last, functor, 1 << max_digit);
    172172    }
    173173
    174174
    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 >
    177177    struct RadixSortSelector {
    178178      template <typename Iterator, typename Functor>
    179179      static void sort(Iterator first, Iterator last, Functor functor) {
    180         radixSignedSort<Value>(first, last, functor);
     180        radixSignedSort<Value>(first, last, functor);
    181181      }
    182182    };
    183183
     
    185185    struct RadixSortSelector<Value, false> {
    186186      template <typename Iterator, typename Functor>
    187187      static void sort(Iterator first, Iterator last, Functor functor) {
    188         radixUnsignedSort<Value>(first, last, functor);
     188        radixUnsignedSort<Value>(first, last, functor);
    189189      }
    190190    };
    191191
     
    195195  ///
    196196  /// \brief Sorts the STL compatible range into ascending order.
    197197  ///
    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.
    205202  ///
    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.
    212213  ///
    213214  /// \param first The begin of the given range.
    214215  /// \param last The end of the given range.
    215216  /// \param functor An adaptible unary function or a normal function
    216217  /// which maps the items to any integer type which can be either
    217218  /// signed or unsigned.
     219  ///
     220  /// \sa counterSort()
    218221  template <typename Iterator, typename Functor>
    219222  void radixSort(Iterator first, Iterator last, Functor functor) {
    220223    using namespace _radix_sort_bits;
     
    261264    }
    262265
    263266    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;
    268271      std::vector<int> counter(size);
    269272      for (int i = 0; i < size; ++i) {
    270         counter[i] = 0;
     273        counter[i] = 0;
    271274      }
    272275      Key *it = first;
    273276      while (first != last) {
    274         ++counter[valueByte(functor(*first), byte)];
    275         ++first;
     277        ++counter[valueByte(functor(*first), byte)];
     278        ++first;
    276279      }
    277280      int prev, num = 0;
    278281      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;
    282285      }
    283286      while (it != last) {
    284         target[counter[valueByte(functor(*it), byte)]++] = *it;
    285         ++it;
     287        target[counter[valueByte(functor(*it), byte)]++] = *it;
     288        ++it;
    286289      }
    287290    }
    288291
    289292    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;
    294297      std::vector<int> counter(size);
    295298      for (int i = 0; i < size; ++i) {
    296         counter[i] = 0;
     299        counter[i] = 0;
    297300      }
    298301      Key *it = first;
    299302      while (first != last) {
    300         counter[valueByte(functor(*first), byte)]++;
    301         ++first;
     303        counter[valueByte(functor(*first), byte)]++;
     304        ++first;
    302305      }
    303306      int prev, num = 0;
    304307      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;
    308311      }
    309312      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;
    313316      }
    314317      while (it != last) {
    315         target[counter[valueByte(functor(*it), byte)]++] = *it;
    316         ++it;
     318        target[counter[valueByte(functor(*it), byte)]++] = *it;
     319        ++it;
    317320      }
    318321    }
    319322
    320  
     323
    321324    template <typename Value, typename Iterator, typename Functor>
    322325    void counterSignedSort(Iterator first, Iterator last, Functor functor) {
    323326      if (first == last) return;
     
    328331      int length = std::distance(first, last);
    329332      Key* buffer = allocator.allocate(2 * length);
    330333      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        }
    352355      } catch (...) {
    353         allocator.deallocate(buffer, 2 * length);
    354         throw;
     356        allocator.deallocate(buffer, 2 * length);
     357        throw;
    355358      }
    356359      allocator.deallocate(buffer, 2 * length);
    357360    }
     
    366369      int length = std::distance(first, last);
    367370      Key *buffer = allocator.allocate(2 * length);
    368371      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        }
    386389      } catch (...) {
    387         allocator.deallocate(buffer, 2 * length);
    388         throw;
     390        allocator.deallocate(buffer, 2 * length);
     391        throw;
    389392      }
    390393      allocator.deallocate(buffer, 2 * length);
    391394    }
    392395
    393396
    394397
    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 >
    397400    struct CounterSortSelector {
    398401      template <typename Iterator, typename Functor>
    399402      static void sort(Iterator first, Iterator last, Functor functor) {
    400         counterSignedSort<Value>(first, last, functor);
     403        counterSignedSort<Value>(first, last, functor);
    401404      }
    402405    };
    403406
     
    405408    struct CounterSortSelector<Value, false> {
    406409      template <typename Iterator, typename Functor>
    407410      static void sort(Iterator first, Iterator last, Functor functor) {
    408         counterUnsignedSort<Value>(first, last, functor);
     411        counterUnsignedSort<Value>(first, last, functor);
    409412      }
    410413    };
    411414
     
    413416
    414417  /// \ingroup auxalg
    415418  ///
    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.
    417421  ///
    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.
    425424  ///
    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
    427429  /// 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.
    435433  ///
    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.
    438438  ///
     439
    439440  /// \param first The begin of the given range.
    440441  /// \param last The end of the given range.
    441442  /// \param functor An adaptible unary function or a normal function
    442443  /// which maps the items to any integer type which can be either
    443444  /// signed or unsigned.
     445  /// \sa radixSort()
    444446  template <typename Iterator, typename Functor>
    445447  void counterSort(Iterator first, Iterator last, Functor functor) {
    446448    using namespace _radix_sort_bits;
  • test/radix_sort_test.cc

    diff --git a/test/radix_sort_test.cc b/test/radix_sort_test.cc
    a b  
    1 /* -*- C++ -*-
     1/* -*- mode: C++; indent-tabs-mode: nil; -*-
    22 *
    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.
    44 *
    55 * Copyright (C) 2003-2008
    66 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
     
    8181      check(data1[i] == data2[n - 1 - i], "Test failed");
    8282    }
    8383
    84   } 
    85  
     84  }
     85
    8686  {
    8787    std::vector<unsigned char> data1(n);
    8888    generateCharSequence(n, data1);
     
    121121    for (int i = 0; i < n; ++i) {
    122122      check(data1[i] == data2[n - 1 - i], "Test failed");
    123123    }
    124   } 
     124  }
    125125
    126126  {
    127127    std::vector<unsigned char> data1(n);
     
    140140
    141141int main() {
    142142
    143   checkRadixSort(); 
     143  checkRadixSort();
    144144  checkCounterSort();
    145145
    146146  return 0;