2 *******************************************************************************
4 * Copyright (C) 2003, International Business Machines
5 * Corporation and others. All Rights Reserved.
7 *******************************************************************************
8 * file name: uarrsort.c
10 * tab size: 8 (not used)
13 * created on: 2003aug04
14 * created by: Markus W. Scherer
16 * Internal function for sorting arrays.
19 #include "unicode/utypes.h"
24 MIN_QSORT
=9, /* from Knuth */
28 /* UComparator convenience implementations ---------------------------------- */
30 U_CAPI
int32_t U_EXPORT2
31 uprv_uint16Comparator(const void *context
, const void *left
, const void *right
) {
32 return (int32_t)*(const uint16_t *)left
- (int32_t)*(const uint16_t *)right
;
35 U_CAPI
int32_t U_EXPORT2
36 uprv_int32Comparator(const void *context
, const void *left
, const void *right
) {
37 return *(const int32_t *)left
- *(const int32_t *)right
;
40 U_CAPI
int32_t U_EXPORT2
41 uprv_uint32Comparator(const void *context
, const void *left
, const void *right
) {
42 uint32_t l
=*(const uint32_t *)left
, r
=*(const uint32_t *)right
;
44 /* compare directly because (l-r) would overflow the int32_t result */
54 /* Straight insertion sort from Knuth vol. III, pg. 81 ---------------------- */
57 doInsertionSort(char *array
, int32_t start
, int32_t limit
, int32_t itemSize
,
58 UComparator
*cmp
, const void *context
, void *pv
) {
61 for(j
=start
+1; j
<limit
; ++j
) {
63 uprv_memcpy(pv
, array
+j
*itemSize
, itemSize
);
65 for(i
=j
; i
>start
; --i
) {
66 if(/* v>=array[i-1] */ cmp(context
, pv
, array
+(i
-1)*itemSize
)>=0) {
70 /* array[i]=array[i-1]; */
71 uprv_memcpy(array
+i
*itemSize
, array
+(i
-1)*itemSize
, itemSize
);
76 uprv_memcpy(array
+i
*itemSize
, pv
, itemSize
);
82 insertionSort(char *array
, int32_t length
, int32_t itemSize
,
83 UComparator
*cmp
, const void *context
, UErrorCode
*pErrorCode
) {
84 UAlignedMemory v
[STACK_ITEM_SIZE
/sizeof(UAlignedMemory
)+1];
87 /* allocate an intermediate item variable (v) */
88 if(itemSize
<=STACK_ITEM_SIZE
) {
91 pv
=uprv_malloc(itemSize
);
93 *pErrorCode
=U_MEMORY_ALLOCATION_ERROR
;
98 doInsertionSort(array
, 0, length
, itemSize
, cmp
, context
, pv
);
105 /* QuickSort ---------------------------------------------------------------- */
108 * This implementation is semi-recursive:
109 * It recurses for the smaller sub-array to shorten the recursion depth,
110 * and loops for the larger sub-array.
112 * Loosely after QuickSort algorithms in
114 * Algorithmen und Datenstrukturen mit Modula-2
115 * B.G. Teubner Stuttgart
120 subQuickSort(char *array
, int32_t start
, int32_t limit
, int32_t itemSize
,
121 UComparator
*cmp
, const void *context
,
122 void *px
, void *pw
) {
125 /* start and left are inclusive, limit and right are exclusive */
127 if((start
+MIN_QSORT
)>=limit
) {
128 doInsertionSort(array
, start
, limit
, itemSize
, cmp
, context
, px
);
135 /* x=array[middle] */
136 uprv_memcpy(px
, array
+((start
+limit
)/2)*itemSize
, itemSize
);
139 while(/* array[left]<x */
140 cmp(context
, array
+left
*itemSize
, px
)<0
144 while(/* x<array[right-1] */
145 cmp(context
, px
, array
+(right
-1)*itemSize
)<0
150 /* swap array[left] and array[right-1] via w; ++left; --right */
155 uprv_memcpy(pw
, array
+left
*itemSize
, itemSize
);
156 uprv_memcpy(array
+left
*itemSize
, array
+right
*itemSize
, itemSize
);
157 uprv_memcpy(array
+right
*itemSize
, pw
, itemSize
);
164 /* sort sub-arrays */
165 if((right
-start
)<(limit
-left
)) {
166 /* sort [start..right[ */
167 if(start
<(right
-1)) {
168 subQuickSort(array
, start
, right
, itemSize
, cmp
, context
, px
, pw
);
171 /* sort [left..limit[ */
174 /* sort [left..limit[ */
176 subQuickSort(array
, left
, limit
, itemSize
, cmp
, context
, px
, pw
);
179 /* sort [start..right[ */
182 } while(start
<(limit
-1));
186 quickSort(char *array
, int32_t length
, int32_t itemSize
,
187 UComparator
*cmp
, const void *context
, UErrorCode
*pErrorCode
) {
188 UAlignedMemory xw
[(2*STACK_ITEM_SIZE
)/sizeof(UAlignedMemory
)+1];
191 /* allocate two intermediate item variables (x and w) */
192 if(itemSize
<=STACK_ITEM_SIZE
) {
195 p
=uprv_malloc(2*itemSize
);
197 *pErrorCode
=U_MEMORY_ALLOCATION_ERROR
;
202 subQuickSort(array
, 0, length
, itemSize
,
203 cmp
, context
, p
, (char *)p
+itemSize
);
210 /* uprv_sortArray() API ----------------------------------------------------- */
213 * Check arguments, select an appropriate implementation,
214 * cast the array to char * so that array+i*itemSize works.
216 U_CAPI
void U_EXPORT2
217 uprv_sortArray(void *array
, int32_t length
, int32_t itemSize
,
218 UComparator
*cmp
, const void *context
,
219 UBool sortStable
, UErrorCode
*pErrorCode
) {
220 if(pErrorCode
==NULL
|| U_FAILURE(*pErrorCode
)) {
223 if((length
>0 && array
==NULL
) || length
<0 || itemSize
<=0 || cmp
==NULL
) {
224 *pErrorCode
=U_ILLEGAL_ARGUMENT_ERROR
;
230 } else if(length
<MIN_QSORT
|| sortStable
) {
231 insertionSort((char *)array
, length
, itemSize
, cmp
, context
, pErrorCode
);
232 /* could add heapSort or similar for stable sorting of longer arrays */
234 quickSort((char *)array
, length
, itemSize
, cmp
, context
, pErrorCode
);