mirror of
https://github.com/ccxvii/mujs.git
synced 2026-02-05 17:29:43 +08:00
Issue 193 and issue 194: Always use heapsort instead of quicksort.
The quicksort implementation behaves badly when presented with non-deterministic comparison functions. The heapsort is more robust and has fewer edge cases to worry about in the face of an adversarial comparison function.
This commit is contained in:
47
jsarray.c
47
jsarray.c
@@ -346,8 +346,6 @@ static void Ap_sort_swap(js_State *J, int idx_a, int idx_b)
|
||||
}
|
||||
}
|
||||
|
||||
#if JS_HEAPSORT
|
||||
|
||||
/* A bottom-up/bouncing heapsort implementation */
|
||||
|
||||
static int Ap_sort_leaf(js_State *J, int i, int end)
|
||||
@@ -390,46 +388,6 @@ static void Ap_sort_heapsort(js_State *J, int n)
|
||||
}
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
static int Ap_sort_quicksort_partition(js_State *J, int a, int b)
|
||||
{
|
||||
int pivot = (a + b) >> 1;
|
||||
while (a <= b) {
|
||||
while (Ap_sort_cmp(J, a, pivot) < 0)
|
||||
++a;
|
||||
while (Ap_sort_cmp(J, b, pivot) > 0)
|
||||
--b;
|
||||
if (a <= b) {
|
||||
Ap_sort_swap(J, a, b);
|
||||
++a;
|
||||
--b;
|
||||
}
|
||||
}
|
||||
return a;
|
||||
}
|
||||
|
||||
static void Ap_sort_quicksort(js_State *J, int a, int b)
|
||||
{
|
||||
int i, j, m;
|
||||
|
||||
/* insertion sort small fragments */
|
||||
if (b - a < 8) {
|
||||
for (i = a+1; i < b; ++i)
|
||||
for (j = i; j > a && Ap_sort_cmp(J, j-1, j) > 0; --j)
|
||||
Ap_sort_swap(J, j-1, j);
|
||||
return;
|
||||
}
|
||||
|
||||
m = Ap_sort_quicksort_partition(J, a, b);
|
||||
if (a < m - 1)
|
||||
Ap_sort_quicksort(J, a, m - 1);
|
||||
if (m < b)
|
||||
Ap_sort_quicksort(J, m, b);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
static void Ap_sort(js_State *J)
|
||||
{
|
||||
int len;
|
||||
@@ -446,12 +404,7 @@ static void Ap_sort(js_State *J)
|
||||
if (len >= INT_MAX)
|
||||
js_rangeerror(J, "array is too large to sort");
|
||||
|
||||
|
||||
#if JS_HEAPSORT
|
||||
Ap_sort_heapsort(J, len);
|
||||
#else
|
||||
Ap_sort_quicksort(J, 0, len - 1);
|
||||
#endif
|
||||
|
||||
js_copy(J, 0);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user