00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #include <config.h>
00024
00025 #include <drizzled/internal/my_sys.h>
00026 #include <drizzled/internal/m_string.h>
00027
00028 namespace drizzled {
00029 namespace internal {
00030
00031
00032 #ifdef QSORT_EXTRA_CMP_ARGUMENT
00033 #define CMP(A,B) ((*cmp)(cmp_argument,(A),(B)))
00034 #else
00035 #define CMP(A,B) ((*cmp)((A),(B)))
00036 #endif
00037
00038 #define SWAP(A, B, size,swap_ptrs) \
00039 do { \
00040 if (swap_ptrs) \
00041 { \
00042 char **a = (char**) (A), **b = (char**) (B); \
00043 char *tmp = *a; *a++ = *b; *b++ = tmp; \
00044 } \
00045 else \
00046 { \
00047 char *a = (A), *b = (B); \
00048 char *end= a+size; \
00049 do \
00050 { \
00051 char tmp = *a; *a++ = *b; *b++ = tmp; \
00052 } while (a < end); \
00053 } \
00054 } while (0)
00055
00056
00057 #define MEDIAN(low, mid, high) \
00058 { \
00059 if (CMP(high,low) < 0) \
00060 SWAP(high, low, size, ptr_cmp); \
00061 if (CMP(mid, low) < 0) \
00062 SWAP(mid, low, size, ptr_cmp); \
00063 else if (CMP(high, mid) < 0) \
00064 SWAP(mid, high, size, ptr_cmp); \
00065 }
00066
00067
00068
00069 typedef struct st_stack
00070 {
00071 char *low,*high;
00072 } stack_node;
00073
00074 #define PUSH(LOW,HIGH) {stack_ptr->low = LOW; stack_ptr++->high = HIGH;}
00075 #define POP(LOW,HIGH) {LOW = (--stack_ptr)->low; HIGH = stack_ptr->high;}
00076
00077
00078 #define STACK_SIZE (8 * sizeof(unsigned long int))
00079 #define THRESHOLD_FOR_INSERT_SORT 10
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091 #ifdef QSORT_EXTRA_CMP_ARGUMENT
00092 void my_qsort2(void *base_ptr, size_t count, size_t size,
00093 qsort2_cmp cmp, void *cmp_argument)
00094 #else
00095 void my_qsort(void *base_ptr, size_t count, size_t size,
00096 qsort_cmp cmp)
00097 #endif
00098 {
00099 char *low, *high, *pivot;
00100 stack_node stack[STACK_SIZE], *stack_ptr;
00101 bool ptr_cmp;
00102
00103
00104 if (count <= 1)
00105 return;
00106
00107 low = (char*) base_ptr;
00108 high = low+ size * (count - 1);
00109 stack_ptr = stack + 1;
00110 #ifdef HAVE_VALGRIND
00111
00112 stack[0].low=stack[0].high=0;
00113 #endif
00114 pivot = (char *) malloc(size);
00115 ptr_cmp= size == sizeof(char*) && !((low - (char*) 0)& (sizeof(char*)-1));
00116
00117
00118 do
00119 {
00120 char *low_ptr, *high_ptr, *mid;
00121
00122 count=((size_t) (high - low) / size)+1;
00123
00124 if (count < THRESHOLD_FOR_INSERT_SORT)
00125 {
00126 for (low_ptr = low + size; low_ptr <= high; low_ptr += size)
00127 {
00128 char *ptr;
00129 for (ptr = low_ptr; ptr > low && CMP(ptr - size, ptr) > 0;
00130 ptr -= size)
00131 SWAP(ptr, ptr - size, size, ptr_cmp);
00132 }
00133 POP(low, high);
00134 continue;
00135 }
00136
00137
00138 mid= low + size * (count >> 1);
00139 if (count > 40)
00140 {
00141 size_t step = size* (count / 8);
00142 MEDIAN(low, low + step, low+step*2);
00143 MEDIAN(mid - step, mid, mid+step);
00144 MEDIAN(high - 2 * step, high-step, high);
00145
00146 MEDIAN(low+step, mid, high-step);
00147 low_ptr = low;
00148 high_ptr = high;
00149 }
00150 else
00151 {
00152 MEDIAN(low, mid, high);
00153
00154 low_ptr = low + size;
00155 high_ptr = high - size;
00156 }
00157 memcpy(pivot, mid, size);
00158
00159 do
00160 {
00161 while (CMP(low_ptr, pivot) < 0)
00162 low_ptr += size;
00163 while (CMP(pivot, high_ptr) < 0)
00164 high_ptr -= size;
00165
00166 if (low_ptr < high_ptr)
00167 {
00168 SWAP(low_ptr, high_ptr, size, ptr_cmp);
00169 low_ptr += size;
00170 high_ptr -= size;
00171 }
00172 else
00173 {
00174 if (low_ptr == high_ptr)
00175 {
00176 low_ptr += size;
00177 high_ptr -= size;
00178 }
00179 break;
00180 }
00181 }
00182 while (low_ptr <= high_ptr);
00183
00184
00185
00186
00187
00188
00189
00190
00191 if ((int) (high_ptr - low) <= 0)
00192 {
00193 if ((int) (high - low_ptr) <= 0)
00194 {
00195 POP(low, high);
00196 }
00197 else
00198 low = low_ptr;
00199 }
00200 else if ((int) (high - low_ptr) <= 0)
00201 high = high_ptr;
00202 else if ((high_ptr - low) > (high - low_ptr))
00203 {
00204 PUSH(low, high_ptr);
00205 low = low_ptr;
00206 }
00207 else
00208 {
00209 PUSH(low_ptr, high);
00210 high = high_ptr;
00211 }
00212 } while (stack_ptr > stack);
00213 free(pivot);
00214 return;
00215 }
00216
00217 }
00218 }