Yet Another eXchange Tool  DO_NOT_EDIT_HERE
xt_quicksort_base.h
Go to the documentation of this file.
1 
13 /*
14  * Keywords:
15  * Maintainer: Jörg Behrens <behrens@dkrz.de>
16  * Moritz Hanke <hanke@dkrz.de>
17  * Thomas Jahns <jahns@dkrz.de>
18  * URL: https://doc.redmine.dkrz.de/yaxt/html/
19  *
20  * Redistribution and use in source and binary forms, with or without
21  * modification, are permitted provided that the following conditions are
22  * met:
23  *
24  * Redistributions of source code must retain the above copyright notice,
25  * this list of conditions and the following disclaimer.
26  *
27  * Redistributions in binary form must reproduce the above copyright
28  * notice, this list of conditions and the following disclaimer in the
29  * documentation and/or other materials provided with the distribution.
30  *
31  * Neither the name of the DKRZ GmbH nor the names of its contributors
32  * may be used to endorse or promote products derived from this software
33  * without specific prior written permission.
34  *
35  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
36  * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
37  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
38  * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
39  * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
40  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
41  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
42  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
43  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
44  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
45  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
46  */
47 /*
48  * xt_quicksort_int was derived from the ScalES-PPM library code,
49  * which is derived from genometools, which in turn is derived from
50  * the FreeBSD libc.
51  */
52 /*
53  Modifications for integration with genometools
54  2008 Thomas Jahns <Thomas.Jahns@gmx.net>
55 
56  The advertising clause 3. was removed due to the corresponding
57  revoke by William Hoskins on July 22, 1999.
58  <ftp://ftp.cs.berkeley.edu/pub/4bsd/README.Impt.License.Change>
59 */
60 /*-
61  * Copyright (c) 1992, 1993
62  * The Regents of the University of California. All rights reserved.
63  *
64  * Redistribution and use in source and binary forms, with or without
65  * modification, are permitted provided that the following conditions
66  * are met:
67  * 1. Redistributions of source code must retain the above copyright
68  * notice, this list of conditions and the following disclaimer.
69  * 2. Redistributions in binary form must reproduce the above copyright
70  * notice, this list of conditions and the following disclaimer in the
71  * documentation and/or other materials provided with the distribution.
72  * 4. Neither the name of the University nor the names of its contributors
73  * may be used to endorse or promote products derived from this software
74  * without specific prior written permission.
75  *
76  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
77  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
78  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
79  * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
80  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
81  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
82  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
83  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
84  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
85  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
86  * SUCH DAMAGE.
87  */
88 #ifndef XT_QUICKSORT_BASE_H
89 #define XT_QUICKSORT_BASE_H
90 #define TOKEN_PASTE(a,b) a##_##b
91 #define NAME_COMPOSE(a,b) TOKEN_PASTE(a,b)
92 #endif
93 #ifndef SORT_TYPE
94 #error "must define type to sort on"
95 #endif
96 #ifndef SORT_TYPE_SUFFIX
97 #error "must define suffix for type to name functions"
98 #endif
99 #ifndef SORT_TYPE_CMP_LT
100 #error "must define suffix for type to name functions"
101 #endif
102 
103 #define MED3 NAME_COMPOSE(med3,SORT_TYPE_SUFFIX)
104 #define VECSWAP NAME_COMPOSE(vecswap,SORT_TYPE_SUFFIX)
105 #define XT_QUICKSORT NAME_COMPOSE(xt_quicksort,SORT_TYPE_SUFFIX)
106 
107 static inline SORT_TYPE *
109 {
110  return SORT_TYPE_CMP_LT(*a,*b) ?
111  (SORT_TYPE_CMP_LT(*b,*c) ? b : (SORT_TYPE_CMP_LT(*a,*c) ? a : c ))
112  : (SORT_TYPE_CMP_LT(*c,*b) ? b : (SORT_TYPE_CMP_LT(*a,*c) ? a : c ));
113 }
114 
115 #ifndef SWAP
116 #define SWAP(a,b) do { \
117  SORT_TYPE t = a; a = b; b = t; \
118  } while (0)
119 #endif
120 
121 static inline void
122 VECSWAP(SORT_TYPE *restrict a, SORT_TYPE *restrict b, size_t n)
123 {
124  for (size_t i = 0; i < n; ++i) {
125  SORT_TYPE t = a[i];
126  a[i] = b[i];
127  b[i] = t;
128  }
129 }
130 
131 void XT_QUICKSORT(SORT_TYPE *a, size_t n)
132 {
133 #define MIN(a,b) (((a) < (b)) ? (a) : (b))
134 
135  while (1) {
136  bool swap_cnt = false;
137  if (n < 7) {
138  for (SORT_TYPE *pm = a + 1; pm < a + n; ++pm)
139  for (SORT_TYPE *pl = pm; pl > a && SORT_TYPE_CMP_LT(*pl, pl[-1]); --pl)
140  SWAP(*pl, pl[-1]);
141  return;
142  }
143  {
144  SORT_TYPE *pm = a + (n / 2);
145  if (n > 7) {
146  SORT_TYPE *pl = a;
147  SORT_TYPE *pn = a + (n - 1);
148  if (n > 40) {
149  size_t d = n / 8;
150  pl = MED3(pl, pl + d, pl + 2 * d);
151  pm = MED3(pm - d, pm, pm + d);
152  pn = MED3(pn - 2 * d, pn - d, pn);
153  }
154  pm = MED3(pl, pm, pn);
155  }
156  SWAP(*a, *pm);
157  }
158  SORT_TYPE *pa = a + 1, *pb = pa;
159  SORT_TYPE *pc = a + n - 1, *pd = pc;
160  SORT_TYPE pivot = *a;
161  for (;;) {
162  while (pb <= pc && SORT_TYPE_CMP_LE(*pb, pivot)) {
163  if (SORT_TYPE_CMP_EQ(*pb, pivot)) {
164  swap_cnt = true;
165  SWAP(*pa, *pb);
166  ++pa;
167  }
168  ++pb;
169  }
170  while (pb <= pc && SORT_TYPE_CMP_LE(pivot, *pc)) {
171  if (SORT_TYPE_CMP_EQ(*pc, pivot)) {
172  swap_cnt = true;
173  SWAP(*pc, *pd);
174  --pd;
175  }
176  --pc;
177  }
178  if (pb > pc)
179  break;
180  SWAP(*pb, *pc);
181  swap_cnt = true;
182  ++pb;
183  --pc;
184  }
185  if (!swap_cnt) { /* Switch to insertion sort */
186  for (SORT_TYPE *pm = a + 1; pm < a + n; ++pm)
187  for (SORT_TYPE *pl = pm; pl > a && SORT_TYPE_CMP_LT(*pl, pl[-1]); --pl)
188  SWAP(*pl, pl[-1]);
189  return;
190  }
191 
192  SORT_TYPE *pn = a + n;
193  ptrdiff_t pdiff = MIN(pa - a, pb - pa);
194  VECSWAP(a, pb - pdiff, (size_t)pdiff);
195  pdiff = MIN(pd - pc, pn - pd - 1);
196  VECSWAP(pb, pn - pdiff, (size_t)pdiff);
197  if ((pdiff = pb - pa) > (ptrdiff_t)1)
198  XT_QUICKSORT(a, (size_t)pdiff);
199  if ((pdiff = pd - pc) > (ptrdiff_t)1) {
200  /* Iterate rather than recurse to save stack space */
201  a = pn - pdiff;
202  n = (size_t)pdiff;
203  }
204  else
205  break;
206  }
207 #undef MIN
208 }
#define MED3
#define SORT_TYPE_CMP_LE(a, b)
Definition: quicksort.c:216
#define SWAP(a, b)
#define SORT_TYPE_CMP_LT(a, b)
Definition: quicksort.c:215
#define SORT_TYPE
Definition: quicksort.c:213
#define VECSWAP
#define XT_QUICKSORT
#define SORT_TYPE_CMP_EQ(a, b)
Definition: quicksort.c:217
#define MIN(a, b)