aboutsummaryrefslogtreecommitdiffstats
path: root/src/data.c
diff options
context:
space:
mode:
authorEli Zaretskii2013-09-26 10:37:16 +0300
committerEli Zaretskii2013-09-26 10:37:16 +0300
commitb87c4ff2817e71ca71b028792200b1e069a95e04 (patch)
treebfe00c0655fa02078a9ab2c633ea06d90c4a2064 /src/data.c
parentbbc108377873aa6ed7cf21c731770103096eea39 (diff)
parentba355de014b75ed104da4777f909db70d62f2357 (diff)
downloademacs-b87c4ff2817e71ca71b028792200b1e069a95e04.tar.gz
emacs-b87c4ff2817e71ca71b028792200b1e069a95e04.zip
Merge from trunk.
Diffstat (limited to 'src/data.c')
-rw-r--r--src/data.c545
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;
54static Lisp_Object Qnatnump; 54static Lisp_Object Qnatnump;
55Lisp_Object Qstringp, Qarrayp, Qsequencep, Qbufferp; 55Lisp_Object Qstringp, Qarrayp, Qsequencep, Qbufferp;
56Lisp_Object Qchar_or_string_p, Qmarkerp, Qinteger_or_marker_p, Qvectorp; 56Lisp_Object Qchar_or_string_p, Qmarkerp, Qinteger_or_marker_p, Qvectorp;
57Lisp_Object Qbool_vector_p;
57Lisp_Object Qbuffer_or_string_p; 58Lisp_Object Qbuffer_or_string_p;
58static Lisp_Object Qkeywordp, Qboundp; 59static Lisp_Object Qkeywordp, Qboundp;
59Lisp_Object Qfboundp; 60Lisp_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
2000extern struct terminal *get_terminal (Lisp_Object display, int); 2001extern 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
2258enum comparison { equal, notequal, less, grtr, less_or_equal, grtr_or_equal }; 2259Lisp_Object
2259 2260arithcompare (Lisp_Object num1, Lisp_Object num2, enum Arith_Comparison comparison)
2260static Lisp_Object
2261arithcompare (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
2313DEFUN ("=", Feqlsign, Seqlsign, 2, 2, 0, 2312static Lisp_Object
2314 doc: /* Return t if two args, both numbers or markers, are equal. */) 2313arithcompare_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
2320DEFUN ("<", Flss, Slss, 2, 2, 0, 2324DEFUN ("=", 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) 2326usage: (= 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
2327DEFUN (">", Fgtr, Sgtr, 2, 2, 0, 2332DEFUN ("<", 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) 2334usage: (< 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
2334DEFUN ("<=", Fleq, Sleq, 2, 2, 0, 2340DEFUN (">", 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.
2336Both must be numbers or markers. */) 2342usage: (> 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
2342DEFUN (">=", Fgeq, Sgeq, 2, 2, 0, 2348DEFUN ("<=", 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.
2344Both must be numbers or markers. */) 2350All must be numbers or markers.
2345 (register Lisp_Object num1, Lisp_Object num2) 2351usage: (<= 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
2357DEFUN (">=", Fgeq, Sgeq, 1, MANY, 0,
2358 doc: /* Return t if each arg is greater than or equal to the next arg.
2359All must be numbers or markers.
2360usage: (= 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
2350DEFUN ("/=", Fneq, Sneq, 2, 2, 0, 2366DEFUN ("/=", 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
2357DEFUN ("zerop", Fzerop, Szerop, 1, 1, 0, 2373DEFUN ("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
2966static size_t
2967bool_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
2993POPCOUNT_STATIC_INLINE unsigned int
2994popcount_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
3007POPCOUNT_STATIC_INLINE unsigned int
3008popcount_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
3052POPCOUNT_STATIC_INLINE unsigned int
3053popcount_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
3063POPCOUNT_STATIC_INLINE unsigned int
3064popcount_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
3075enum 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
3081static Lisp_Object
3082bool_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. */
3145static unsigned int
3146count_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
3183static size_t
3184size_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
3197DEFUN ("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.
3200A, B, and C must be bool vectors. If C is nil, allocate a new bool
3201vector in which to store the result. Return the destination vector if
3202it 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
3209DEFUN ("bool-vector-union", Fbool_vector_union,
3210 Sbool_vector_union, 2, 3, 0,
3211 doc: /* Compute C = A | B, bitwise or.
3212A, B, and C must be bool vectors. If C is nil, allocate a new bool
3213vector in which to store the result. Return the destination vector if
3214it 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
3220DEFUN ("bool-vector-intersection", Fbool_vector_intersection,
3221 Sbool_vector_intersection, 2, 3, 0,
3222 doc: /* Compute C = A & B, bitwise and.
3223A, B, and C must be bool vectors. If C is nil, allocate a new bool
3224vector in which to store the result. Return the destination vector if
3225it 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
3231DEFUN ("bool-vector-set-difference", Fbool_vector_set_difference,
3232 Sbool_vector_set_difference, 2, 3, 0,
3233 doc: /* Compute C = A &~ B, set difference.
3234A, B, and C must be bool vectors. If C is nil, allocate a new bool
3235vector in which to store the result. Return the destination vector if
3236it 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
3242DEFUN ("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
3251DEFUN ("bool-vector-not", Fbool_vector_not,
3252 Sbool_vector_not, 1, 2, 0,
3253 doc: /* Compute B = ~A.
3254B must be a bool vector. A must be a bool vector or nil.
3255If A is nil, allocate a new bool vector in which to store the result.
3256Return 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
3294DEFUN ("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.
3297A 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
3329DEFUN ("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.
3333A must be a bool vector. B is a generalized boolean. i is an
3334index 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
2946void 3409void
@@ -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,