Stxxl  1.4.0
include/stxxl/bits/containers/pq_mergers.h
Go to the documentation of this file.
00001 /***************************************************************************
00002  *  include/stxxl/bits/containers/pq_mergers.h
00003  *
00004  *  Part of the STXXL. See http://stxxl.sourceforge.net
00005  *
00006  *  Copyright (C) 1999 Peter Sanders <sanders@mpi-sb.mpg.de>
00007  *  Copyright (C) 2003, 2004, 2007 Roman Dementiev <dementiev@mpi-sb.mpg.de>
00008  *  Copyright (C) 2007-2009 Johannes Singler <singler@ira.uka.de>
00009  *  Copyright (C) 2007, 2008 Andreas Beckmann <beckmann@cs.uni-frankfurt.de>
00010  *
00011  *  Distributed under the Boost Software License, Version 1.0.
00012  *  (See accompanying file LICENSE_1_0.txt or copy at
00013  *  http://www.boost.org/LICENSE_1_0.txt)
00014  **************************************************************************/
00015 
00016 #ifndef STXXL_PQ_MERGERS_HEADER
00017 #define STXXL_PQ_MERGERS_HEADER
00018 
00019 __STXXL_BEGIN_NAMESPACE
00020 
00021 //! \addtogroup stlcontinternals
00022 //!
00023 //! \{
00024 
00025 /*! \internal
00026  */
00027 namespace priority_queue_local
00028 {
00029 /////////////////////////////////////////////////////////////////////
00030 // auxiliary functions
00031 
00032 // merge length elements from the two sentinel terminated input
00033 // sequences source0 and source1 to target
00034 // advance source0 and source1 accordingly
00035 // require: at least length nonsentinel elements available in source0, source1
00036 // require: target may overwrite one of the sources as long as
00037 //   *(sourcex + length) is before the end of sourcex
00038     template <class InputIterator, class OutputIterator, class Cmp_>
00039     void merge_iterator(
00040         InputIterator & source0,
00041         InputIterator & source1,
00042         OutputIterator target,
00043         unsigned_type length,
00044         Cmp_& cmp)
00045     {
00046         OutputIterator done = target + length;
00047 
00048         while (target != done)
00049         {
00050             if (cmp(*source0, *source1))
00051             {
00052                 *target = *source1;
00053                 ++source1;
00054             }
00055             else
00056             {
00057                 *target = *source0;
00058                 ++source0;
00059             }
00060             ++target;
00061         }
00062     }
00063 
00064 // merge length elements from the three sentinel terminated input
00065 // sequences source0, source1 and source2 to target
00066 // advance source0, source1 and source2 accordingly
00067 // require: at least length nonsentinel elements available in source0, source1 and source2
00068 // require: target may overwrite one of the sources as long as
00069 //   *(sourcex + length) is before the end of sourcex
00070     template <class InputIterator, class OutputIterator, class Cmp_>
00071     void merge3_iterator(
00072         InputIterator & source0,
00073         InputIterator & source1,
00074         InputIterator & source2,
00075         OutputIterator target,
00076         unsigned_type length,
00077         Cmp_& cmp)
00078     {
00079         OutputIterator done = target + length;
00080 
00081         if (cmp(*source1, *source0)) {
00082             if (cmp(*source2, *source1)) {
00083                 goto s012;
00084             }
00085             else {
00086                 if (cmp(*source0, *source2)) {
00087                     goto s201;
00088                 }
00089                 else {
00090                     goto s021;
00091                 }
00092             }
00093         } else {
00094             if (cmp(*source2, *source1)) {
00095                 if (cmp(*source2, *source0)) {
00096                     goto s102;
00097                 }
00098                 else {
00099                     goto s120;
00100                 }
00101             } else {
00102                 goto s210;
00103             }
00104         }
00105 
00106 #define Merge3Case(a, b, c) \
00107     s ## a ## b ## c : \
00108     if (target == done) \
00109         return; \
00110     *target = *source ## a; \
00111     ++target; \
00112     ++source ## a; \
00113     if (cmp(*source ## b, *source ## a)) \
00114         goto s ## a ## b ## c; \
00115     if (cmp(*source ## c, *source ## a)) \
00116         goto s ## b ## a ## c; \
00117     goto s ## b ## c ## a;
00118 
00119         // the order is chosen in such a way that
00120         // four of the trailing gotos can be eliminated by the optimizer
00121         Merge3Case(0, 1, 2);
00122         Merge3Case(1, 2, 0);
00123         Merge3Case(2, 0, 1);
00124         Merge3Case(1, 0, 2);
00125         Merge3Case(0, 2, 1);
00126         Merge3Case(2, 1, 0);
00127 
00128 #undef Merge3Case
00129     }
00130 
00131 
00132 // merge length elements from the four sentinel terminated input
00133 // sequences source0, source1, source2 and source3 to target
00134 // advance source0, source1, source2 and source3 accordingly
00135 // require: at least length nonsentinel elements available in source0, source1, source2 and source3
00136 // require: target may overwrite one of the sources as long as
00137 //   *(sourcex + length) is before the end of sourcex
00138     template <class InputIterator, class OutputIterator, class Cmp_>
00139     void merge4_iterator(
00140         InputIterator & source0,
00141         InputIterator & source1,
00142         InputIterator & source2,
00143         InputIterator & source3,
00144         OutputIterator target, unsigned_type length, Cmp_& cmp)
00145     {
00146         OutputIterator done = target + length;
00147 
00148 #define StartMerge4(a, b, c, d) \
00149     if ((!cmp(*source ## a, *source ## b)) && (!cmp(*source ## b, *source ## c)) && (!cmp(*source ## c, *source ## d))) \
00150         goto s ## a ## b ## c ## d;
00151 
00152         // b>a c>b d>c
00153         // a<b b<c c<d
00154         // a<=b b<=c c<=d
00155         // !(a>b) !(b>c) !(c>d)
00156 
00157         StartMerge4(0, 1, 2, 3);
00158         StartMerge4(1, 2, 3, 0);
00159         StartMerge4(2, 3, 0, 1);
00160         StartMerge4(3, 0, 1, 2);
00161 
00162         StartMerge4(0, 3, 1, 2);
00163         StartMerge4(3, 1, 2, 0);
00164         StartMerge4(1, 2, 0, 3);
00165         StartMerge4(2, 0, 3, 1);
00166 
00167         StartMerge4(0, 2, 3, 1);
00168         StartMerge4(2, 3, 1, 0);
00169         StartMerge4(3, 1, 0, 2);
00170         StartMerge4(1, 0, 2, 3);
00171 
00172         StartMerge4(2, 0, 1, 3);
00173         StartMerge4(0, 1, 3, 2);
00174         StartMerge4(1, 3, 2, 0);
00175         StartMerge4(3, 2, 0, 1);
00176 
00177         StartMerge4(3, 0, 2, 1);
00178         StartMerge4(0, 2, 1, 3);
00179         StartMerge4(2, 1, 3, 0);
00180         StartMerge4(1, 3, 0, 2);
00181 
00182         StartMerge4(1, 0, 3, 2);
00183         StartMerge4(0, 3, 2, 1);
00184         StartMerge4(3, 2, 1, 0);
00185         StartMerge4(2, 1, 0, 3);
00186 
00187 #define Merge4Case(a, b, c, d) \
00188     s ## a ## b ## c ## d : \
00189     if (target == done) \
00190         return; \
00191     *target = *source ## a; \
00192     ++target; \
00193     ++source ## a; \
00194     if (cmp(*source ## c, *source ## a)) \
00195     { \
00196         if (cmp(*source ## b, *source ## a)) \
00197             goto s ## a ## b ## c ## d; \
00198         else \
00199             goto s ## b ## a ## c ## d; \
00200     } \
00201     else \
00202     { \
00203         if (cmp(*source ## d, *source ## a)) \
00204             goto s ## b ## c ## a ## d; \
00205         else \
00206             goto s ## b ## c ## d ## a; \
00207     }
00208 
00209         Merge4Case(0, 1, 2, 3);
00210         Merge4Case(1, 2, 3, 0);
00211         Merge4Case(2, 3, 0, 1);
00212         Merge4Case(3, 0, 1, 2);
00213 
00214         Merge4Case(0, 3, 1, 2);
00215         Merge4Case(3, 1, 2, 0);
00216         Merge4Case(1, 2, 0, 3);
00217         Merge4Case(2, 0, 3, 1);
00218 
00219         Merge4Case(0, 2, 3, 1);
00220         Merge4Case(2, 3, 1, 0);
00221         Merge4Case(3, 1, 0, 2);
00222         Merge4Case(1, 0, 2, 3);
00223 
00224         Merge4Case(2, 0, 1, 3);
00225         Merge4Case(0, 1, 3, 2);
00226         Merge4Case(1, 3, 2, 0);
00227         Merge4Case(3, 2, 0, 1);
00228 
00229         Merge4Case(3, 0, 2, 1);
00230         Merge4Case(0, 2, 1, 3);
00231         Merge4Case(2, 1, 3, 0);
00232         Merge4Case(1, 3, 0, 2);
00233 
00234         Merge4Case(1, 0, 3, 2);
00235         Merge4Case(0, 3, 2, 1);
00236         Merge4Case(3, 2, 1, 0);
00237         Merge4Case(2, 1, 0, 3);
00238 
00239 #undef StartMerge4
00240 #undef Merge4Case
00241     }
00242 } //priority_queue_local
00243 
00244 //! \}
00245 
00246 __STXXL_END_NAMESPACE
00247 
00248 #endif // !STXXL_PQ_MERGERS_HEADER
00249 // vim: et:ts=4:sw=4
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines