added Verlet scheme and NxN non-bonded functionality
[gromacs.git] / src / gmxlib / gmx_sort.c
blobe0fe87bd1f63f99bac1f09fe6d1ba9925e86eb64
1 /* -*- mode: c; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; c-file-style: "stroustrup"; -*-
3 *
4 * This file is part of Gromacs Copyright (c) 1991-2010
5 * David van der Spoel, Erik Lindahl, Berk Hess, University of Groningen.
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version 2
10 * of the License, or (at your option) any later version.
12 * To help us fund GROMACS development, we humbly ask that you cite
13 * the research papers on the package. Check out http://www.gromacs.org
15 * And Hey:
16 * Gnomes, ROck Monsters And Chili Sauce
19 #ifdef HAVE_CONFIG_H
20 #include <config.h>
21 #endif
23 #include <stdlib.h>
24 #include "gmx_sort.h"
27 static void
28 qsort_swapfunc(void * a,
29 void * b,
30 size_t n,
31 int swaptype)
33 int * ia;
34 int * ib;
35 int itmp;
37 char * ca;
38 char * cb;
39 char ctmp;
41 if (swaptype <= 1)
43 ia = (int *)a;
44 ib = (int *)b;
45 for( ; n > 0; ia += 1, ib += 1, n -= sizeof(int))
47 itmp = *ia;
48 *ia = *ib;
49 *ib = itmp;
52 else
54 ca = (char *)a;
55 cb = (char *)b;
56 for( ; n > 0; ca += 1, cb += 1, n -= 1)
58 ctmp = *ca;
59 *ca = *cb;
60 *cb = ctmp;
66 static void *
67 qsort_med3(void * a,
68 void * b,
69 void * c,
70 int (*compar) (const void *a, const void *b))
72 if(compar(a,b) < 0)
74 if(compar(b,c) < 0)
75 return b;
76 else if(compar(a,c) < 0)
77 return c;
78 else
79 return a;
81 else
83 if(compar(b,c) > 0)
84 return b;
85 else if(compar(a,c) > 0)
86 return c;
87 else
88 return a;
93 void
94 gmx_qsort(void * base,
95 size_t nmemb,
96 size_t size,
97 int (*compar)(const void *, const void *))
99 #define QSORT_EXCH(a, b, t) (t = a, a = b, b = t)
100 #define QSORT_SWAP(a, b) swaptype != 0 ? qsort_swapfunc(a, b, size, swaptype) : \
101 (void)QSORT_EXCH(*(int *)(a), *(int *)(b), t)
103 char *pa, *pb, *pc, *pd, *pl, *pm, *pn, *pv, *cbase;
104 int r, swaptype;
105 int t, v;
106 size_t s, st;
108 cbase = (char *)base;
110 swaptype = (size_t)(cbase - (char *)0) % sizeof(int) || size % sizeof(int) ? 2 : size == sizeof(int)? 0 : 1;
112 if (nmemb < 7)
114 /* Insertion sort on smallest arrays */
115 for (pm = cbase + size; pm < cbase + nmemb*size; pm += size)
117 for (pl = pm; (pl > cbase) && compar((void *)(pl-size),(void *) pl) > 0; pl -= size)
119 QSORT_SWAP(pl, pl-size);
122 return;
125 /* Small arrays, middle element */
126 pm = cbase + (nmemb/2)*size;
128 if (nmemb > 7)
130 pl = cbase;
131 pn = cbase + (nmemb-1)*size;
132 if (nmemb > 40)
134 /* Big arrays, pseudomedian of 9 */
135 s = (nmemb/8)*size;
136 pl = (char *)qsort_med3((void *)pl, (void *)((size_t)pl+s), (void *)((size_t)pl+2*s), compar);
137 pm = (char *)qsort_med3((void *)((size_t)pm-s), (void *)pm, (void *)((size_t)pm+s), compar);
138 pn = (char *)qsort_med3((void *)((size_t)pn-2*s), (void *)((size_t)pn-s), (void *)pn, compar);
140 /* Mid-size, med of 3 */
141 pm = (char *)qsort_med3((void *)pl, (void *)pm, (void *)pn, compar);
144 /* pv points to partition value */
145 if (swaptype != 0)
147 pv = cbase;
148 QSORT_SWAP(pv, pm);
150 else
152 pv = (char*)(void*)&v;
153 v = *(int *)pm;
156 pa = pb = cbase;
157 pc = pd = cbase + (nmemb-1)*size;
159 for (;;)
161 while (pb <= pc && (r = compar((void *)pb,(void *) pv)) <= 0)
163 if (r == 0)
165 QSORT_SWAP(pa, pb);
166 pa += size;
168 pb += size;
170 while (pc >= pb && (r = compar((void *)pc,(void *) pv)) >= 0)
172 if (r == 0)
174 QSORT_SWAP(pc, pd);
175 pd -= size;
177 pc -= size;
179 if (pb > pc)
181 break;
183 QSORT_SWAP(pb, pc);
184 pb += size;
185 pc -= size;
187 pn = cbase + nmemb*size;
189 s = pa-cbase;
190 st = pb-pa;
191 if(st<s)
193 s = st;
196 if(s>0)
198 qsort_swapfunc(cbase, pb-s, s, swaptype);
201 s = pd-pc;
202 st = pn-pd-size;
203 if(st<s)
205 s = st;
208 if(s>0)
210 qsort_swapfunc(pb, pn-s, s, swaptype);
213 if ((s = pb-pa) > size)
215 gmx_qsort(cbase, s/size, size, compar);
218 if ((s = pd-pc) > size)
220 gmx_qsort(pn-s, s/size, size, compar);
223 #undef QSORT_EXCH
224 #undef QSORT_SWAP
226 return;