diff options
| author | Eli Zaretskii | 2013-09-26 10:37:16 +0300 |
|---|---|---|
| committer | Eli Zaretskii | 2013-09-26 10:37:16 +0300 |
| commit | b87c4ff2817e71ca71b028792200b1e069a95e04 (patch) | |
| tree | bfe00c0655fa02078a9ab2c633ea06d90c4a2064 /src/data.c | |
| parent | bbc108377873aa6ed7cf21c731770103096eea39 (diff) | |
| parent | ba355de014b75ed104da4777f909db70d62f2357 (diff) | |
| download | emacs-b87c4ff2817e71ca71b028792200b1e069a95e04.tar.gz emacs-b87c4ff2817e71ca71b028792200b1e069a95e04.zip | |
Merge from trunk.
Diffstat (limited to 'src/data.c')
| -rw-r--r-- | src/data.c | 545 |
1 files changed, 509 insertions, 36 deletions
diff --git a/src/data.c b/src/data.c index 9f4bd1f1c02..79679bae444 100644 --- a/src/data.c +++ b/src/data.c | |||
| @@ -54,6 +54,7 @@ Lisp_Object Qintegerp, Qwholenump, Qsymbolp, Qlistp, Qconsp; | |||
| 54 | static Lisp_Object Qnatnump; | 54 | static Lisp_Object Qnatnump; |
| 55 | Lisp_Object Qstringp, Qarrayp, Qsequencep, Qbufferp; | 55 | Lisp_Object Qstringp, Qarrayp, Qsequencep, Qbufferp; |
| 56 | Lisp_Object Qchar_or_string_p, Qmarkerp, Qinteger_or_marker_p, Qvectorp; | 56 | Lisp_Object Qchar_or_string_p, Qmarkerp, Qinteger_or_marker_p, Qvectorp; |
| 57 | Lisp_Object Qbool_vector_p; | ||
| 57 | Lisp_Object Qbuffer_or_string_p; | 58 | Lisp_Object Qbuffer_or_string_p; |
| 58 | static Lisp_Object Qkeywordp, Qboundp; | 59 | static Lisp_Object Qkeywordp, Qboundp; |
| 59 | Lisp_Object Qfboundp; | 60 | Lisp_Object Qfboundp; |
| @@ -616,7 +617,7 @@ global value outside of any lexical scope. */) | |||
| 616 | struct Lisp_Buffer_Local_Value *blv = SYMBOL_BLV (sym); | 617 | struct Lisp_Buffer_Local_Value *blv = SYMBOL_BLV (sym); |
| 617 | if (blv->fwd) | 618 | if (blv->fwd) |
| 618 | /* In set_internal, we un-forward vars when their value is | 619 | /* In set_internal, we un-forward vars when their value is |
| 619 | set to Qunbound. */ | 620 | set to Qunbound. */ |
| 620 | return Qt; | 621 | return Qt; |
| 621 | else | 622 | else |
| 622 | { | 623 | { |
| @@ -627,7 +628,7 @@ global value outside of any lexical scope. */) | |||
| 627 | } | 628 | } |
| 628 | case SYMBOL_FORWARDED: | 629 | case SYMBOL_FORWARDED: |
| 629 | /* In set_internal, we un-forward vars when their value is | 630 | /* In set_internal, we un-forward vars when their value is |
| 630 | set to Qunbound. */ | 631 | set to Qunbound. */ |
| 631 | return Qt; | 632 | return Qt; |
| 632 | default: emacs_abort (); | 633 | default: emacs_abort (); |
| 633 | } | 634 | } |
| @@ -1995,7 +1996,7 @@ If the current binding is global (the default), the value is nil. */) | |||
| 1995 | } | 1996 | } |
| 1996 | 1997 | ||
| 1997 | /* This code is disabled now that we use the selected frame to return | 1998 | /* This code is disabled now that we use the selected frame to return |
| 1998 | keyboard-local-values. */ | 1999 | keyboard-local-values. */ |
| 1999 | #if 0 | 2000 | #if 0 |
| 2000 | extern struct terminal *get_terminal (Lisp_Object display, int); | 2001 | extern struct terminal *get_terminal (Lisp_Object display, int); |
| 2001 | 2002 | ||
| @@ -2255,10 +2256,8 @@ bool-vector. IDX starts at 0. */) | |||
| 2255 | 2256 | ||
| 2256 | /* Arithmetic functions */ | 2257 | /* Arithmetic functions */ |
| 2257 | 2258 | ||
| 2258 | enum comparison { equal, notequal, less, grtr, less_or_equal, grtr_or_equal }; | 2259 | Lisp_Object |
| 2259 | 2260 | arithcompare (Lisp_Object num1, Lisp_Object num2, enum Arith_Comparison comparison) | |
| 2260 | static Lisp_Object | ||
| 2261 | arithcompare (Lisp_Object num1, Lisp_Object num2, enum comparison comparison) | ||
| 2262 | { | 2261 | { |
| 2263 | double f1 = 0, f2 = 0; | 2262 | double f1 = 0, f2 = 0; |
| 2264 | bool floatp = 0; | 2263 | bool floatp = 0; |
| @@ -2275,32 +2274,32 @@ arithcompare (Lisp_Object num1, Lisp_Object num2, enum comparison comparison) | |||
| 2275 | 2274 | ||
| 2276 | switch (comparison) | 2275 | switch (comparison) |
| 2277 | { | 2276 | { |
| 2278 | case equal: | 2277 | case ARITH_EQUAL: |
| 2279 | if (floatp ? f1 == f2 : XINT (num1) == XINT (num2)) | 2278 | if (floatp ? f1 == f2 : XINT (num1) == XINT (num2)) |
| 2280 | return Qt; | 2279 | return Qt; |
| 2281 | return Qnil; | 2280 | return Qnil; |
| 2282 | 2281 | ||
| 2283 | case notequal: | 2282 | case ARITH_NOTEQUAL: |
| 2284 | if (floatp ? f1 != f2 : XINT (num1) != XINT (num2)) | 2283 | if (floatp ? f1 != f2 : XINT (num1) != XINT (num2)) |
| 2285 | return Qt; | 2284 | return Qt; |
| 2286 | return Qnil; | 2285 | return Qnil; |
| 2287 | 2286 | ||
| 2288 | case less: | 2287 | case ARITH_LESS: |
| 2289 | if (floatp ? f1 < f2 : XINT (num1) < XINT (num2)) | 2288 | if (floatp ? f1 < f2 : XINT (num1) < XINT (num2)) |
| 2290 | return Qt; | 2289 | return Qt; |
| 2291 | return Qnil; | 2290 | return Qnil; |
| 2292 | 2291 | ||
| 2293 | case less_or_equal: | 2292 | case ARITH_LESS_OR_EQUAL: |
| 2294 | if (floatp ? f1 <= f2 : XINT (num1) <= XINT (num2)) | 2293 | if (floatp ? f1 <= f2 : XINT (num1) <= XINT (num2)) |
| 2295 | return Qt; | 2294 | return Qt; |
| 2296 | return Qnil; | 2295 | return Qnil; |
| 2297 | 2296 | ||
| 2298 | case grtr: | 2297 | case ARITH_GRTR: |
| 2299 | if (floatp ? f1 > f2 : XINT (num1) > XINT (num2)) | 2298 | if (floatp ? f1 > f2 : XINT (num1) > XINT (num2)) |
| 2300 | return Qt; | 2299 | return Qt; |
| 2301 | return Qnil; | 2300 | return Qnil; |
| 2302 | 2301 | ||
| 2303 | case grtr_or_equal: | 2302 | case ARITH_GRTR_OR_EQUAL: |
| 2304 | if (floatp ? f1 >= f2 : XINT (num1) >= XINT (num2)) | 2303 | if (floatp ? f1 >= f2 : XINT (num1) >= XINT (num2)) |
| 2305 | return Qt; | 2304 | return Qt; |
| 2306 | return Qnil; | 2305 | return Qnil; |
| @@ -2310,48 +2309,65 @@ arithcompare (Lisp_Object num1, Lisp_Object num2, enum comparison comparison) | |||
| 2310 | } | 2309 | } |
| 2311 | } | 2310 | } |
| 2312 | 2311 | ||
| 2313 | DEFUN ("=", Feqlsign, Seqlsign, 2, 2, 0, | 2312 | static Lisp_Object |
| 2314 | doc: /* Return t if two args, both numbers or markers, are equal. */) | 2313 | arithcompare_driver (ptrdiff_t nargs, Lisp_Object *args, |
| 2315 | (register Lisp_Object num1, Lisp_Object num2) | 2314 | enum Arith_Comparison comparison) |
| 2316 | { | 2315 | { |
| 2317 | return arithcompare (num1, num2, equal); | 2316 | for (ptrdiff_t argnum = 1; argnum < nargs; ++argnum) |
| 2317 | { | ||
| 2318 | if (EQ (Qnil, arithcompare (args[argnum-1], args[argnum], comparison))) | ||
| 2319 | return Qnil; | ||
| 2320 | } | ||
| 2321 | return Qt; | ||
| 2318 | } | 2322 | } |
| 2319 | 2323 | ||
| 2320 | DEFUN ("<", Flss, Slss, 2, 2, 0, | 2324 | DEFUN ("=", Feqlsign, Seqlsign, 1, MANY, 0, |
| 2321 | doc: /* Return t if first arg is less than second arg. Both must be numbers or markers. */) | 2325 | doc: /* Return t if args, all numbers or markers, are equal. |
| 2322 | (register Lisp_Object num1, Lisp_Object num2) | 2326 | usage: (= NUMBER-OR-MARKER &rest NUMBERS-OR-MARKERS) */) |
| 2327 | (ptrdiff_t nargs, Lisp_Object *args) | ||
| 2323 | { | 2328 | { |
| 2324 | return arithcompare (num1, num2, less); | 2329 | return arithcompare_driver (nargs, args, ARITH_EQUAL); |
| 2325 | } | 2330 | } |
| 2326 | 2331 | ||
| 2327 | DEFUN (">", Fgtr, Sgtr, 2, 2, 0, | 2332 | DEFUN ("<", Flss, Slss, 1, MANY, 0, |
| 2328 | doc: /* Return t if first arg is greater than second arg. Both must be numbers or markers. */) | 2333 | doc: /* Return t if each arg is less than the next arg. All must be numbers or markers. |
| 2329 | (register Lisp_Object num1, Lisp_Object num2) | 2334 | usage: (< NUMBER-OR-MARKER &rest NUMBERS-OR-MARKERS) */) |
| 2335 | (ptrdiff_t nargs, Lisp_Object *args) | ||
| 2330 | { | 2336 | { |
| 2331 | return arithcompare (num1, num2, grtr); | 2337 | return arithcompare_driver (nargs, args, ARITH_LESS); |
| 2332 | } | 2338 | } |
| 2333 | 2339 | ||
| 2334 | DEFUN ("<=", Fleq, Sleq, 2, 2, 0, | 2340 | DEFUN (">", Fgtr, Sgtr, 1, MANY, 0, |
| 2335 | doc: /* Return t if first arg is less than or equal to second arg. | 2341 | doc: /* Return t if each arg is greater than the next arg. All must be numbers or markers. |
| 2336 | Both must be numbers or markers. */) | 2342 | usage: (> NUMBER-OR-MARKER &rest NUMBERS-OR-MARKERS) */) |
| 2337 | (register Lisp_Object num1, Lisp_Object num2) | 2343 | (ptrdiff_t nargs, Lisp_Object *args) |
| 2338 | { | 2344 | { |
| 2339 | return arithcompare (num1, num2, less_or_equal); | 2345 | return arithcompare_driver (nargs, args, ARITH_GRTR); |
| 2340 | } | 2346 | } |
| 2341 | 2347 | ||
| 2342 | DEFUN (">=", Fgeq, Sgeq, 2, 2, 0, | 2348 | DEFUN ("<=", Fleq, Sleq, 1, MANY, 0, |
| 2343 | doc: /* Return t if first arg is greater than or equal to second arg. | 2349 | doc: /* Return t if each arg is less than or equal to the next arg. |
| 2344 | Both must be numbers or markers. */) | 2350 | All must be numbers or markers. |
| 2345 | (register Lisp_Object num1, Lisp_Object num2) | 2351 | usage: (<= NUMBER-OR-MARKER &rest NUMBERS-OR-MARKERS) */) |
| 2352 | (ptrdiff_t nargs, Lisp_Object *args) | ||
| 2353 | { | ||
| 2354 | return arithcompare_driver (nargs, args, ARITH_LESS_OR_EQUAL); | ||
| 2355 | } | ||
| 2356 | |||
| 2357 | DEFUN (">=", Fgeq, Sgeq, 1, MANY, 0, | ||
| 2358 | doc: /* Return t if each arg is greater than or equal to the next arg. | ||
| 2359 | All must be numbers or markers. | ||
| 2360 | usage: (= NUMBER-OR-MARKER &rest NUMBERS-OR-MARKERS) */) | ||
| 2361 | (ptrdiff_t nargs, Lisp_Object *args) | ||
| 2346 | { | 2362 | { |
| 2347 | return arithcompare (num1, num2, grtr_or_equal); | 2363 | return arithcompare_driver (nargs, args, ARITH_GRTR_OR_EQUAL); |
| 2348 | } | 2364 | } |
| 2349 | 2365 | ||
| 2350 | DEFUN ("/=", Fneq, Sneq, 2, 2, 0, | 2366 | DEFUN ("/=", Fneq, Sneq, 2, 2, 0, |
| 2351 | doc: /* Return t if first arg is not equal to second arg. Both must be numbers or markers. */) | 2367 | doc: /* Return t if first arg is not equal to second arg. Both must be numbers or markers. */) |
| 2352 | (register Lisp_Object num1, Lisp_Object num2) | 2368 | (register Lisp_Object num1, Lisp_Object num2) |
| 2353 | { | 2369 | { |
| 2354 | return arithcompare (num1, num2, notequal); | 2370 | return arithcompare (num1, num2, ARITH_NOTEQUAL); |
| 2355 | } | 2371 | } |
| 2356 | 2372 | ||
| 2357 | DEFUN ("zerop", Fzerop, Szerop, 1, 1, 0, | 2373 | DEFUN ("zerop", Fzerop, Szerop, 1, 1, 0, |
| @@ -2941,6 +2957,453 @@ lowercase l) for small endian machines. */) | |||
| 2941 | return make_number (order); | 2957 | return make_number (order); |
| 2942 | } | 2958 | } |
| 2943 | 2959 | ||
| 2960 | /* Because we round up the bool vector allocate size to word_size | ||
| 2961 | units, we can safely read past the "end" of the vector in the | ||
| 2962 | operations below. These extra bits are always zero. Also, we | ||
| 2963 | always allocate bool vectors with at least one size_t of storage so | ||
| 2964 | that we don't have to special-case empty bit vectors. */ | ||
| 2965 | |||
| 2966 | static size_t | ||
| 2967 | bool_vector_spare_mask (ptrdiff_t nr_bits) | ||
| 2968 | { | ||
| 2969 | eassert_and_assume (nr_bits > 0); | ||
| 2970 | return (((size_t) 1) << (nr_bits % BITS_PER_SIZE_T)) - 1; | ||
| 2971 | } | ||
| 2972 | |||
| 2973 | #if _MSC_VER >= 1500 && (defined _M_IX86 || defined _M_X64) | ||
| 2974 | # define USE_MSC_POPCOUNT | ||
| 2975 | # define POPCOUNT_STATIC_INLINE static inline | ||
| 2976 | #elif __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) | ||
| 2977 | # define USE_GCC_POPCOUNT | ||
| 2978 | # if 199901L <= __STDC_VERSION__ || !__STRICT_ANSI__ | ||
| 2979 | # define POPCOUNT_STATIC_INLINE static inline | ||
| 2980 | # endif | ||
| 2981 | #else | ||
| 2982 | # define NEED_GENERIC_POPCOUNT | ||
| 2983 | #endif | ||
| 2984 | #ifndef POPCOUNT_STATIC_INLINE | ||
| 2985 | # define POPCOUNT_STATIC_INLINE static | ||
| 2986 | #endif | ||
| 2987 | |||
| 2988 | #ifdef USE_MSC_POPCOUNT | ||
| 2989 | # define NEED_GENERIC_POPCOUNT | ||
| 2990 | #endif | ||
| 2991 | |||
| 2992 | #ifdef NEED_GENERIC_POPCOUNT | ||
| 2993 | POPCOUNT_STATIC_INLINE unsigned int | ||
| 2994 | popcount_size_t_generic (size_t val) | ||
| 2995 | { | ||
| 2996 | unsigned short j; | ||
| 2997 | unsigned int count = 0; | ||
| 2998 | |||
| 2999 | for (j = 0; j < BITS_PER_SIZE_T; ++j) | ||
| 3000 | count += !!((((size_t) 1) << j) & val); | ||
| 3001 | |||
| 3002 | return count; | ||
| 3003 | } | ||
| 3004 | #endif | ||
| 3005 | |||
| 3006 | #ifdef USE_MSC_POPCOUNT | ||
| 3007 | POPCOUNT_STATIC_INLINE unsigned int | ||
| 3008 | popcount_size_t_msc (size_t val) | ||
| 3009 | { | ||
| 3010 | unsigned int count; | ||
| 3011 | |||
| 3012 | #pragma intrinsic __cpuid | ||
| 3013 | /* While gcc falls back to its own generic code if the machine on | ||
| 3014 | which it's running doesn't support popcount, we need to perform the | ||
| 3015 | detection and fallback ourselves when compiling with Microsoft's | ||
| 3016 | compiler. */ | ||
| 3017 | |||
| 3018 | static enum { | ||
| 3019 | popcount_unknown_support, | ||
| 3020 | popcount_use_generic, | ||
| 3021 | popcount_use_intrinsic | ||
| 3022 | } popcount_state; | ||
| 3023 | |||
| 3024 | if (popcount_state == popcount_unknown_support) | ||
| 3025 | { | ||
| 3026 | int cpu_info[4]; | ||
| 3027 | __cpuid (cpu_info, 1); | ||
| 3028 | if (cpu_info[2] & (1<<23)) /* See MSDN. */ | ||
| 3029 | popcount_state = popcount_use_intrinsic; | ||
| 3030 | else | ||
| 3031 | popcount_state = popcount_use_generic; | ||
| 3032 | } | ||
| 3033 | |||
| 3034 | if (popcount_state == popcount_use_intrinsic) | ||
| 3035 | { | ||
| 3036 | # if BITS_PER_SIZE_T == 64 | ||
| 3037 | # pragma intrinsic __popcnt64 | ||
| 3038 | count = __popcnt64 (val); | ||
| 3039 | # else | ||
| 3040 | # pragma intrinsic __popcnt | ||
| 3041 | count = __popcnt (val); | ||
| 3042 | # endif | ||
| 3043 | } | ||
| 3044 | else | ||
| 3045 | count = popcount_size_t_generic (val); | ||
| 3046 | |||
| 3047 | return count; | ||
| 3048 | } | ||
| 3049 | #endif /* USE_MSC_POPCOUNT */ | ||
| 3050 | |||
| 3051 | #ifdef USE_GCC_POPCOUNT | ||
| 3052 | POPCOUNT_STATIC_INLINE unsigned int | ||
| 3053 | popcount_size_t_gcc (size_t val) | ||
| 3054 | { | ||
| 3055 | # if BITS_PER_SIZE_T == 64 | ||
| 3056 | return __builtin_popcountll (val); | ||
| 3057 | # else | ||
| 3058 | return __builtin_popcount (val); | ||
| 3059 | # endif | ||
| 3060 | } | ||
| 3061 | #endif /* USE_GCC_POPCOUNT */ | ||
| 3062 | |||
| 3063 | POPCOUNT_STATIC_INLINE unsigned int | ||
| 3064 | popcount_size_t (size_t val) | ||
| 3065 | { | ||
| 3066 | #if defined USE_MSC_POPCOUNT | ||
| 3067 | return popcount_size_t_msc (val); | ||
| 3068 | #elif defined USE_GCC_POPCOUNT | ||
| 3069 | return popcount_size_t_gcc (val); | ||
| 3070 | #else | ||
| 3071 | return popcount_size_t_generic (val); | ||
| 3072 | #endif | ||
| 3073 | } | ||
| 3074 | |||
| 3075 | enum bool_vector_op { bool_vector_exclusive_or, | ||
| 3076 | bool_vector_union, | ||
| 3077 | bool_vector_intersection, | ||
| 3078 | bool_vector_set_difference, | ||
| 3079 | bool_vector_subsetp }; | ||
| 3080 | |||
| 3081 | static Lisp_Object | ||
| 3082 | bool_vector_binop_driver (Lisp_Object op1, | ||
| 3083 | Lisp_Object op2, | ||
| 3084 | Lisp_Object dest, | ||
| 3085 | enum bool_vector_op op) | ||
| 3086 | { | ||
| 3087 | EMACS_INT nr_bits; | ||
| 3088 | size_t *adata, *bdata, *cdata; | ||
| 3089 | ptrdiff_t i; | ||
| 3090 | size_t changed = 0; | ||
| 3091 | size_t mword; | ||
| 3092 | ptrdiff_t nr_words; | ||
| 3093 | |||
| 3094 | CHECK_BOOL_VECTOR (op1); | ||
| 3095 | CHECK_BOOL_VECTOR (op2); | ||
| 3096 | |||
| 3097 | nr_bits = min (XBOOL_VECTOR (op1)->size, | ||
| 3098 | XBOOL_VECTOR (op2)->size); | ||
| 3099 | |||
| 3100 | if (NILP (dest)) | ||
| 3101 | { | ||
| 3102 | dest = Fmake_bool_vector (make_number (nr_bits), Qnil); | ||
| 3103 | changed = 1; | ||
| 3104 | } | ||
| 3105 | else | ||
| 3106 | { | ||
| 3107 | CHECK_BOOL_VECTOR (dest); | ||
| 3108 | nr_bits = min (nr_bits, XBOOL_VECTOR (dest)->size); | ||
| 3109 | } | ||
| 3110 | |||
| 3111 | eassert_and_assume (nr_bits >= 0); | ||
| 3112 | nr_words = ROUNDUP (nr_bits, BITS_PER_SIZE_T) / BITS_PER_SIZE_T; | ||
| 3113 | |||
| 3114 | adata = (size_t *) XBOOL_VECTOR (dest)->data; | ||
| 3115 | bdata = (size_t *) XBOOL_VECTOR (op1)->data; | ||
| 3116 | cdata = (size_t *) XBOOL_VECTOR (op2)->data; | ||
| 3117 | i = 0; | ||
| 3118 | do | ||
| 3119 | { | ||
| 3120 | if (op == bool_vector_exclusive_or) | ||
| 3121 | mword = bdata[i] ^ cdata[i]; | ||
| 3122 | else if (op == bool_vector_union || op == bool_vector_subsetp) | ||
| 3123 | mword = bdata[i] | cdata[i]; | ||
| 3124 | else if (op == bool_vector_intersection) | ||
| 3125 | mword = bdata[i] & cdata[i]; | ||
| 3126 | else if (op == bool_vector_set_difference) | ||
| 3127 | mword = bdata[i] &~ cdata[i]; | ||
| 3128 | else | ||
| 3129 | abort (); | ||
| 3130 | |||
| 3131 | changed |= adata[i] ^ mword; | ||
| 3132 | |||
| 3133 | if (op != bool_vector_subsetp) | ||
| 3134 | adata[i] = mword; | ||
| 3135 | |||
| 3136 | i++; | ||
| 3137 | } | ||
| 3138 | while (i < nr_words); | ||
| 3139 | |||
| 3140 | return changed ? dest : Qnil; | ||
| 3141 | } | ||
| 3142 | |||
| 3143 | /* Compute the number of trailing zero bits in val. If val is zero, | ||
| 3144 | return the number of bits in val. */ | ||
| 3145 | static unsigned int | ||
| 3146 | count_trailing_zero_bits (size_t val) | ||
| 3147 | { | ||
| 3148 | if (val == 0) | ||
| 3149 | return CHAR_BIT * sizeof (val); | ||
| 3150 | |||
| 3151 | #if defined USE_GCC_POPCOUNT && BITS_PER_SIZE_T == 64 | ||
| 3152 | return __builtin_ctzll (val); | ||
| 3153 | #elif defined USE_GCC_POPCOUNT && BITS_PER_SIZE_T == 32 | ||
| 3154 | return __builtin_ctz (val); | ||
| 3155 | #elif _MSC_VER && BITS_PER_SIZE_T == 64 | ||
| 3156 | # pragma intrinsic _BitScanForward64 | ||
| 3157 | { | ||
| 3158 | /* No support test needed: support since 386. */ | ||
| 3159 | unsigned long result; | ||
| 3160 | _BitScanForward64 (&result, val); | ||
| 3161 | return (unsigned int) result; | ||
| 3162 | } | ||
| 3163 | #elif _MSC_VER && BITS_PER_SIZE_T == 32 | ||
| 3164 | # pragma intrinsic _BitScanForward | ||
| 3165 | { | ||
| 3166 | /* No support test needed: support since 386. */ | ||
| 3167 | unsigned long result; | ||
| 3168 | _BitScanForward (&result, val); | ||
| 3169 | return (unsigned int) result; | ||
| 3170 | } | ||
| 3171 | #else | ||
| 3172 | { | ||
| 3173 | unsigned int count; | ||
| 3174 | count = 0; | ||
| 3175 | for (val = ~val; val & 1; val >>= 1) | ||
| 3176 | ++count; | ||
| 3177 | |||
| 3178 | return count; | ||
| 3179 | } | ||
| 3180 | #endif | ||
| 3181 | } | ||
| 3182 | |||
| 3183 | static size_t | ||
| 3184 | size_t_to_host_endian (size_t val) | ||
| 3185 | { | ||
| 3186 | #ifdef WORDS_BIGENDIAN | ||
| 3187 | # if BITS_PER_SIZE_T == 64 | ||
| 3188 | return swap64 (val); | ||
| 3189 | # else | ||
| 3190 | return swap32 (val); | ||
| 3191 | # endif | ||
| 3192 | #else | ||
| 3193 | return val; | ||
| 3194 | #endif | ||
| 3195 | } | ||
| 3196 | |||
| 3197 | DEFUN ("bool-vector-exclusive-or", Fbool_vector_exclusive_or, | ||
| 3198 | Sbool_vector_exclusive_or, 2, 3, 0, | ||
| 3199 | doc: /* Compute C = A ^ B, bitwise exclusive or. | ||
| 3200 | A, B, and C must be bool vectors. If C is nil, allocate a new bool | ||
| 3201 | vector in which to store the result. Return the destination vector if | ||
| 3202 | it changed or nil otherwise. */ | ||
| 3203 | ) | ||
| 3204 | (Lisp_Object a, Lisp_Object b, Lisp_Object c) | ||
| 3205 | { | ||
| 3206 | return bool_vector_binop_driver (a, b, c, bool_vector_exclusive_or); | ||
| 3207 | } | ||
| 3208 | |||
| 3209 | DEFUN ("bool-vector-union", Fbool_vector_union, | ||
| 3210 | Sbool_vector_union, 2, 3, 0, | ||
| 3211 | doc: /* Compute C = A | B, bitwise or. | ||
| 3212 | A, B, and C must be bool vectors. If C is nil, allocate a new bool | ||
| 3213 | vector in which to store the result. Return the destination vector if | ||
| 3214 | it changed or nil otherwise. */) | ||
| 3215 | (Lisp_Object a, Lisp_Object b, Lisp_Object c) | ||
| 3216 | { | ||
| 3217 | return bool_vector_binop_driver (a, b, c, bool_vector_union); | ||
| 3218 | } | ||
| 3219 | |||
| 3220 | DEFUN ("bool-vector-intersection", Fbool_vector_intersection, | ||
| 3221 | Sbool_vector_intersection, 2, 3, 0, | ||
| 3222 | doc: /* Compute C = A & B, bitwise and. | ||
| 3223 | A, B, and C must be bool vectors. If C is nil, allocate a new bool | ||
| 3224 | vector in which to store the result. Return the destination vector if | ||
| 3225 | it changed or nil otherwise. */) | ||
| 3226 | (Lisp_Object a, Lisp_Object b, Lisp_Object c) | ||
| 3227 | { | ||
| 3228 | return bool_vector_binop_driver (a, b, c, bool_vector_intersection); | ||
| 3229 | } | ||
| 3230 | |||
| 3231 | DEFUN ("bool-vector-set-difference", Fbool_vector_set_difference, | ||
| 3232 | Sbool_vector_set_difference, 2, 3, 0, | ||
| 3233 | doc: /* Compute C = A &~ B, set difference. | ||
| 3234 | A, B, and C must be bool vectors. If C is nil, allocate a new bool | ||
| 3235 | vector in which to store the result. Return the destination vector if | ||
| 3236 | it changed or nil otherwise. */) | ||
| 3237 | (Lisp_Object a, Lisp_Object b, Lisp_Object c) | ||
| 3238 | { | ||
| 3239 | return bool_vector_binop_driver (a, b, c, bool_vector_set_difference); | ||
| 3240 | } | ||
| 3241 | |||
| 3242 | DEFUN ("bool-vector-subsetp", Fbool_vector_subsetp, | ||
| 3243 | Sbool_vector_subsetp, 2, 2, 0, | ||
| 3244 | doc: ) | ||
| 3245 | (Lisp_Object a, Lisp_Object b) | ||
| 3246 | { | ||
| 3247 | /* Like bool_vector_union, but doesn't modify b. */ | ||
| 3248 | return bool_vector_binop_driver (b, a, b, bool_vector_subsetp); | ||
| 3249 | } | ||
| 3250 | |||
| 3251 | DEFUN ("bool-vector-not", Fbool_vector_not, | ||
| 3252 | Sbool_vector_not, 1, 2, 0, | ||
| 3253 | doc: /* Compute B = ~A. | ||
| 3254 | B must be a bool vector. A must be a bool vector or nil. | ||
| 3255 | If A is nil, allocate a new bool vector in which to store the result. | ||
| 3256 | Return the destination vector. */) | ||
| 3257 | (Lisp_Object a, Lisp_Object b) | ||
| 3258 | { | ||
| 3259 | EMACS_INT nr_bits; | ||
| 3260 | size_t *bdata, *adata; | ||
| 3261 | ptrdiff_t i; | ||
| 3262 | size_t mword; | ||
| 3263 | |||
| 3264 | CHECK_BOOL_VECTOR (a); | ||
| 3265 | nr_bits = XBOOL_VECTOR (a)->size; | ||
| 3266 | |||
| 3267 | if (NILP (b)) | ||
| 3268 | b = Fmake_bool_vector (make_number (nr_bits), Qnil); | ||
| 3269 | else | ||
| 3270 | { | ||
| 3271 | CHECK_BOOL_VECTOR (b); | ||
| 3272 | nr_bits = min (nr_bits, XBOOL_VECTOR (b)->size); | ||
| 3273 | } | ||
| 3274 | |||
| 3275 | bdata = (size_t *) XBOOL_VECTOR (b)->data; | ||
| 3276 | adata = (size_t *) XBOOL_VECTOR (a)->data; | ||
| 3277 | |||
| 3278 | eassert_and_assume (nr_bits >= 0); | ||
| 3279 | |||
| 3280 | for (i = 0; i < nr_bits / BITS_PER_SIZE_T; i++) | ||
| 3281 | bdata[i] = ~adata[i]; | ||
| 3282 | |||
| 3283 | if (nr_bits % BITS_PER_SIZE_T) | ||
| 3284 | { | ||
| 3285 | mword = size_t_to_host_endian (adata[i]); | ||
| 3286 | mword = ~mword; | ||
| 3287 | mword &= bool_vector_spare_mask (nr_bits); | ||
| 3288 | bdata[i] = size_t_to_host_endian (mword); | ||
| 3289 | } | ||
| 3290 | |||
| 3291 | return b; | ||
| 3292 | } | ||
| 3293 | |||
| 3294 | DEFUN ("bool-vector-count-matches", Fbool_vector_count_matches, | ||
| 3295 | Sbool_vector_count_matches, 2, 2, 0, | ||
| 3296 | doc: /* Count how many elements in A equal B. | ||
| 3297 | A must be a bool vector. B is a generalized bool. */) | ||
| 3298 | (Lisp_Object a, Lisp_Object b) | ||
| 3299 | { | ||
| 3300 | ptrdiff_t count; | ||
| 3301 | EMACS_INT nr_bits; | ||
| 3302 | size_t *adata; | ||
| 3303 | size_t match; | ||
| 3304 | ptrdiff_t i; | ||
| 3305 | |||
| 3306 | CHECK_BOOL_VECTOR (a); | ||
| 3307 | |||
| 3308 | nr_bits = XBOOL_VECTOR (a)->size; | ||
| 3309 | count = 0; | ||
| 3310 | match = NILP (b) ? (size_t) -1 : 0; | ||
| 3311 | adata = (size_t *) XBOOL_VECTOR (a)->data; | ||
| 3312 | |||
| 3313 | eassert_and_assume (nr_bits >= 0); | ||
| 3314 | |||
| 3315 | for (i = 0; i < nr_bits / BITS_PER_SIZE_T; ++i) | ||
| 3316 | count += popcount_size_t (adata[i] ^ match); | ||
| 3317 | |||
| 3318 | /* Mask out trailing parts of final mword. */ | ||
| 3319 | if (nr_bits % BITS_PER_SIZE_T) | ||
| 3320 | { | ||
| 3321 | size_t mword = adata[i] ^ match; | ||
| 3322 | mword = size_t_to_host_endian (mword); | ||
| 3323 | count += popcount_size_t (mword & bool_vector_spare_mask (nr_bits)); | ||
| 3324 | } | ||
| 3325 | |||
| 3326 | return make_number (count); | ||
| 3327 | } | ||
| 3328 | |||
| 3329 | DEFUN ("bool-vector-count-matches-at", | ||
| 3330 | Fbool_vector_count_matches_at, | ||
| 3331 | Sbool_vector_count_matches_at, 3, 3, 0, | ||
| 3332 | doc: /* Count how many consecutive elements in A equal B at i. | ||
| 3333 | A must be a bool vector. B is a generalized boolean. i is an | ||
| 3334 | index into the vector. */) | ||
| 3335 | (Lisp_Object a, Lisp_Object b, Lisp_Object i) | ||
| 3336 | { | ||
| 3337 | ptrdiff_t count; | ||
| 3338 | EMACS_INT nr_bits; | ||
| 3339 | ptrdiff_t offset; | ||
| 3340 | size_t *adata; | ||
| 3341 | size_t twiddle; | ||
| 3342 | size_t mword; /* Machine word. */ | ||
| 3343 | ptrdiff_t pos; | ||
| 3344 | ptrdiff_t nr_words; | ||
| 3345 | |||
| 3346 | CHECK_BOOL_VECTOR (a); | ||
| 3347 | CHECK_NATNUM (i); | ||
| 3348 | |||
| 3349 | nr_bits = XBOOL_VECTOR (a)->size; | ||
| 3350 | if (XFASTINT (i) > nr_bits) /* Allow one past the end for convenience */ | ||
| 3351 | args_out_of_range (a, i); | ||
| 3352 | |||
| 3353 | adata = (size_t *) XBOOL_VECTOR (a)->data; | ||
| 3354 | |||
| 3355 | assume (nr_bits >= 0); | ||
| 3356 | nr_words = ROUNDUP (nr_bits, BITS_PER_SIZE_T) / BITS_PER_SIZE_T; | ||
| 3357 | |||
| 3358 | pos = XFASTINT (i) / BITS_PER_SIZE_T; | ||
| 3359 | offset = XFASTINT (i) % BITS_PER_SIZE_T; | ||
| 3360 | count = 0; | ||
| 3361 | |||
| 3362 | /* By XORing with twiddle, we transform the problem of "count | ||
| 3363 | consecutive equal values" into "count the zero bits". The latter | ||
| 3364 | operation usually has hardware support. */ | ||
| 3365 | twiddle = NILP (b) ? 0 : (size_t) -1; | ||
| 3366 | |||
| 3367 | /* Scan the remainder of the mword at the current offset. */ | ||
| 3368 | if (pos < nr_words && offset != 0) | ||
| 3369 | { | ||
| 3370 | mword = size_t_to_host_endian (adata[pos]); | ||
| 3371 | mword ^= twiddle; | ||
| 3372 | mword >>= offset; | ||
| 3373 | count = count_trailing_zero_bits (mword); | ||
| 3374 | count = min (count, BITS_PER_SIZE_T - offset); | ||
| 3375 | pos++; | ||
| 3376 | if (count + offset < BITS_PER_SIZE_T) | ||
| 3377 | return make_number (count); | ||
| 3378 | } | ||
| 3379 | |||
| 3380 | /* Scan whole words until we either reach the end of the vector or | ||
| 3381 | find an mword that doesn't completely match. twiddle is | ||
| 3382 | endian-independent. */ | ||
| 3383 | while (pos < nr_words && adata[pos] == twiddle) | ||
| 3384 | { | ||
| 3385 | count += BITS_PER_SIZE_T; | ||
| 3386 | ++pos; | ||
| 3387 | } | ||
| 3388 | |||
| 3389 | if (pos < nr_words) | ||
| 3390 | { | ||
| 3391 | /* If we stopped because of a mismatch, see how many bits match | ||
| 3392 | in the current mword. */ | ||
| 3393 | mword = size_t_to_host_endian (adata[pos]); | ||
| 3394 | mword ^= twiddle; | ||
| 3395 | count += count_trailing_zero_bits (mword); | ||
| 3396 | } | ||
| 3397 | else if (nr_bits % BITS_PER_SIZE_T != 0) | ||
| 3398 | { | ||
| 3399 | /* If we hit the end, we might have overshot our count. Reduce | ||
| 3400 | the total by the number of spare bits at the end of the | ||
| 3401 | vector. */ | ||
| 3402 | count -= BITS_PER_SIZE_T - nr_bits % BITS_PER_SIZE_T; | ||
| 3403 | } | ||
| 3404 | |||
| 3405 | return make_number (count); | ||
| 3406 | } | ||
| 2944 | 3407 | ||
| 2945 | 3408 | ||
| 2946 | void | 3409 | void |
| @@ -2990,6 +3453,7 @@ syms_of_data (void) | |||
| 2990 | DEFSYM (Qsequencep, "sequencep"); | 3453 | DEFSYM (Qsequencep, "sequencep"); |
| 2991 | DEFSYM (Qbufferp, "bufferp"); | 3454 | DEFSYM (Qbufferp, "bufferp"); |
| 2992 | DEFSYM (Qvectorp, "vectorp"); | 3455 | DEFSYM (Qvectorp, "vectorp"); |
| 3456 | DEFSYM (Qbool_vector_p, "bool-vector-p"); | ||
| 2993 | DEFSYM (Qchar_or_string_p, "char-or-string-p"); | 3457 | DEFSYM (Qchar_or_string_p, "char-or-string-p"); |
| 2994 | DEFSYM (Qmarkerp, "markerp"); | 3458 | DEFSYM (Qmarkerp, "markerp"); |
| 2995 | DEFSYM (Qbuffer_or_string_p, "buffer-or-string-p"); | 3459 | DEFSYM (Qbuffer_or_string_p, "buffer-or-string-p"); |
| @@ -3207,6 +3671,15 @@ syms_of_data (void) | |||
| 3207 | defsubr (&Ssubr_arity); | 3671 | defsubr (&Ssubr_arity); |
| 3208 | defsubr (&Ssubr_name); | 3672 | defsubr (&Ssubr_name); |
| 3209 | 3673 | ||
| 3674 | defsubr (&Sbool_vector_exclusive_or); | ||
| 3675 | defsubr (&Sbool_vector_union); | ||
| 3676 | defsubr (&Sbool_vector_intersection); | ||
| 3677 | defsubr (&Sbool_vector_set_difference); | ||
| 3678 | defsubr (&Sbool_vector_not); | ||
| 3679 | defsubr (&Sbool_vector_subsetp); | ||
| 3680 | defsubr (&Sbool_vector_count_matches); | ||
| 3681 | defsubr (&Sbool_vector_count_matches_at); | ||
| 3682 | |||
| 3210 | set_symbol_function (Qwholenump, XSYMBOL (Qnatnump)->function); | 3683 | set_symbol_function (Qwholenump, XSYMBOL (Qnatnump)->function); |
| 3211 | 3684 | ||
| 3212 | DEFVAR_LISP ("most-positive-fixnum", Vmost_positive_fixnum, | 3685 | DEFVAR_LISP ("most-positive-fixnum", Vmost_positive_fixnum, |