+ /* XXX: this is an unsafe optimization of doomy hell */
+ Method method(class_getInstanceMethod([[self objectAtIndex:0] class], selector));
+ _assert(method != NULL);
+ uint32_t (*imp)(id, SEL, id) = reinterpret_cast<uint32_t (*)(id, SEL, id)>(method_getImplementation(method));
+ _assert(imp != NULL);
+#endif
+
+ struct RadixItem_ *swap(new RadixItem_[count * 2]);
+
+ for (size_t i(0); i != count; ++i) {
+ RadixItem_ &item(swap[i]);
+ item.index = i;
+
+ id object([self objectAtIndex:i]);
+
+#if 0
+ [invocation setTarget:object];
+ [invocation invoke];
+ [invocation getReturnValue:&item.key];
+#else
+ item.key = imp(object, selector, object);
+#endif
+ }
+
+ RadixSort_(self, count, swap);
+}
+
+- (void) radixSortUsingFunction:(SKRadixFunction)function withContext:(void *)argument {
+ size_t count([self count]);
+ struct RadixItem_ *swap(new RadixItem_[count * 2]);
+
+ for (size_t i(0); i != count; ++i) {
+ RadixItem_ &item(swap[i]);
+ item.index = i;
+
+ id object([self objectAtIndex:i]);
+ item.key = function(object, argument);
+ }
+
+ RadixSort_(self, count, swap);
+}
+
+@end
+/* }}} */
+/* Insertion Sort {{{ */
+
+CFIndex SKBSearch_(const void *element, CFIndex elementSize, const void *list, CFIndex count, CFComparatorFunction comparator, void *context) {
+ const char *ptr = (const char *)list;
+ while (0 < count) {
+ CFIndex half = count / 2;
+ const char *probe = ptr + elementSize * half;
+ CFComparisonResult cr = comparator(element, probe, context);
+ if (0 == cr) return (probe - (const char *)list) / elementSize;
+ ptr = (cr < 0) ? ptr : probe + elementSize;
+ count = (cr < 0) ? half : (half + (count & 1) - 1);
+ }
+ return (ptr - (const char *)list) / elementSize;
+}
+
+CFIndex CFBSearch_(const void *element, CFIndex elementSize, const void *list, CFIndex count, CFComparatorFunction comparator, void *context) {
+ const char *ptr = (const char *)list;
+ while (0 < count) {
+ CFIndex half = count / 2;
+ const char *probe = ptr + elementSize * half;
+ CFComparisonResult cr = comparator(element, probe, context);
+ if (0 == cr) return (probe - (const char *)list) / elementSize;
+ ptr = (cr < 0) ? ptr : probe + elementSize;
+ count = (cr < 0) ? half : (half + (count & 1) - 1);
+ }
+ return (ptr - (const char *)list) / elementSize;
+}
+
+void CFArrayInsertionSortValues(CFMutableArrayRef array, CFRange range, CFComparatorFunction comparator, void *context) {
+ if (range.length == 0)
+ return;
+ const void **values(new const void *[range.length]);
+ CFArrayGetValues(array, range, values);
+
+#if HistogramInsertionSort
+ uint32_t total(0), *offsets(new uint32_t[range.length]);
+#endif
+
+ for (CFIndex index(1); index != range.length; ++index) {
+ const void *value(values[index]);
+ //CFIndex correct(SKBSearch_(&value, sizeof(const void *), values, index, comparator, context));
+ CFIndex correct(index);
+ while (comparator(value, values[correct - 1], context) == kCFCompareLessThan)
+ if (--correct == 0)
+ break;
+ if (correct != index) {
+ size_t offset(index - correct);
+#if HistogramInsertionSort
+ total += offset;
+ ++offsets[offset];
+ if (offset > 10)
+ NSLog(@"Heavy Insertion Displacement: %u = %@", offset, value);
+#endif
+ memmove(values + correct + 1, values + correct, sizeof(const void *) * offset);
+ values[correct] = value;
+ }
+ }
+
+ CFArrayReplaceValues(array, range, values, range.length);
+ delete [] values;
+
+#if HistogramInsertionSort
+ for (CFIndex index(0); index != range.length; ++index)
+ if (offsets[index] != 0)
+ NSLog(@"Insertion Displacement [%u]: %u", index, offsets[index]);
+ NSLog(@"Average Insertion Displacement: %f", double(total) / range.length);
+ delete [] offsets;