aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorPaul Eggert2020-08-15 10:48:37 -0700
committerPaul Eggert2020-08-15 11:19:51 -0700
commitb467bb531e1ab0eed57e1889004d2115e80e4292 (patch)
tree844d23f28d438f66dd8659dec46baf081722888f /src
parente97def2bbce7777d3afc916a5aa4d951fab5f3f4 (diff)
downloademacs-b467bb531e1ab0eed57e1889004d2115e80e4292.tar.gz
emacs-b467bb531e1ab0eed57e1889004d2115e80e4292.zip
Minimize ‘equal’ calls in (delete x vector)
* src/fns.c (Fdelete): When deleting from a vector, call Fequal only once per vector element. This is faster when Fequal is slow, and avoids the need to preinitialize the vector result. Finish when the result is exhausted, not when the input is exhausted; the two are equivalent but the former may be faster. * test/src/fns-tests.el (test-vector-delete): New test.
Diffstat (limited to 'src')
-rw-r--r--src/fns.c38
1 files changed, 29 insertions, 9 deletions
diff --git a/src/fns.c b/src/fns.c
index c89bd8144e7..069edbe90e2 100644
--- a/src/fns.c
+++ b/src/fns.c
@@ -1747,22 +1747,42 @@ changing the value of a sequence `foo'. */)
1747{ 1747{
1748 if (VECTORP (seq)) 1748 if (VECTORP (seq))
1749 { 1749 {
1750 ptrdiff_t i, n; 1750 ptrdiff_t n = 0;
1751 ptrdiff_t size = ASIZE (seq);
1752 ptrdiff_t neqbits_words = ((size + BITS_PER_BITS_WORD - 1)
1753 / BITS_PER_BITS_WORD);
1754 USE_SAFE_ALLOCA;
1755 bits_word *neqbits = SAFE_ALLOCA (neqbits_words * sizeof *neqbits);
1756 bits_word neqword = 0;
1751 1757
1752 for (i = n = 0; i < ASIZE (seq); ++i) 1758 for (ptrdiff_t i = 0; i < size; i++)
1753 if (NILP (Fequal (AREF (seq, i), elt))) 1759 {
1754 ++n; 1760 bool neq = NILP (Fequal (AREF (seq, i), elt));
1761 n += neq;
1762 neqbits[i / BITS_PER_BITS_WORD] = neqword = (neqword << 1) + neq;
1763 }
1755 1764
1756 if (n != ASIZE (seq)) 1765 if (n != size)
1757 { 1766 {
1758 struct Lisp_Vector *p = allocate_nil_vector (n); 1767 struct Lisp_Vector *p = allocate_vector (n);
1759 1768
1760 for (i = n = 0; i < ASIZE (seq); ++i) 1769 if (n != 0)
1761 if (NILP (Fequal (AREF (seq, i), elt))) 1770 {
1762 p->contents[n++] = AREF (seq, i); 1771 ptrdiff_t j = 0;
1772 for (ptrdiff_t i = 0; ; i++)
1773 if (neqbits[i / BITS_PER_BITS_WORD]
1774 & ((bits_word) 1 << (i % BITS_PER_BITS_WORD)))
1775 {
1776 p->contents[j++] = AREF (seq, i);
1777 if (j == n)
1778 break;
1779 }
1780 }
1763 1781
1764 XSETVECTOR (seq, p); 1782 XSETVECTOR (seq, p);
1765 } 1783 }
1784
1785 SAFE_FREE ();
1766 } 1786 }
1767 else if (STRINGP (seq)) 1787 else if (STRINGP (seq))
1768 { 1788 {