/* ******************************************************************************* * * Copyright (C) 2003, International Business Machines * Corporation and others. All Rights Reserved. * ******************************************************************************* * file name: uarrsort.c * encoding: US-ASCII * tab size: 8 (not used) * indentation:4 * * created on: 2003aug04 * created by: Markus W. Scherer * * Internal function for sorting arrays. */ #include "unicode/utypes.h" #include "cmemory.h" #include "uarrsort.h" enum { MIN_QSORT=9, /* from Knuth */ STACK_ITEM_SIZE=200 }; /* UComparator convenience implementations ---------------------------------- */ U_CAPI int32_t U_EXPORT2 uprv_uint16Comparator(const void *context, const void *left, const void *right) { return (int32_t)*(const uint16_t *)left - (int32_t)*(const uint16_t *)right; } U_CAPI int32_t U_EXPORT2 uprv_int32Comparator(const void *context, const void *left, const void *right) { return *(const int32_t *)left - *(const int32_t *)right; } U_CAPI int32_t U_EXPORT2 uprv_uint32Comparator(const void *context, const void *left, const void *right) { uint32_t l=*(const uint32_t *)left, r=*(const uint32_t *)right; /* compare directly because (l-r) would overflow the int32_t result */ if(lr */ { return 1; } } /* Straight insertion sort from Knuth vol. III, pg. 81 ---------------------- */ static void doInsertionSort(char *array, int32_t start, int32_t limit, int32_t itemSize, UComparator *cmp, const void *context, void *pv) { int32_t i, j; for(j=start+1; jstart; --i) { if(/* v>=array[i-1] */ cmp(context, pv, array+(i-1)*itemSize)>=0) { break; } /* array[i]=array[i-1]; */ uprv_memcpy(array+i*itemSize, array+(i-1)*itemSize, itemSize); } if(i!=j) { /* array[i]=v; */ uprv_memcpy(array+i*itemSize, pv, itemSize); } } } static void insertionSort(char *array, int32_t length, int32_t itemSize, UComparator *cmp, const void *context, UErrorCode *pErrorCode) { UAlignedMemory v[STACK_ITEM_SIZE/sizeof(UAlignedMemory)+1]; void *pv; /* allocate an intermediate item variable (v) */ if(itemSize<=STACK_ITEM_SIZE) { pv=v; } else { pv=uprv_malloc(itemSize); if(pv==NULL) { *pErrorCode=U_MEMORY_ALLOCATION_ERROR; return; } } doInsertionSort(array, 0, length, itemSize, cmp, context, pv); if(pv!=v) { uprv_free(pv); } } /* QuickSort ---------------------------------------------------------------- */ /* * This implementation is semi-recursive: * It recurses for the smaller sub-array to shorten the recursion depth, * and loops for the larger sub-array. * * Loosely after QuickSort algorithms in * Niklaus Wirth * Algorithmen und Datenstrukturen mit Modula-2 * B.G. Teubner Stuttgart * 4. Auflage 1986 * ISBN 3-519-02260-5 */ static void subQuickSort(char *array, int32_t start, int32_t limit, int32_t itemSize, UComparator *cmp, const void *context, void *px, void *pw) { int32_t left, right; /* start and left are inclusive, limit and right are exclusive */ do { if((start+MIN_QSORT)>=limit) { doInsertionSort(array, start, limit, itemSize, cmp, context, px); break; } left=start; right=limit; /* x=array[middle] */ uprv_memcpy(px, array+((start+limit)/2)*itemSize, itemSize); do { while(/* array[left]0 && array==NULL) || length<0 || itemSize<=0 || cmp==NULL) { *pErrorCode=U_ILLEGAL_ARGUMENT_ERROR; return; } if(length<=1) { return; } else if(length