michael@0: /* michael@0: ******************************************************************************* michael@0: * michael@0: * Copyright (C) 2003-2013, International Business Machines michael@0: * Corporation and others. All Rights Reserved. michael@0: * michael@0: ******************************************************************************* michael@0: * file name: uarrsort.c michael@0: * encoding: US-ASCII michael@0: * tab size: 8 (not used) michael@0: * indentation:4 michael@0: * michael@0: * created on: 2003aug04 michael@0: * created by: Markus W. Scherer michael@0: * michael@0: * Internal function for sorting arrays. michael@0: */ michael@0: michael@0: #include "unicode/utypes.h" michael@0: #include "cmemory.h" michael@0: #include "uarrsort.h" michael@0: michael@0: enum { michael@0: /** michael@0: * "from Knuth" michael@0: * michael@0: * A binary search over 8 items performs 4 comparisons: michael@0: * log2(8)=3 to subdivide, +1 to check for equality. michael@0: * A linear search over 8 items on average also performs 4 comparisons. michael@0: */ michael@0: MIN_QSORT=9, michael@0: STACK_ITEM_SIZE=200 michael@0: }; michael@0: michael@0: /* UComparator convenience implementations ---------------------------------- */ michael@0: michael@0: U_CAPI int32_t U_EXPORT2 michael@0: uprv_uint16Comparator(const void *context, const void *left, const void *right) { michael@0: return (int32_t)*(const uint16_t *)left - (int32_t)*(const uint16_t *)right; michael@0: } michael@0: michael@0: U_CAPI int32_t U_EXPORT2 michael@0: uprv_int32Comparator(const void *context, const void *left, const void *right) { michael@0: return *(const int32_t *)left - *(const int32_t *)right; michael@0: } michael@0: michael@0: U_CAPI int32_t U_EXPORT2 michael@0: uprv_uint32Comparator(const void *context, const void *left, const void *right) { michael@0: uint32_t l=*(const uint32_t *)left, r=*(const uint32_t *)right; michael@0: michael@0: /* compare directly because (l-r) would overflow the int32_t result */ michael@0: if(lr */ { michael@0: return 1; michael@0: } michael@0: } michael@0: michael@0: /* Insertion sort using binary search --------------------------------------- */ michael@0: michael@0: U_CAPI int32_t U_EXPORT2 michael@0: uprv_stableBinarySearch(char *array, int32_t limit, void *item, int32_t itemSize, michael@0: UComparator *cmp, const void *context) { michael@0: int32_t start=0; michael@0: UBool found=FALSE; michael@0: michael@0: /* Binary search until we get down to a tiny sub-array. */ michael@0: while((limit-start)>=MIN_QSORT) { michael@0: int32_t i=(start+limit)/2; michael@0: int32_t diff=cmp(context, item, array+i*itemSize); michael@0: if(diff==0) { michael@0: /* michael@0: * Found the item. We look for the *last* occurrence of such michael@0: * an item, for stable sorting. michael@0: * If we knew that there will be only few equal items, michael@0: * we could break now and enter the linear search. michael@0: * However, if there are many equal items, then it should be michael@0: * faster to continue with the binary search. michael@0: * It seems likely that we either have all unique items michael@0: * (where found will never become TRUE in the insertion sort) michael@0: * or potentially many duplicates. michael@0: */ michael@0: found=TRUE; michael@0: start=i+1; michael@0: } else if(diff<0) { michael@0: limit=i; michael@0: } else { michael@0: start=i; michael@0: } michael@0: } michael@0: michael@0: /* Linear search over the remaining tiny sub-array. */ michael@0: while(start=limit) { michael@0: doInsertionSort(array+start*itemSize, limit-start, itemSize, cmp, context, px); michael@0: break; michael@0: } michael@0: michael@0: left=start; michael@0: right=limit; michael@0: michael@0: /* x=array[middle] */ michael@0: uprv_memcpy(px, array+((start+limit)/2)*itemSize, itemSize); michael@0: michael@0: do { michael@0: while(/* array[left]0 && array==NULL) || length<0 || itemSize<=0 || cmp==NULL) { michael@0: *pErrorCode=U_ILLEGAL_ARGUMENT_ERROR; michael@0: return; michael@0: } michael@0: michael@0: if(length<=1) { michael@0: return; michael@0: } else if(length