00001 #include "tests/vm/qsort.h"
00002 #include <stdbool.h>
00003 #include <debug.h>
00004 #include <random.h>
00005
00006
00007 static unsigned char
00008 pick_pivot (unsigned char *buf, size_t size)
00009 {
00010 ASSERT (size >= 1);
00011 return buf[random_ulong () % size];
00012 }
00013
00014
00015
00016
00017
00018 static bool
00019 is_partitioned (const unsigned char *array, size_t size,
00020 unsigned char pivot, size_t left_size)
00021 {
00022 size_t i;
00023
00024 for (i = 0; i < left_size; i++)
00025 if (array[i] >= pivot)
00026 return false;
00027
00028 for (; i < size; i++)
00029 if (array[i] < pivot)
00030 return false;
00031
00032 return true;
00033 }
00034
00035
00036 static void
00037 swap (unsigned char *a, unsigned char *b)
00038 {
00039 unsigned char t = *a;
00040 *a = *b;
00041 *b = t;
00042 }
00043
00044
00045
00046
00047 static size_t
00048 partition (unsigned char *array, size_t size, int pivot)
00049 {
00050 size_t left_size = size;
00051 unsigned char *first = array;
00052 unsigned char *last = first + left_size;
00053
00054 for (;;)
00055 {
00056
00057
00058 for (;;)
00059 {
00060 if (first == last)
00061 {
00062 ASSERT (is_partitioned (array, size, pivot, left_size));
00063 return left_size;
00064 }
00065 else if (*first >= pivot)
00066 break;
00067
00068 first++;
00069 }
00070 left_size--;
00071
00072
00073
00074 for (;;)
00075 {
00076 last--;
00077
00078 if (first == last)
00079 {
00080 ASSERT (is_partitioned (array, size, pivot, left_size));
00081 return left_size;
00082 }
00083 else if (*last < pivot)
00084 break;
00085 else
00086 left_size--;
00087 }
00088
00089
00090
00091
00092 swap (first, last);
00093 first++;
00094 }
00095 }
00096
00097
00098
00099 static bool
00100 is_sorted (const unsigned char *buf, size_t size)
00101 {
00102 size_t i;
00103
00104 for (i = 1; i < size; i++)
00105 if (buf[i - 1] > buf[i])
00106 return false;
00107
00108 return true;
00109 }
00110
00111
00112
00113 void
00114 qsort_bytes (unsigned char *buf, size_t size)
00115 {
00116 if (!is_sorted (buf, size))
00117 {
00118 int pivot = pick_pivot (buf, size);
00119
00120 unsigned char *left_half = buf;
00121 size_t left_size = partition (buf, size, pivot);
00122 unsigned char *right_half = left_half + left_size;
00123 size_t right_size = size - left_size;
00124
00125 if (left_size <= right_size)
00126 {
00127 qsort_bytes (left_half, left_size);
00128 qsort_bytes (right_half, right_size);
00129 }
00130 else
00131 {
00132 qsort_bytes (right_half, right_size);
00133 qsort_bytes (left_half, left_size);
00134 }
00135 }
00136 }