diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/ChangeLog | 11 | ||||
| -rw-r--r-- | src/alloc.c | 11 | ||||
| -rw-r--r-- | src/fns.c | 99 | ||||
| -rw-r--r-- | src/lisp.h | 2 |
4 files changed, 116 insertions, 7 deletions
diff --git a/src/ChangeLog b/src/ChangeLog index 9b3c3d0bd66..c24ca69536f 100644 --- a/src/ChangeLog +++ b/src/ChangeLog | |||
| @@ -1,3 +1,14 @@ | |||
| 1 | 2014-08-29 Dmitry Antipov <dmantipov@yandex.ru> | ||
| 2 | |||
| 3 | Add vectors support to Fsort. | ||
| 4 | * fns.c (sort_vector, sort_vector_compare): New functions. | ||
| 5 | (sort_list): Likewise, refactored out of ... | ||
| 6 | (Fsort): ... adjusted user. Mention vectors in docstring. | ||
| 7 | (sort_vector_predicate) [!HAVE_QSORT_R]: New variable. | ||
| 8 | * alloc.c (make_save_int_obj): New function. | ||
| 9 | * lisp.h (enum Lisp_Save_Type): New member SAVE_TYPE_INT_OBJ. | ||
| 10 | (make_save_int_obj): Add prototype. | ||
| 11 | |||
| 1 | 2014-08-28 Ken Brown <kbrown@cornell.edu> | 12 | 2014-08-28 Ken Brown <kbrown@cornell.edu> |
| 2 | 13 | ||
| 3 | Add support for HYBRID_MALLOC, allowing the use of gmalloc before | 14 | Add support for HYBRID_MALLOC, allowing the use of gmalloc before |
diff --git a/src/alloc.c b/src/alloc.c index 9c81ae2eedf..bb47a24d905 100644 --- a/src/alloc.c +++ b/src/alloc.c | |||
| @@ -3610,6 +3610,17 @@ make_save_ptr_int (void *a, ptrdiff_t b) | |||
| 3610 | return val; | 3610 | return val; |
| 3611 | } | 3611 | } |
| 3612 | 3612 | ||
| 3613 | Lisp_Object | ||
| 3614 | make_save_int_obj (ptrdiff_t a, Lisp_Object b) | ||
| 3615 | { | ||
| 3616 | Lisp_Object val = allocate_misc (Lisp_Misc_Save_Value); | ||
| 3617 | struct Lisp_Save_Value *p = XSAVE_VALUE (val); | ||
| 3618 | p->save_type = SAVE_TYPE_INT_OBJ; | ||
| 3619 | p->data[0].integer = a; | ||
| 3620 | p->data[1].object = b; | ||
| 3621 | return val; | ||
| 3622 | } | ||
| 3623 | |||
| 3613 | #if ! (defined USE_X_TOOLKIT || defined USE_GTK) | 3624 | #if ! (defined USE_X_TOOLKIT || defined USE_GTK) |
| 3614 | Lisp_Object | 3625 | Lisp_Object |
| 3615 | make_save_ptr_ptr (void *a, void *b) | 3626 | make_save_ptr_ptr (void *a, void *b) |
| @@ -1846,13 +1846,12 @@ See also the function `nreverse', which is used more often. */) | |||
| 1846 | wrong_type_argument (Qsequencep, seq); | 1846 | wrong_type_argument (Qsequencep, seq); |
| 1847 | return new; | 1847 | return new; |
| 1848 | } | 1848 | } |
| 1849 | 1849 | ||
| 1850 | DEFUN ("sort", Fsort, Ssort, 2, 2, 0, | 1850 | /* Sort LIST using PREDICATE, preserving original order of elements |
| 1851 | doc: /* Sort LIST, stably, comparing elements using PREDICATE. | 1851 | considered as equal. */ |
| 1852 | Returns the sorted list. LIST is modified by side effects. | 1852 | |
| 1853 | PREDICATE is called with two elements of LIST, and should return non-nil | 1853 | static Lisp_Object |
| 1854 | if the first element should sort before the second. */) | 1854 | sort_list (Lisp_Object list, Lisp_Object predicate) |
| 1855 | (Lisp_Object list, Lisp_Object predicate) | ||
| 1856 | { | 1855 | { |
| 1857 | Lisp_Object front, back; | 1856 | Lisp_Object front, back; |
| 1858 | register Lisp_Object len, tem; | 1857 | register Lisp_Object len, tem; |
| @@ -1877,6 +1876,92 @@ if the first element should sort before the second. */) | |||
| 1877 | return merge (front, back, predicate); | 1876 | return merge (front, back, predicate); |
| 1878 | } | 1877 | } |
| 1879 | 1878 | ||
| 1879 | /* Using GNU qsort_r, we can pass this as a parameter. */ | ||
| 1880 | #ifndef HAVE_QSORT_R | ||
| 1881 | static Lisp_Object sort_vector_predicate; | ||
| 1882 | #endif | ||
| 1883 | |||
| 1884 | /* Comparison function called by qsort. */ | ||
| 1885 | |||
| 1886 | static int | ||
| 1887 | #ifdef HAVE_QSORT_R | ||
| 1888 | sort_vector_compare (const void *p, const void *q, void *arg) | ||
| 1889 | #else | ||
| 1890 | sort_vector_compare (const void *p, const void *q) | ||
| 1891 | #endif /* HAVE_QSORT_R */ | ||
| 1892 | { | ||
| 1893 | bool more, less; | ||
| 1894 | Lisp_Object op, oq, vp, vq; | ||
| 1895 | #ifdef HAVE_QSORT_R | ||
| 1896 | Lisp_Object sort_vector_predicate = *(Lisp_Object *) arg; | ||
| 1897 | #endif | ||
| 1898 | |||
| 1899 | op = *(Lisp_Object *) p; | ||
| 1900 | oq = *(Lisp_Object *) q; | ||
| 1901 | vp = XSAVE_OBJECT (op, 1); | ||
| 1902 | vq = XSAVE_OBJECT (oq, 1); | ||
| 1903 | |||
| 1904 | /* Use recorded element index as a secondary key to | ||
| 1905 | preserve original order. Pretty ugly but works. */ | ||
| 1906 | more = NILP (call2 (sort_vector_predicate, vp, vq)); | ||
| 1907 | less = NILP (call2 (sort_vector_predicate, vq, vp)); | ||
| 1908 | return ((more && !less) ? 1 | ||
| 1909 | : ((!more && less) ? -1 | ||
| 1910 | : XSAVE_INTEGER (op, 0) - XSAVE_INTEGER (oq, 0))); | ||
| 1911 | } | ||
| 1912 | |||
| 1913 | /* Sort VECTOR using PREDICATE, preserving original order of elements | ||
| 1914 | considered as equal. */ | ||
| 1915 | |||
| 1916 | static Lisp_Object | ||
| 1917 | sort_vector (Lisp_Object vector, Lisp_Object predicate) | ||
| 1918 | { | ||
| 1919 | ptrdiff_t i; | ||
| 1920 | EMACS_INT len = ASIZE (vector); | ||
| 1921 | Lisp_Object *v = XVECTOR (vector)->contents; | ||
| 1922 | |||
| 1923 | if (len < 2) | ||
| 1924 | return vector; | ||
| 1925 | /* Record original index of each element to make qsort stable. */ | ||
| 1926 | for (i = 0; i < len; i++) | ||
| 1927 | v[i] = make_save_int_obj (i, v[i]); | ||
| 1928 | |||
| 1929 | /* Setup predicate and sort. */ | ||
| 1930 | #ifdef HAVE_QSORT_R | ||
| 1931 | qsort_r (v, len, word_size, sort_vector_compare, (void *) &predicate); | ||
| 1932 | #else | ||
| 1933 | sort_vector_predicate = predicate; | ||
| 1934 | qsort (v, len, word_size, sort_vector_compare); | ||
| 1935 | #endif /* HAVE_QSORT_R */ | ||
| 1936 | |||
| 1937 | /* Discard indexes and restore original elements. */ | ||
| 1938 | for (i = 0; i < len; i++) | ||
| 1939 | { | ||
| 1940 | Lisp_Object save = v[i]; | ||
| 1941 | /* Use explicit free to offload GC. */ | ||
| 1942 | v[i] = XSAVE_OBJECT (save, 1); | ||
| 1943 | free_misc (save); | ||
| 1944 | } | ||
| 1945 | return vector; | ||
| 1946 | } | ||
| 1947 | |||
| 1948 | DEFUN ("sort", Fsort, Ssort, 2, 2, 0, | ||
| 1949 | doc: /* Sort SEQ, stably, comparing elements using PREDICATE. | ||
| 1950 | Returns the sorted sequence. SEQ should be a list or vector. | ||
| 1951 | If SEQ is a list, it is modified by side effects. PREDICATE | ||
| 1952 | is called with two elements of SEQ, and should return non-nil | ||
| 1953 | if the first element should sort before the second. */) | ||
| 1954 | (Lisp_Object seq, Lisp_Object predicate) | ||
| 1955 | { | ||
| 1956 | if (CONSP (seq)) | ||
| 1957 | seq = sort_list (seq, predicate); | ||
| 1958 | else if (VECTORP (seq)) | ||
| 1959 | seq = sort_vector (seq, predicate); | ||
| 1960 | else if (!NILP (seq)) | ||
| 1961 | wrong_type_argument (Qarrayp, seq); | ||
| 1962 | return seq; | ||
| 1963 | } | ||
| 1964 | |||
| 1880 | Lisp_Object | 1965 | Lisp_Object |
| 1881 | merge (Lisp_Object org_l1, Lisp_Object org_l2, Lisp_Object pred) | 1966 | merge (Lisp_Object org_l1, Lisp_Object org_l2, Lisp_Object pred) |
| 1882 | { | 1967 | { |
diff --git a/src/lisp.h b/src/lisp.h index 98734a55812..7cbbb299896 100644 --- a/src/lisp.h +++ b/src/lisp.h | |||
| @@ -1989,6 +1989,7 @@ enum Lisp_Save_Type | |||
| 1989 | SAVE_TYPE_OBJ_OBJ_OBJ_OBJ | 1989 | SAVE_TYPE_OBJ_OBJ_OBJ_OBJ |
| 1990 | = SAVE_OBJECT + (SAVE_TYPE_OBJ_OBJ_OBJ << SAVE_SLOT_BITS), | 1990 | = SAVE_OBJECT + (SAVE_TYPE_OBJ_OBJ_OBJ << SAVE_SLOT_BITS), |
| 1991 | SAVE_TYPE_PTR_INT = SAVE_POINTER + (SAVE_INTEGER << SAVE_SLOT_BITS), | 1991 | SAVE_TYPE_PTR_INT = SAVE_POINTER + (SAVE_INTEGER << SAVE_SLOT_BITS), |
| 1992 | SAVE_TYPE_INT_OBJ = SAVE_INTEGER + (SAVE_OBJECT << SAVE_SLOT_BITS), | ||
| 1992 | SAVE_TYPE_PTR_OBJ = SAVE_POINTER + (SAVE_OBJECT << SAVE_SLOT_BITS), | 1993 | SAVE_TYPE_PTR_OBJ = SAVE_POINTER + (SAVE_OBJECT << SAVE_SLOT_BITS), |
| 1993 | SAVE_TYPE_PTR_PTR = SAVE_POINTER + (SAVE_POINTER << SAVE_SLOT_BITS), | 1994 | SAVE_TYPE_PTR_PTR = SAVE_POINTER + (SAVE_POINTER << SAVE_SLOT_BITS), |
| 1994 | SAVE_TYPE_FUNCPTR_PTR_OBJ | 1995 | SAVE_TYPE_FUNCPTR_PTR_OBJ |
| @@ -3773,6 +3774,7 @@ extern Lisp_Object make_save_obj_obj_obj_obj (Lisp_Object, Lisp_Object, | |||
| 3773 | extern Lisp_Object make_save_ptr (void *); | 3774 | extern Lisp_Object make_save_ptr (void *); |
| 3774 | extern Lisp_Object make_save_ptr_int (void *, ptrdiff_t); | 3775 | extern Lisp_Object make_save_ptr_int (void *, ptrdiff_t); |
| 3775 | extern Lisp_Object make_save_ptr_ptr (void *, void *); | 3776 | extern Lisp_Object make_save_ptr_ptr (void *, void *); |
| 3777 | extern Lisp_Object make_save_int_obj (ptrdiff_t, Lisp_Object); | ||
| 3776 | extern Lisp_Object make_save_funcptr_ptr_obj (void (*) (void), void *, | 3778 | extern Lisp_Object make_save_funcptr_ptr_obj (void (*) (void), void *, |
| 3777 | Lisp_Object); | 3779 | Lisp_Object); |
| 3778 | extern Lisp_Object make_save_memory (Lisp_Object *, ptrdiff_t); | 3780 | extern Lisp_Object make_save_memory (Lisp_Object *, ptrdiff_t); |