blob: 92205bfc8e8428bf44ccf0f25e82ebb3bf2cee4f [file] [log] [blame]
Ed Warnickecb9cada2015-12-08 15:45:58 -07001/*
2 * Copyright (c) 2015 Cisco and/or its affiliates.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at:
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15/*
16 Copyright (c) 2001, 2002, 2003, 2005 Eliot Dresselhaus
17
18 Permission is hereby granted, free of charge, to any person obtaining
19 a copy of this software and associated documentation files (the
20 "Software"), to deal in the Software without restriction, including
21 without limitation the rights to use, copy, modify, merge, publish,
22 distribute, sublicense, and/or sell copies of the Software, and to
23 permit persons to whom the Software is furnished to do so, subject to
24 the following conditions:
25
26 The above copyright notice and this permission notice shall be
27 included in all copies or substantial portions of the Software.
28
29 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
30 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
31 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
32 NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
33 LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
34 OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
35 WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
36*/
37
38#ifndef included_clib_bitmap_h
39#define included_clib_bitmap_h
40
Dave Barach310f7fe2016-08-05 14:36:27 -040041/** \file
42 Bitmaps built as vectors of machine words
Dave Barachc3799992016-08-15 11:12:27 -040043*/
Ed Warnickecb9cada2015-12-08 15:45:58 -070044
45#include <vppinfra/vec.h>
46#include <vppinfra/random.h>
47#include <vppinfra/error.h>
48#include <vppinfra/bitops.h> /* for count_set_bits */
49
Damjan Marion0b140722016-06-14 00:36:09 +020050typedef uword clib_bitmap_t;
51
Dave Barach310f7fe2016-08-05 14:36:27 -040052/** predicate function; is an entire bitmap empty?
53 @param ai - pointer to a bitmap
54 @returns 1 if the entire bitmap is zero, 0 otherwise
55*/
Ed Warnickecb9cada2015-12-08 15:45:58 -070056always_inline uword
57clib_bitmap_is_zero (uword * ai)
58{
59 uword i;
60 for (i = 0; i < vec_len (ai); i++)
61 if (ai[i] != 0)
62 return 0;
63 return 1;
64}
65
Dave Barach310f7fe2016-08-05 14:36:27 -040066/** predicate function; are two bitmaps equal?
67 @param a - pointer to a bitmap
68 @param b - pointer to a bitmap
69 @returns 1 if the bitmaps are equal, 0 otherwise
70*/
Ed Warnickecb9cada2015-12-08 15:45:58 -070071always_inline uword
72clib_bitmap_is_equal (uword * a, uword * b)
73{
74 uword i;
75 if (vec_len (a) != vec_len (b))
76 return 0;
77 for (i = 0; i < vec_len (a); i++)
78 if (a[i] != b[i])
79 return 0;
80 return 1;
81}
82
Dave Barach310f7fe2016-08-05 14:36:27 -040083/** Duplicate a bitmap
Chris Luked4024f52016-09-06 09:32:36 -040084 @param v - pointer to a bitmap
Dave Barach310f7fe2016-08-05 14:36:27 -040085 @returns a duplicate of the bitmap
86*/
Ed Warnickecb9cada2015-12-08 15:45:58 -070087#define clib_bitmap_dup(v) vec_dup(v)
88
Dave Barach310f7fe2016-08-05 14:36:27 -040089/** Free a bitmap
90 @param v - pointer to the bitmap to free
91*/
Ed Warnickecb9cada2015-12-08 15:45:58 -070092#define clib_bitmap_free(v) vec_free(v)
93
Dave Barach310f7fe2016-08-05 14:36:27 -040094/** Number of bytes in a bitmap
95 @param v - pointer to the bitmap
96*/
Ed Warnickecb9cada2015-12-08 15:45:58 -070097#define clib_bitmap_bytes(v) vec_bytes(v)
98
Dave Barach310f7fe2016-08-05 14:36:27 -040099/** Clear a bitmap
100 @param v - pointer to the bitmap to clear
101*/
Ed Warnickecb9cada2015-12-08 15:45:58 -0700102#define clib_bitmap_zero(v) vec_zero(v)
103
Dave Barach310f7fe2016-08-05 14:36:27 -0400104/** Allocate a bitmap with the supplied number of bits
105 @param [out] v - the resulting bitmap
106 @param n_bits - the required number of bits
107*/
108
Ed Warnickecb9cada2015-12-08 15:45:58 -0700109#define clib_bitmap_alloc(v,n_bits) \
110 v = vec_new (uword, ((n_bits) + BITS (uword) - 1) / BITS (uword))
111
112#define clib_bitmap_vec_validate(v,i) vec_validate_aligned((v),(i),sizeof(uword))
113
114/* Make sure that a bitmap is at least n_bits in size */
115#define clib_bitmap_validate(v,n_bits) \
116 clib_bitmap_vec_validate ((v), ((n_bits) - 1) / BITS (uword))
117
118/* low-level routine to remove trailing zeros from a bitmap */
119always_inline uword *
120_clib_bitmap_remove_trailing_zeros (uword * a)
121{
122 word i;
123 if (a)
124 {
125 for (i = _vec_len (a) - 1; i >= 0; i--)
126 if (a[i] != 0)
127 break;
128 _vec_len (a) = i + 1;
129 }
130 return a;
131}
132
Dave Barach310f7fe2016-08-05 14:36:27 -0400133/** Sets the ith bit of a bitmap to new_value.
Dave Barachc3799992016-08-15 11:12:27 -0400134 No sanity checking. Be careful.
Dave Barach310f7fe2016-08-05 14:36:27 -0400135 @param a - pointer to the bitmap
136 @param i - the bit position to interrogate
137 @param new_value - new value for the bit
138 @returns the old value of the bit
139*/
Ed Warnickecb9cada2015-12-08 15:45:58 -0700140always_inline uword
141clib_bitmap_set_no_check (uword * a, uword i, uword new_value)
142{
143 uword i0 = i / BITS (a[0]);
144 uword i1 = i % BITS (a[0]);
145 uword bit = (uword) 1 << i1;
146 uword ai, old_value;
147
148 /* Removed ASSERT since uword * a may not be a vector. */
149 /* ASSERT (i0 < vec_len (a)); */
150
151 ai = a[i0];
152 old_value = (ai & bit) != 0;
Dave Barachc3799992016-08-15 11:12:27 -0400153 ai &= ~bit;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700154 ai |= ((uword) (new_value != 0)) << i1;
155 a[i0] = ai;
156 return old_value;
157}
158
Dave Barach310f7fe2016-08-05 14:36:27 -0400159/** Sets the ith bit of a bitmap to new_value
160 Removes trailing zeros from the bitmap
Chris Luked4024f52016-09-06 09:32:36 -0400161 @param ai - pointer to the bitmap
Dave Barach310f7fe2016-08-05 14:36:27 -0400162 @param i - the bit position to interrogate
Chris Luked4024f52016-09-06 09:32:36 -0400163 @param value - new value for the bit
Dave Barach310f7fe2016-08-05 14:36:27 -0400164 @returns the old value of the bit
165*/
Ed Warnickecb9cada2015-12-08 15:45:58 -0700166always_inline uword *
167clib_bitmap_set (uword * ai, uword i, uword value)
168{
169 uword i0 = i / BITS (ai[0]);
170 uword i1 = i % BITS (ai[0]);
171 uword a;
172
173 /* Check for writing a zero to beyond end of bitmap. */
174 if (value == 0 && i0 >= vec_len (ai))
175 return ai; /* Implied trailing zeros. */
176
177 clib_bitmap_vec_validate (ai, i0);
178
179 a = ai[i0];
180 a &= ~((uword) 1 << i1);
181 a |= ((uword) (value != 0)) << i1;
182 ai[i0] = a;
183
184 /* If bits have been cleared, test for zero. */
185 if (a == 0)
186 ai = _clib_bitmap_remove_trailing_zeros (ai);
187
188 return ai;
189}
190
Dave Barach310f7fe2016-08-05 14:36:27 -0400191/** Gets the ith bit value from a bitmap
192 @param ai - pointer to the bitmap
193 @param i - the bit position to interrogate
194 @returns the indicated bit value
195*/
Ed Warnickecb9cada2015-12-08 15:45:58 -0700196always_inline uword
197clib_bitmap_get (uword * ai, uword i)
198{
199 uword i0 = i / BITS (ai[0]);
200 uword i1 = i % BITS (ai[0]);
201 return i0 < vec_len (ai) && 0 != ((ai[i0] >> i1) & 1);
202}
203
Dave Barach310f7fe2016-08-05 14:36:27 -0400204/** Gets the ith bit value from a bitmap
205 Does not sanity-check the bit position. Be careful.
206 @param ai - pointer to the bitmap
207 @param i - the bit position to interrogate
208 @returns the indicated bit value, or garbage if the bit position is
209 out of range.
Ed Warnickecb9cada2015-12-08 15:45:58 -0700210*/
211always_inline uword
212clib_bitmap_get_no_check (uword * ai, uword i)
213{
214 uword i0 = i / BITS (ai[0]);
215 uword i1 = i % BITS (ai[0]);
216 return 0 != ((ai[i0] >> i1) & 1);
217}
218
Ed Warnickecb9cada2015-12-08 15:45:58 -0700219always_inline uword
220clib_bitmap_get_multiple_no_check (uword * ai, uword i, uword n_bits)
221{
222 uword i0 = i / BITS (ai[0]);
223 uword i1 = i % BITS (ai[0]);
224 ASSERT (i1 + n_bits <= BITS (uword));
225 return 0 != ((ai[i0] >> i1) & pow2_mask (n_bits));
226}
227
Dave Barach310f7fe2016-08-05 14:36:27 -0400228/** Gets the ith through ith + n_bits bit values from a bitmap
229 @param bitmap - pointer to the bitmap
230 @param i - the first bit position to retrieve
231 @param n_bits - the number of bit positions to retrieve
232 @returns the indicated range of bits
233*/
Ed Warnickecb9cada2015-12-08 15:45:58 -0700234always_inline uword
235clib_bitmap_get_multiple (uword * bitmap, uword i, uword n_bits)
236{
237 uword i0, i1, result;
238 uword l = vec_len (bitmap);
239
Dave Barachf9c231e2016-08-05 10:10:18 -0400240 ASSERT (n_bits <= BITS (result));
Ed Warnickecb9cada2015-12-08 15:45:58 -0700241
242 i0 = i / BITS (bitmap[0]);
243 i1 = i % BITS (bitmap[0]);
244
245 /* Check first word. */
246 result = 0;
247 if (i0 < l)
248 {
249 result |= (bitmap[i0] >> i1);
250 if (n_bits < BITS (bitmap[0]))
251 result &= (((uword) 1 << n_bits) - 1);
252 }
253
254 /* Check for overlap into next word. */
255 i0++;
256 if (i1 + n_bits > BITS (bitmap[0]) && i0 < l)
257 {
258 n_bits -= BITS (bitmap[0]) - i1;
Dave Barachc3799992016-08-15 11:12:27 -0400259 result |=
260 (bitmap[i0] & (((uword) 1 << n_bits) - 1)) << (BITS (bitmap[0]) - i1);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700261 }
262
263 return result;
264}
265
Dave Barach310f7fe2016-08-05 14:36:27 -0400266/** sets the ith through ith + n_bits bits in a bitmap
267 @param bitmap - pointer to the bitmap
268 @param i - the first bit position to retrieve
269 @param value - the values to set
270 @param n_bits - the number of bit positions to set
271 @returns a pointer to the updated bitmap, which may expand and move
272*/
Ed Warnickecb9cada2015-12-08 15:45:58 -0700273
Ed Warnickecb9cada2015-12-08 15:45:58 -0700274always_inline uword *
275clib_bitmap_set_multiple (uword * bitmap, uword i, uword value, uword n_bits)
276{
277 uword i0, i1, l, t, m;
278
Dave Barachf9c231e2016-08-05 10:10:18 -0400279 ASSERT (n_bits <= BITS (value));
Ed Warnickecb9cada2015-12-08 15:45:58 -0700280
281 i0 = i / BITS (bitmap[0]);
282 i1 = i % BITS (bitmap[0]);
283
284 /* Allocate bitmap. */
285 clib_bitmap_vec_validate (bitmap, (i + n_bits) / BITS (bitmap[0]));
286 l = vec_len (bitmap);
287
288 m = ~0;
289 if (n_bits < BITS (value))
290 m = (((uword) 1 << n_bits) - 1);
291 value &= m;
292
293 /* Insert into first word. */
294 t = bitmap[i0];
295 t &= ~(m << i1);
296 t |= value << i1;
297 bitmap[i0] = t;
298
299 /* Insert into second word. */
300 i0++;
301 if (i1 + n_bits > BITS (bitmap[0]) && i0 < l)
302 {
303 t = BITS (bitmap[0]) - i1;
304 value >>= t;
305 n_bits -= t;
306 t = bitmap[i0];
307 m = ((uword) 1 << n_bits) - 1;
308 t &= ~m;
309 t |= value;
310 bitmap[i0] = t;
311 }
312
313 return bitmap;
314}
315
Ed Warnickecb9cada2015-12-08 15:45:58 -0700316always_inline uword *
Korian Edeline40e6bdf2018-08-08 11:30:30 +0200317clib_bitmap_set_region (uword * bitmap, uword i, uword value, uword n_bits)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700318{
319 uword a0, a1, b0;
320 uword i_end, mask;
321
322 a0 = i / BITS (bitmap[0]);
323 a1 = i % BITS (bitmap[0]);
324
325 i_end = i + n_bits;
326 b0 = i_end / BITS (bitmap[0]);
327
328 clib_bitmap_vec_validate (bitmap, b0);
329
330 /* First word. */
331 mask = n_bits < BITS (bitmap[0]) ? pow2_mask (n_bits) : ~0;
332 mask <<= a1;
333
334 if (value)
335 bitmap[a0] |= mask;
336 else
337 bitmap[a0] &= ~mask;
338
339 for (a0++; a0 < b0; a0++)
340 bitmap[a0] = value ? ~0 : 0;
341
342 if (a0 == b0)
343 {
344 word n_bits_left = n_bits - (BITS (bitmap[0]) - a1);
345 mask = pow2_mask (n_bits_left);
346 if (value)
347 bitmap[a0] |= mask;
348 else
349 bitmap[a0] &= ~mask;
350 }
351
352 return bitmap;
353}
354
Dave Barach310f7fe2016-08-05 14:36:27 -0400355/** Macro to iterate across set bits in a bitmap
356
357 @param i - the current set bit
358 @param ai - the bitmap
359 @param body - the expression to evaluate for each set bit
360*/
Damjan Marionf0ca1e82020-12-13 23:26:56 +0100361#define clib_bitmap_foreach(i,ai) \
362 if (ai) \
363 for (i = clib_bitmap_first_set (ai); \
364 i != ~0; \
365 i = clib_bitmap_next_set (ai, i + 1))
366
Dave Barach310f7fe2016-08-05 14:36:27 -0400367/** Return the lowest numbered set bit in a bitmap
368 @param ai - pointer to the bitmap
369 @returns lowest numbered set bit, or ~0 if the entire bitmap is zero
370*/
Dave Barachc3799992016-08-15 11:12:27 -0400371always_inline uword
372clib_bitmap_first_set (uword * ai)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700373{
Damjan Marion32ab9542018-06-26 01:29:55 +0200374 uword i = 0;
375#if uword_bits == 64
Damjan Marion13c98a22018-06-26 16:05:43 +0200376#if defined(CLIB_HAVE_VEC256)
Damjan Marion32ab9542018-06-26 01:29:55 +0200377 while (i + 7 < vec_len (ai))
378 {
379 u64x4 v;
380 v = u64x4_load_unaligned (ai + i) | u64x4_load_unaligned (ai + i + 4);
381 if (!u64x4_is_all_zero (v))
382 break;
383 i += 8;
384 }
Damjan Marion13c98a22018-06-26 16:05:43 +0200385#elif defined(CLIB_HAVE_VEC128) && defined(CLIB_HAVE_VEC128_UNALIGNED_LOAD_STORE)
Damjan Marion32ab9542018-06-26 01:29:55 +0200386 while (i + 3 < vec_len (ai))
387 {
388 u64x2 v;
389 v = u64x2_load_unaligned (ai + i) | u64x2_load_unaligned (ai + i + 2);
390 if (!u64x2_is_all_zero (v))
391 break;
392 i += 4;
393 }
394#endif
395#endif
396 for (; i < vec_len (ai); i++)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700397 {
398 uword x = ai[i];
399 if (x != 0)
400 return i * BITS (ai[0]) + log2_first_set (x);
401 }
402 return ~0;
403}
404
Dave Barach310f7fe2016-08-05 14:36:27 -0400405/** Return the higest numbered set bit in a bitmap
406 @param ai - pointer to the bitmap
407 @returns lowest numbered set bit, or ~0 if the entire bitmap is zero
408*/
Dave Barachc3799992016-08-15 11:12:27 -0400409always_inline uword
410clib_bitmap_last_set (uword * ai)
Damjan Marion0247b462016-06-08 01:37:11 +0200411{
412 uword i;
413
Dave Barachc3799992016-08-15 11:12:27 -0400414 for (i = vec_len (ai); i > 0; i--)
Damjan Marion0247b462016-06-08 01:37:11 +0200415 {
Damjan Marionec175102016-06-30 01:02:17 +0200416 uword x = ai[i - 1];
Damjan Marion0247b462016-06-08 01:37:11 +0200417 if (x != 0)
418 {
419 uword first_bit;
Damjan Marion11056002018-05-10 13:40:44 +0200420 first_bit = count_leading_zeros (x);
Damjan Marionec175102016-06-30 01:02:17 +0200421 return (i) * BITS (ai[0]) - first_bit - 1;
Damjan Marion0247b462016-06-08 01:37:11 +0200422 }
423 }
424 return ~0;
425}
426
Dave Barach310f7fe2016-08-05 14:36:27 -0400427/** Return the lowest numbered clear bit in a bitmap
428 @param ai - pointer to the bitmap
429 @returns lowest numbered clear bit
430*/
Ed Warnickecb9cada2015-12-08 15:45:58 -0700431always_inline uword
432clib_bitmap_first_clear (uword * ai)
433{
434 uword i;
435 for (i = 0; i < vec_len (ai); i++)
436 {
437 uword x = ~ai[i];
438 if (x != 0)
439 return i * BITS (ai[0]) + log2_first_set (x);
440 }
441 return i * BITS (ai[0]);
442}
443
Dave Barach310f7fe2016-08-05 14:36:27 -0400444/** Return the number of set bits in a bitmap
445 @param ai - pointer to the bitmap
446 @returns the number of set bits in the bitmap
447*/
Ed Warnickecb9cada2015-12-08 15:45:58 -0700448always_inline uword
449clib_bitmap_count_set_bits (uword * ai)
450{
451 uword i;
452 uword n_set = 0;
453 for (i = 0; i < vec_len (ai); i++)
454 n_set += count_set_bits (ai[i]);
455 return n_set;
456}
457
Dave Barach310f7fe2016-08-05 14:36:27 -0400458/** Logical operator across two bitmaps
459
460 @param ai - pointer to the destination bitmap
461 @param bi - pointer to the source bitmap
462 @returns ai = ai and bi. ai is modified, bi is not modified
463*/
Dave Barachc3799992016-08-15 11:12:27 -0400464always_inline uword *clib_bitmap_and (uword * ai, uword * bi);
Dave Barach310f7fe2016-08-05 14:36:27 -0400465
466/** Logical operator across two bitmaps
467
468 @param ai - pointer to the destination bitmap
469 @param bi - pointer to the source bitmap
470 @returns ai = ai & ~bi. ai is modified, bi is not modified
471*/
Dave Barachc3799992016-08-15 11:12:27 -0400472always_inline uword *clib_bitmap_andnot (uword * ai, uword * bi);
Dave Barach310f7fe2016-08-05 14:36:27 -0400473
474/** Logical operator across two bitmaps
475
476 @param ai - pointer to the destination bitmap
477 @param bi - pointer to the source bitmap
478 @returns ai = ai & ~bi. ai is modified, bi is not modified
479*/
Dave Barachc3799992016-08-15 11:12:27 -0400480always_inline uword *clib_bitmap_or (uword * ai, uword * bi);
Dave Barach310f7fe2016-08-05 14:36:27 -0400481/** Logical operator across two bitmaps
482
483 @param ai - pointer to the destination bitmap
484 @param bi - pointer to the source bitmap
485 @returns ai = ai or bi. ai is modified, bi is not modified
486*/
Dave Barachc3799992016-08-15 11:12:27 -0400487always_inline uword *clib_bitmap_or (uword * ai, uword * bi);
Dave Barach310f7fe2016-08-05 14:36:27 -0400488
489/** Logical operator across two bitmaps
490
491 @param ai - pointer to the destination bitmap
492 @param bi - pointer to the source bitmap
493 @returns ai = ai xor bi. ai is modified, bi is not modified
494*/
Dave Barachc3799992016-08-15 11:12:27 -0400495always_inline uword *clib_bitmap_xor (uword * ai, uword * bi);
Dave Barach310f7fe2016-08-05 14:36:27 -0400496
Ed Warnickecb9cada2015-12-08 15:45:58 -0700497/* ALU function definition macro for functions taking two bitmaps. */
498#define _(name, body, check_zero) \
499always_inline uword * \
500clib_bitmap_##name (uword * ai, uword * bi) \
501{ \
502 uword i, a, b, bi_len, n_trailing_zeros; \
503 \
504 n_trailing_zeros = 0; \
505 bi_len = vec_len (bi); \
506 if (bi_len > 0) \
507 clib_bitmap_vec_validate (ai, bi_len - 1); \
508 for (i = 0; i < vec_len (ai); i++) \
509 { \
510 a = ai[i]; \
511 b = i < bi_len ? bi[i] : 0; \
512 do { body; } while (0); \
513 ai[i] = a; \
514 if (check_zero) \
515 n_trailing_zeros = a ? 0 : (n_trailing_zeros + 1); \
516 } \
517 if (check_zero) \
518 _vec_len (ai) -= n_trailing_zeros; \
519 return ai; \
520}
521
522/* ALU functions: */
Florin Corasfcd23682018-06-29 03:22:44 -0700523/* *INDENT-OFF* */
Dave Barachc3799992016-08-15 11:12:27 -0400524_(and, a = a & b, 1)
Florin Corasfcd23682018-06-29 03:22:44 -0700525_(andnot, a = a & ~b, 1)
526_(or, a = a | b, 0)
527_(xor, a = a ^ b, 1)
528/* *INDENT-ON* */
Ed Warnickecb9cada2015-12-08 15:45:58 -0700529#undef _
Dave Barach310f7fe2016-08-05 14:36:27 -0400530/** Logical operator across two bitmaps which duplicates the first bitmap
531
532 @param ai - pointer to the destination bitmap
533 @param bi - pointer to the source bitmap
534 @returns aiDup = ai and bi. Neither ai nor bi are modified
535*/
Florin Corasfcd23682018-06-29 03:22:44 -0700536always_inline uword *clib_bitmap_dup_and (uword * ai, uword * bi);
Dave Barach310f7fe2016-08-05 14:36:27 -0400537
538/** Logical operator across two bitmaps which duplicates the first bitmap
539
540 @param ai - pointer to the destination bitmap
541 @param bi - pointer to the source bitmap
542 @returns aiDup = ai & ~bi. Neither ai nor bi are modified
543*/
Florin Corasfcd23682018-06-29 03:22:44 -0700544always_inline uword *clib_bitmap_dup_andnot (uword * ai, uword * bi);
Dave Barach310f7fe2016-08-05 14:36:27 -0400545
546/** Logical operator across two bitmaps which duplicates the first bitmap
547
548 @param ai - pointer to the destination bitmap
549 @param bi - pointer to the source bitmap
550 @returns aiDup = ai or bi. Neither ai nor bi are modified
551*/
Florin Corasfcd23682018-06-29 03:22:44 -0700552always_inline uword *clib_bitmap_dup_or (uword * ai, uword * bi);
Dave Barach310f7fe2016-08-05 14:36:27 -0400553
554/** Logical operator across two bitmaps which duplicates the first bitmap
555
556 @param ai - pointer to the destination bitmap
557 @param bi - pointer to the source bitmap
558 @returns aiDup = ai xor bi. Neither ai nor bi are modified
559*/
Florin Corasfcd23682018-06-29 03:22:44 -0700560always_inline uword *clib_bitmap_dup_xor (uword * ai, uword * bi);
Dave Barach310f7fe2016-08-05 14:36:27 -0400561
Ed Warnickecb9cada2015-12-08 15:45:58 -0700562#define _(name) \
563 always_inline uword * \
564 clib_bitmap_dup_##name (uword * ai, uword * bi) \
565{ return clib_bitmap_##name (clib_bitmap_dup (ai), bi); }
566
Florin Corasfcd23682018-06-29 03:22:44 -0700567/* *INDENT-OFF* */
Dave Barachc3799992016-08-15 11:12:27 -0400568_(and);
569_(andnot);
570_(or);
571_(xor);
Florin Corasfcd23682018-06-29 03:22:44 -0700572/* *INDENT-ON* */
Ed Warnickecb9cada2015-12-08 15:45:58 -0700573#undef _
574
Florin Corasfcd23682018-06-29 03:22:44 -0700575/* ALU function definition macro for functions taking one bitmap and an
576 * immediate. */
Ed Warnickecb9cada2015-12-08 15:45:58 -0700577#define _(name, body, check_zero) \
578always_inline uword * \
579clib_bitmap_##name (uword * ai, uword i) \
580{ \
581 uword i0 = i / BITS (ai[0]); \
582 uword i1 = i % BITS (ai[0]); \
583 uword a, b; \
584 clib_bitmap_vec_validate (ai, i0); \
585 a = ai[i0]; \
586 b = (uword) 1 << i1; \
587 do { body; } while (0); \
588 ai[i0] = a; \
589 if (check_zero && a == 0) \
590 ai = _clib_bitmap_remove_trailing_zeros (ai); \
591 return ai; \
592}
593
594/* ALU functions immediate: */
Florin Corasfcd23682018-06-29 03:22:44 -0700595/* *INDENT-OFF* */
Dave Barachc3799992016-08-15 11:12:27 -0400596_(andi, a = a & b, 1)
Florin Corasfcd23682018-06-29 03:22:44 -0700597_(andnoti, a = a & ~b, 1)
598_(ori, a = a | b, 0)
599_(xori, a = a ^ b, 1)
600/* *INDENT-ON* */
Ed Warnickecb9cada2015-12-08 15:45:58 -0700601#undef _
Florin Corasfcd23682018-06-29 03:22:44 -0700602
603/* ALU function definition macro for functions taking one bitmap and an
604 * immediate. No tail trimming */
605#define _(name, body) \
606always_inline uword * \
607clib_bitmap_##name##_notrim (uword * ai, uword i) \
608{ \
609 uword i0 = i / BITS (ai[0]); \
610 uword i1 = i % BITS (ai[0]); \
611 uword a, b; \
612 clib_bitmap_vec_validate (ai, i0); \
613 a = ai[i0]; \
614 b = (uword) 1 << i1; \
615 do { body; } while (0); \
616 ai[i0] = a; \
617 return ai; \
618}
619
620/* ALU functions immediate: */
621/* *INDENT-OFF* */
622_(andi, a = a & b)
623_(andnoti, a = a & ~b)
624_(ori, a = a | b)
625_(xori, a = a ^ b)
626#undef _
627/* *INDENT-ON* */
628
Dave Barach310f7fe2016-08-05 14:36:27 -0400629/** Return a random bitmap of the requested length
630 @param ai - pointer to the destination bitmap
631 @param n_bits - number of bits to allocate
Chris Luked4024f52016-09-06 09:32:36 -0400632 @param [in,out] seed - pointer to the random number seed
Dave Barach310f7fe2016-08-05 14:36:27 -0400633 @returns a reasonably random bitmap based. See random.h.
634*/
Florin Corasfcd23682018-06-29 03:22:44 -0700635always_inline uword *
636clib_bitmap_random (uword * ai, uword n_bits, u32 * seed)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700637{
638 vec_reset_length (ai);
639
640 if (n_bits > 0)
641 {
642 uword i = n_bits - 1;
643 uword i0, i1;
644 uword log2_rand_max;
645
646 log2_rand_max = min_log2 (random_u32_max ());
647
648 i0 = i / BITS (ai[0]);
649 i1 = i % BITS (ai[0]);
650
651 clib_bitmap_vec_validate (ai, i0);
652 for (i = 0; i <= i0; i++)
653 {
654 uword n;
655 for (n = 0; n < BITS (ai[i]); n += log2_rand_max)
656 ai[i] |= random_u32 (seed) << n;
657 }
658 if (i1 + 1 < BITS (ai[0]))
659 ai[i0] &= (((uword) 1 << (i1 + 1)) - 1);
660 }
661 return ai;
662}
663
Dave Barach310f7fe2016-08-05 14:36:27 -0400664/** Return the next set bit in a bitmap starting at bit i
665 @param ai - pointer to the bitmap
666 @param i - first bit position to test
Dave Barachc3799992016-08-15 11:12:27 -0400667 @returns first set bit position at or after i,
Dave Barach310f7fe2016-08-05 14:36:27 -0400668 ~0 if no further set bits are found
669*/
Ed Warnickecb9cada2015-12-08 15:45:58 -0700670always_inline uword
671clib_bitmap_next_set (uword * ai, uword i)
672{
673 uword i0 = i / BITS (ai[0]);
674 uword i1 = i % BITS (ai[0]);
675 uword t;
Dave Barachc3799992016-08-15 11:12:27 -0400676
Ed Warnickecb9cada2015-12-08 15:45:58 -0700677 if (i0 < vec_len (ai))
678 {
679 t = (ai[i0] >> i1) << i1;
680 if (t)
681 return log2_first_set (t) + i0 * BITS (ai[0]);
682
683 for (i0++; i0 < vec_len (ai); i0++)
684 {
685 t = ai[i0];
686 if (t)
687 return log2_first_set (t) + i0 * BITS (ai[0]);
688 }
689 }
690
691 return ~0;
692}
693
Dave Barach310f7fe2016-08-05 14:36:27 -0400694/** Return the next clear bit in a bitmap starting at bit i
695 @param ai - pointer to the bitmap
696 @param i - first bit position to test
697 @returns first clear bit position at or after i
698*/
Ed Warnickecb9cada2015-12-08 15:45:58 -0700699always_inline uword
700clib_bitmap_next_clear (uword * ai, uword i)
701{
702 uword i0 = i / BITS (ai[0]);
703 uword i1 = i % BITS (ai[0]);
704 uword t;
Dave Barachc3799992016-08-15 11:12:27 -0400705
Ed Warnickecb9cada2015-12-08 15:45:58 -0700706 if (i0 < vec_len (ai))
707 {
708 t = (~ai[i0] >> i1) << i1;
709 if (t)
710 return log2_first_set (t) + i0 * BITS (ai[0]);
711
712 for (i0++; i0 < vec_len (ai); i0++)
713 {
Dave Barachc3799992016-08-15 11:12:27 -0400714 t = ~ai[i0];
Ed Warnickecb9cada2015-12-08 15:45:58 -0700715 if (t)
716 return log2_first_set (t) + i0 * BITS (ai[0]);
717 }
John Loef8db362018-07-04 16:27:59 -0400718
719 /* no clear bit left in bitmap, return bit just beyond bitmap */
Dave Barach37b44542020-04-27 18:38:36 -0400720 return (i0 * BITS (ai[0])) + 1;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700721 }
722 return i;
723}
724
Damjan Marion7f57f502021-04-15 16:13:20 +0200725uword unformat_bitmap_mask (unformat_input_t *input, va_list *va);
726uword unformat_bitmap_list (unformat_input_t *input, va_list *va);
727u8 *format_bitmap_hex (u8 *s, va_list *args);
728u8 *format_bitmap_list (u8 *s, va_list *args);
Yi Hee4a9eb72018-07-17 14:18:41 +0800729
Ed Warnickecb9cada2015-12-08 15:45:58 -0700730#endif /* included_clib_bitmap_h */
Dave Barachc3799992016-08-15 11:12:27 -0400731
732/*
733 * fd.io coding-style-patch-verification: ON
734 *
735 * Local Variables:
736 * eval: (c-set-style "gnu")
737 * End:
738 */