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 */
|
/* A bottom-up/bouncing heapsort implementation */
|
||||||
|
|
||||||
static int Ap_sort_leaf(js_State *J, int i, int end)
|
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)
|
static void Ap_sort(js_State *J)
|
||||||
{
|
{
|
||||||
int len;
|
int len;
|
||||||
@@ -446,12 +404,7 @@ static void Ap_sort(js_State *J)
|
|||||||
if (len >= INT_MAX)
|
if (len >= INT_MAX)
|
||||||
js_rangeerror(J, "array is too large to sort");
|
js_rangeerror(J, "array is too large to sort");
|
||||||
|
|
||||||
|
|
||||||
#if JS_HEAPSORT
|
|
||||||
Ap_sort_heapsort(J, len);
|
Ap_sort_heapsort(J, len);
|
||||||
#else
|
|
||||||
Ap_sort_quicksort(J, 0, len - 1);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
js_copy(J, 0);
|
js_copy(J, 0);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user