/* Stably sort LIST using PREDICATE. This converts the list to a
- vector, sorts the vector using the TIMSORT algorithm, and converts
- back to a list. */
+ vector, sorts the vector using the TIMSORT algorithm, and returns
+ the result converted back to a list. The input list is
+ destructively reused to hold the sorted result.*/
static Lisp_Object
sort_list (Lisp_Object list, Lisp_Object predicate)
static void
sort_vector (Lisp_Object vector, Lisp_Object predicate)
{
- ptrdiff_t len = ASIZE (vector);
- if (len < 2)
+ ptrdiff_t length = ASIZE (vector);
+ if (length < 2)
return;
- tim_sort (predicate, XVECTOR (vector)->contents, len);
+ tim_sort (predicate, XVECTOR (vector)->contents, length);
}
DEFUN ("sort", Fsort, Ssort, 2, 2, 0,
}
Lisp_Object tem;
- if (inorder (pred, Fcar (l1), Fcar (l2)))
+ if (!NILP (call2 (pred, Fcar (l1), Fcar (l2))))
{
tem = l1;
l1 = Fcdr (l1);
which is passed around as an argument to all the subroutines. A
"stretch" structure includes a pointer to the run BASE of length
LEN along with its POWER (a computed integer used by the powersort
- merge strategy that depends on this run and the succeeding run. */
+ merge strategy that depends on this run and the succeeding run.) */
#include <config.h>
Lisp_Object **src;
Lisp_Object **dst;
ptrdiff_t *size;
- int order;
+ int order; /* -1 while in merge_lo; +1 while in merg_hi; 0 otherwise. */
};
ptrdiff_t min_gallop;
/* 'A' is temporary storage, able to hold ALLOCED elements, to help
- with merges. If temporary storage is passed to the sorting entry
- function, 'A' will point to it. Otherwise 'A' initially points
- to TEMPARRAY, and subsequently to newly allocated memory if
- needed. */
+ with merges. 'A' initially points to TEMPARRAY, and subsequently
+ to newly allocated memory if needed. */
Lisp_Object *a;
ptrdiff_t alloced;
/* INORDER returns true iff (PREDICATE A B) is non-nil. */
-inline bool
+INLINE bool
inorder (const Lisp_Object predicate, const Lisp_Object a, const Lisp_Object b)
{
return !NILP (call2 (predicate, a, b));
Lisp_Object *l = lo;
Lisp_Object *r = start;
Lisp_Object pivot = *r;
- Lisp_Object *p;
eassume (l < r);
do {
- p = l + ((r - l) >> 1);
+ Lisp_Object *p = l + ((r - l) >> 1);
if (inorder (pred, pivot, *p))
r = p;
else
l = p + 1;
} while (l < r);
eassume (l == r);
- for (p = start; p > l; --p)
+ for (Lisp_Object *p = start; p > l; --p)
p[0] = p[-1];
*l = pivot;
}
cycles copying the old data. We just free and alloc
again. */
xfree (ms->a);
- ms->a = NULL;
}
- ms->a = (Lisp_Object *) xmalloc (need * word_size);
- if (ms->a != NULL)
- ms->alloced = need;
+ ms->a = xmalloc (need * word_size);
+ ms->alloced = need;
+}
+
+
+INLINE void
+needmem (merge_state *ms, ptrdiff_t na)
+{
+ if (na > ms->alloced)
+ merge_getmem (ms, na);
}
eassume (ms && ssa && ssb && na > 0 && nb > 0);
eassume (ssa + na == ssb);
- na <= ms->alloced ? 0 : merge_getmem (ms, na);
-
+ needmem (ms, na);
memcpy (ms->a, ssa, na * word_size);
Lisp_Object *dest = ssa;
ssa = ms->a;
eassume (ms && ssa && ssb && na > 0 && nb > 0);
eassume (ssa + na == ssb);
- nb <= ms->alloced ? 0 : merge_getmem(ms, nb);
+ needmem (ms, nb);
Lisp_Object *dest = ssb;
dest += nb - 1;
memcpy(ms->a, ssb, nb * word_size);
static void
reverse_vector (Lisp_Object *s, const ptrdiff_t n)
{
- for (ptrdiff_t i = 0; i < n / 2; i++)
+ for (ptrdiff_t i = 0; i < n >> 1; i++)
{
Lisp_Object tem = s[i];
s[i] = s[n - i - 1];
merge_init (&ms, length, lo, predicate);
- if (length < 2)
- return;
/* March over the array once, left to right, finding natural runs,
and extending short natural runs to minrun elements. */
eassume (ms.pending[0].len == length);
lo = ms.pending[0].base;
- if (ms.a != ms.temparray && ms.alloced <= ms.listlen >> 1)
+ if (ms.a != ms.temparray)
unbind_to (ms.count, Qnil);
}