aboutsummaryrefslogtreecommitdiffstats
path: root/src/data.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/data.c')
-rw-r--r--src/data.c209
1 files changed, 117 insertions, 92 deletions
diff --git a/src/data.c b/src/data.c
index 22d051ef932..d0171b5d758 100644
--- a/src/data.c
+++ b/src/data.c
@@ -2141,13 +2141,9 @@ or a byte-code object. IDX starts at 0. */)
2141 } 2141 }
2142 else if (BOOL_VECTOR_P (array)) 2142 else if (BOOL_VECTOR_P (array))
2143 { 2143 {
2144 int val;
2145
2146 if (idxval < 0 || idxval >= bool_vector_size (array)) 2144 if (idxval < 0 || idxval >= bool_vector_size (array))
2147 args_out_of_range (array, idx); 2145 args_out_of_range (array, idx);
2148 2146 return bool_vector_ref (array, idxval);
2149 val = (unsigned char) XBOOL_VECTOR (array)->data[idxval / BOOL_VECTOR_BITS_PER_CHAR];
2150 return (val & (1 << (idxval % BOOL_VECTOR_BITS_PER_CHAR)) ? Qt : Qnil);
2151 } 2147 }
2152 else if (CHAR_TABLE_P (array)) 2148 else if (CHAR_TABLE_P (array))
2153 { 2149 {
@@ -2191,18 +2187,9 @@ bool-vector. IDX starts at 0. */)
2191 } 2187 }
2192 else if (BOOL_VECTOR_P (array)) 2188 else if (BOOL_VECTOR_P (array))
2193 { 2189 {
2194 int val;
2195
2196 if (idxval < 0 || idxval >= bool_vector_size (array)) 2190 if (idxval < 0 || idxval >= bool_vector_size (array))
2197 args_out_of_range (array, idx); 2191 args_out_of_range (array, idx);
2198 2192 bool_vector_set (array, idxval, !NILP (newelt));
2199 val = (unsigned char) XBOOL_VECTOR (array)->data[idxval / BOOL_VECTOR_BITS_PER_CHAR];
2200
2201 if (! NILP (newelt))
2202 val |= 1 << (idxval % BOOL_VECTOR_BITS_PER_CHAR);
2203 else
2204 val &= ~(1 << (idxval % BOOL_VECTOR_BITS_PER_CHAR));
2205 XBOOL_VECTOR (array)->data[idxval / BOOL_VECTOR_BITS_PER_CHAR] = val;
2206 } 2193 }
2207 else if (CHAR_TABLE_P (array)) 2194 else if (CHAR_TABLE_P (array))
2208 { 2195 {
@@ -2975,9 +2962,7 @@ lowercase l) for small endian machines. */)
2975 2962
2976/* Because we round up the bool vector allocate size to word_size 2963/* Because we round up the bool vector allocate size to word_size
2977 units, we can safely read past the "end" of the vector in the 2964 units, we can safely read past the "end" of the vector in the
2978 operations below. These extra bits are always zero. Also, we 2965 operations below. These extra bits are always zero. */
2979 always allocate bool vectors with at least one bits_word of storage so
2980 that we don't have to special-case empty bit vectors. */
2981 2966
2982static bits_word 2967static bits_word
2983bool_vector_spare_mask (EMACS_INT nr_bits) 2968bool_vector_spare_mask (EMACS_INT nr_bits)
@@ -2985,16 +2970,47 @@ bool_vector_spare_mask (EMACS_INT nr_bits)
2985 return (((bits_word) 1) << (nr_bits % BITS_PER_BITS_WORD)) - 1; 2970 return (((bits_word) 1) << (nr_bits % BITS_PER_BITS_WORD)) - 1;
2986} 2971}
2987 2972
2988#if BITS_WORD_MAX <= UINT_MAX 2973/* Info about unsigned long long, falling back on unsigned long
2989# define popcount_bits_word count_one_bits 2974 if unsigned long long is not available. */
2990#elif BITS_WORD_MAX <= ULONG_MAX 2975
2991# define popcount_bits_word count_one_bits_l 2976#if HAVE_UNSIGNED_LONG_LONG_INT
2992#elif BITS_WORD_MAX <= ULLONG_MAX 2977enum { BITS_PER_ULL = CHAR_BIT * sizeof (unsigned long long) };
2993# define popcount_bits_word count_one_bits_ll
2994#else 2978#else
2995# error "bits_word wider than long long? Please file a bug report." 2979enum { BITS_PER_ULL = CHAR_BIT * sizeof (unsigned long) };
2980# define ULLONG_MAX ULONG_MAX
2981# define count_one_bits_ll count_one_bits_l
2996#endif 2982#endif
2997 2983
2984/* Shift VAL right by the width of an unsigned long long.
2985 BITS_PER_ULL must be less than BITS_PER_BITS_WORD. */
2986
2987static bits_word
2988shift_right_ull (bits_word w)
2989{
2990 /* Pacify bogus GCC warning about shift count exceeding type width. */
2991 int shift = BITS_PER_ULL - BITS_PER_BITS_WORD < 0 ? BITS_PER_ULL : 0;
2992 return w >> shift;
2993}
2994
2995/* Return the number of 1 bits in W. */
2996
2997static int
2998count_one_bits_word (bits_word w)
2999{
3000 if (BITS_WORD_MAX <= UINT_MAX)
3001 return count_one_bits (w);
3002 else if (BITS_WORD_MAX <= ULONG_MAX)
3003 return count_one_bits_l (w);
3004 else
3005 {
3006 int i = 0, count = 0;
3007 while (count += count_one_bits_ll (w),
3008 BITS_PER_BITS_WORD <= (i += BITS_PER_ULL))
3009 w = shift_right_ull (w);
3010 return count;
3011 }
3012}
3013
2998enum bool_vector_op { bool_vector_exclusive_or, 3014enum bool_vector_op { bool_vector_exclusive_or,
2999 bool_vector_union, 3015 bool_vector_union,
3000 bool_vector_intersection, 3016 bool_vector_intersection,
@@ -3010,7 +3026,7 @@ bool_vector_binop_driver (Lisp_Object op1,
3010 EMACS_INT nr_bits; 3026 EMACS_INT nr_bits;
3011 bits_word *adata, *bdata, *cdata; 3027 bits_word *adata, *bdata, *cdata;
3012 ptrdiff_t i; 3028 ptrdiff_t i;
3013 bits_word changed = 0; 3029 bool changed = 0;
3014 bits_word mword; 3030 bits_word mword;
3015 ptrdiff_t nr_words; 3031 ptrdiff_t nr_words;
3016 3032
@@ -3023,7 +3039,7 @@ bool_vector_binop_driver (Lisp_Object op1,
3023 3039
3024 if (NILP (dest)) 3040 if (NILP (dest))
3025 { 3041 {
3026 dest = Fmake_bool_vector (make_number (nr_bits), Qnil); 3042 dest = make_uninit_bool_vector (nr_bits);
3027 changed = 1; 3043 changed = 1;
3028 } 3044 }
3029 else 3045 else
@@ -3033,13 +3049,13 @@ bool_vector_binop_driver (Lisp_Object op1,
3033 wrong_length_argument (op1, op2, dest); 3049 wrong_length_argument (op1, op2, dest);
3034 } 3050 }
3035 3051
3036 nr_words = ROUNDUP (nr_bits, BITS_PER_BITS_WORD) / BITS_PER_BITS_WORD; 3052 nr_words = bool_vector_words (nr_bits);
3053
3054 adata = bool_vector_data (dest);
3055 bdata = bool_vector_data (op1);
3056 cdata = bool_vector_data (op2);
3037 3057
3038 adata = (bits_word *) XBOOL_VECTOR (dest)->data; 3058 for (i = 0; i < nr_words; i++)
3039 bdata = (bits_word *) XBOOL_VECTOR (op1)->data;
3040 cdata = (bits_word *) XBOOL_VECTOR (op2)->data;
3041 i = 0;
3042 do
3043 { 3059 {
3044 if (op == bool_vector_exclusive_or) 3060 if (op == bool_vector_exclusive_or)
3045 mword = bdata[i] ^ cdata[i]; 3061 mword = bdata[i] ^ cdata[i];
@@ -3052,18 +3068,26 @@ bool_vector_binop_driver (Lisp_Object op1,
3052 else 3068 else
3053 abort (); 3069 abort ();
3054 3070
3055 changed |= adata[i] ^ mword; 3071 if (! changed)
3072 changed = adata[i] != mword;
3056 3073
3057 if (op != bool_vector_subsetp) 3074 if (op != bool_vector_subsetp)
3058 adata[i] = mword; 3075 adata[i] = mword;
3059
3060 i++;
3061 } 3076 }
3062 while (i < nr_words);
3063 3077
3064 return changed ? dest : Qnil; 3078 return changed ? dest : Qnil;
3065} 3079}
3066 3080
3081/* PRECONDITION must be true. Return VALUE. This odd construction
3082 works around a bogus GCC diagnostic "shift count >= width of type". */
3083
3084static int
3085pre_value (bool precondition, int value)
3086{
3087 eassume (precondition);
3088 return precondition ? value : 0;
3089}
3090
3067/* Compute the number of trailing zero bits in val. If val is zero, 3091/* Compute the number of trailing zero bits in val. If val is zero,
3068 return the number of bits in val. */ 3092 return the number of bits in val. */
3069static int 3093static int
@@ -3073,27 +3097,34 @@ count_trailing_zero_bits (bits_word val)
3073 return count_trailing_zeros (val); 3097 return count_trailing_zeros (val);
3074 if (BITS_WORD_MAX == ULONG_MAX) 3098 if (BITS_WORD_MAX == ULONG_MAX)
3075 return count_trailing_zeros_l (val); 3099 return count_trailing_zeros_l (val);
3076# if HAVE_UNSIGNED_LONG_LONG_INT
3077 if (BITS_WORD_MAX == ULLONG_MAX) 3100 if (BITS_WORD_MAX == ULLONG_MAX)
3078 return count_trailing_zeros_ll (val); 3101 return count_trailing_zeros_ll (val);
3079# endif
3080 3102
3081 /* The rest of this code is for the unlikely platform where bits_word differs 3103 /* The rest of this code is for the unlikely platform where bits_word differs
3082 in width from unsigned int, unsigned long, and unsigned long long. */ 3104 in width from unsigned int, unsigned long, and unsigned long long. */
3083 if (val == 0) 3105 val |= ~ BITS_WORD_MAX;
3084 return CHAR_BIT * sizeof (val);
3085 if (BITS_WORD_MAX <= UINT_MAX) 3106 if (BITS_WORD_MAX <= UINT_MAX)
3086 return count_trailing_zeros (val); 3107 return count_trailing_zeros (val);
3087 if (BITS_WORD_MAX <= ULONG_MAX) 3108 if (BITS_WORD_MAX <= ULONG_MAX)
3088 return count_trailing_zeros_l (val); 3109 return count_trailing_zeros_l (val);
3089 { 3110 else
3090# if HAVE_UNSIGNED_LONG_LONG_INT 3111 {
3091 verify (BITS_WORD_MAX <= ULLONG_MAX); 3112 int count;
3092 return count_trailing_zeros_ll (val); 3113 for (count = 0;
3093# else 3114 count < BITS_PER_BITS_WORD - BITS_PER_ULL;
3094 verify (BITS_WORD_MAX <= ULONG_MAX); 3115 count += BITS_PER_ULL)
3095# endif 3116 {
3096 } 3117 if (val & ULLONG_MAX)
3118 return count + count_trailing_zeros_ll (val);
3119 val = shift_right_ull (val);
3120 }
3121
3122 if (BITS_PER_BITS_WORD % BITS_PER_ULL != 0
3123 && BITS_WORD_MAX == (bits_word) -1)
3124 val |= (bits_word) 1 << pre_value (ULONG_MAX < BITS_WORD_MAX,
3125 BITS_PER_BITS_WORD % BITS_PER_ULL);
3126 return count + count_trailing_zeros_ll (val);
3127 }
3097} 3128}
3098 3129
3099static bits_word 3130static bits_word
@@ -3101,19 +3132,24 @@ bits_word_to_host_endian (bits_word val)
3101{ 3132{
3102#ifndef WORDS_BIGENDIAN 3133#ifndef WORDS_BIGENDIAN
3103 return val; 3134 return val;
3104#elif BITS_WORD_MAX >> 31 == 1
3105 return bswap_32 (val);
3106#elif BITS_WORD_MAX >> 31 >> 31 >> 1 == 1
3107 return bswap_64 (val);
3108#else 3135#else
3109 int i; 3136 if (BITS_WORD_MAX >> 31 == 1)
3110 bits_word r = 0; 3137 return bswap_32 (val);
3111 for (i = 0; i < sizeof val; i++) 3138# if HAVE_UNSIGNED_LONG_LONG
3112 { 3139 if (BITS_WORD_MAX >> 31 >> 31 >> 1 == 1)
3113 r = (r << CHAR_BIT) | (val & ((1u << CHAR_BIT) - 1)); 3140 return bswap_64 (val);
3114 val >>= CHAR_BIT; 3141# endif
3115 } 3142 {
3116 return r; 3143 int i;
3144 bits_word r = 0;
3145 for (i = 0; i < sizeof val; i++)
3146 {
3147 r = ((r << 1 << (CHAR_BIT - 1))
3148 | (val & ((1u << 1 << (CHAR_BIT - 1)) - 1)));
3149 val = val >> 1 >> (CHAR_BIT - 1);
3150 }
3151 return r;
3152 }
3117#endif 3153#endif
3118} 3154}
3119 3155
@@ -3181,13 +3217,12 @@ Return the destination vector. */)
3181 EMACS_INT nr_bits; 3217 EMACS_INT nr_bits;
3182 bits_word *bdata, *adata; 3218 bits_word *bdata, *adata;
3183 ptrdiff_t i; 3219 ptrdiff_t i;
3184 bits_word mword;
3185 3220
3186 CHECK_BOOL_VECTOR (a); 3221 CHECK_BOOL_VECTOR (a);
3187 nr_bits = bool_vector_size (a); 3222 nr_bits = bool_vector_size (a);
3188 3223
3189 if (NILP (b)) 3224 if (NILP (b))
3190 b = Fmake_bool_vector (make_number (nr_bits), Qnil); 3225 b = make_uninit_bool_vector (nr_bits);
3191 else 3226 else
3192 { 3227 {
3193 CHECK_BOOL_VECTOR (b); 3228 CHECK_BOOL_VECTOR (b);
@@ -3195,15 +3230,15 @@ Return the destination vector. */)
3195 wrong_length_argument (a, b, Qnil); 3230 wrong_length_argument (a, b, Qnil);
3196 } 3231 }
3197 3232
3198 bdata = (bits_word *) XBOOL_VECTOR (b)->data; 3233 bdata = bool_vector_data (b);
3199 adata = (bits_word *) XBOOL_VECTOR (a)->data; 3234 adata = bool_vector_data (a);
3200 3235
3201 for (i = 0; i < nr_bits / BITS_PER_BITS_WORD; i++) 3236 for (i = 0; i < nr_bits / BITS_PER_BITS_WORD; i++)
3202 bdata[i] = ~adata[i]; 3237 bdata[i] = BITS_WORD_MAX & ~adata[i];
3203 3238
3204 if (nr_bits % BITS_PER_BITS_WORD) 3239 if (nr_bits % BITS_PER_BITS_WORD)
3205 { 3240 {
3206 mword = bits_word_to_host_endian (adata[i]); 3241 bits_word mword = bits_word_to_host_endian (adata[i]);
3207 mword = ~mword; 3242 mword = ~mword;
3208 mword &= bool_vector_spare_mask (nr_bits); 3243 mword &= bool_vector_spare_mask (nr_bits);
3209 bdata[i] = bits_word_to_host_endian (mword); 3244 bdata[i] = bits_word_to_host_endian (mword);
@@ -3221,27 +3256,20 @@ A must be a bool vector. B is a generalized bool. */)
3221 EMACS_INT count; 3256 EMACS_INT count;
3222 EMACS_INT nr_bits; 3257 EMACS_INT nr_bits;
3223 bits_word *adata; 3258 bits_word *adata;
3224 bits_word match; 3259 ptrdiff_t i, nwords;
3225 ptrdiff_t i;
3226 3260
3227 CHECK_BOOL_VECTOR (a); 3261 CHECK_BOOL_VECTOR (a);
3228 3262
3229 nr_bits = bool_vector_size (a); 3263 nr_bits = bool_vector_size (a);
3264 nwords = bool_vector_words (nr_bits);
3230 count = 0; 3265 count = 0;
3231 match = NILP (b) ? -1 : 0; 3266 adata = bool_vector_data (a);
3232 adata = (bits_word *) XBOOL_VECTOR (a)->data;
3233
3234 for (i = 0; i < nr_bits / BITS_PER_BITS_WORD; ++i)
3235 count += popcount_bits_word (adata[i] ^ match);
3236 3267
3237 /* Mask out trailing parts of final mword. */ 3268 for (i = 0; i < nwords; i++)
3238 if (nr_bits % BITS_PER_BITS_WORD) 3269 count += count_one_bits_word (adata[i]);
3239 {
3240 bits_word mword = adata[i] ^ match;
3241 mword = bits_word_to_host_endian (mword);
3242 count += popcount_bits_word (mword & bool_vector_spare_mask (nr_bits));
3243 }
3244 3270
3271 if (NILP (b))
3272 count = nr_bits - count;
3245 return make_number (count); 3273 return make_number (count);
3246} 3274}
3247 3275
@@ -3259,7 +3287,7 @@ index into the vector. */)
3259 bits_word *adata; 3287 bits_word *adata;
3260 bits_word twiddle; 3288 bits_word twiddle;
3261 bits_word mword; /* Machine word. */ 3289 bits_word mword; /* Machine word. */
3262 ptrdiff_t pos; 3290 ptrdiff_t pos, pos0;
3263 ptrdiff_t nr_words; 3291 ptrdiff_t nr_words;
3264 3292
3265 CHECK_BOOL_VECTOR (a); 3293 CHECK_BOOL_VECTOR (a);
@@ -3269,10 +3297,8 @@ index into the vector. */)
3269 if (XFASTINT (i) > nr_bits) /* Allow one past the end for convenience */ 3297 if (XFASTINT (i) > nr_bits) /* Allow one past the end for convenience */
3270 args_out_of_range (a, i); 3298 args_out_of_range (a, i);
3271 3299
3272 adata = (bits_word *) XBOOL_VECTOR (a)->data; 3300 adata = bool_vector_data (a);
3273 3301 nr_words = bool_vector_words (nr_bits);
3274 nr_words = ROUNDUP (nr_bits, BITS_PER_BITS_WORD) / BITS_PER_BITS_WORD;
3275
3276 pos = XFASTINT (i) / BITS_PER_BITS_WORD; 3302 pos = XFASTINT (i) / BITS_PER_BITS_WORD;
3277 offset = XFASTINT (i) % BITS_PER_BITS_WORD; 3303 offset = XFASTINT (i) % BITS_PER_BITS_WORD;
3278 count = 0; 3304 count = 0;
@@ -3280,7 +3306,7 @@ index into the vector. */)
3280 /* By XORing with twiddle, we transform the problem of "count 3306 /* By XORing with twiddle, we transform the problem of "count
3281 consecutive equal values" into "count the zero bits". The latter 3307 consecutive equal values" into "count the zero bits". The latter
3282 operation usually has hardware support. */ 3308 operation usually has hardware support. */
3283 twiddle = NILP (b) ? 0 : -1; 3309 twiddle = NILP (b) ? 0 : BITS_WORD_MAX;
3284 3310
3285 /* Scan the remainder of the mword at the current offset. */ 3311 /* Scan the remainder of the mword at the current offset. */
3286 if (pos < nr_words && offset != 0) 3312 if (pos < nr_words && offset != 0)
@@ -3288,8 +3314,8 @@ index into the vector. */)
3288 mword = bits_word_to_host_endian (adata[pos]); 3314 mword = bits_word_to_host_endian (adata[pos]);
3289 mword ^= twiddle; 3315 mword ^= twiddle;
3290 mword >>= offset; 3316 mword >>= offset;
3317 mword |= (bits_word) 1 << (BITS_PER_BITS_WORD - offset);
3291 count = count_trailing_zero_bits (mword); 3318 count = count_trailing_zero_bits (mword);
3292 count = min (count, BITS_PER_BITS_WORD - offset);
3293 pos++; 3319 pos++;
3294 if (count + offset < BITS_PER_BITS_WORD) 3320 if (count + offset < BITS_PER_BITS_WORD)
3295 return make_number (count); 3321 return make_number (count);
@@ -3298,11 +3324,10 @@ index into the vector. */)
3298 /* Scan whole words until we either reach the end of the vector or 3324 /* Scan whole words until we either reach the end of the vector or
3299 find an mword that doesn't completely match. twiddle is 3325 find an mword that doesn't completely match. twiddle is
3300 endian-independent. */ 3326 endian-independent. */
3327 pos0 = pos;
3301 while (pos < nr_words && adata[pos] == twiddle) 3328 while (pos < nr_words && adata[pos] == twiddle)
3302 { 3329 pos++;
3303 count += BITS_PER_BITS_WORD; 3330 count += (pos - pos0) * BITS_PER_BITS_WORD;
3304 ++pos;
3305 }
3306 3331
3307 if (pos < nr_words) 3332 if (pos < nr_words)
3308 { 3333 {