blob: 096d3f1aa4a2d1ef4782c70998b5dde8782bb149 [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>
Ed Warnickecb9cada2015-12-08 15:45:58 -070048
Damjan Marion0b140722016-06-14 00:36:09 +020049typedef uword clib_bitmap_t;
50
Dave Barach310f7fe2016-08-05 14:36:27 -040051/** predicate function; is an entire bitmap empty?
52 @param ai - pointer to a bitmap
53 @returns 1 if the entire bitmap is zero, 0 otherwise
54*/
Ed Warnickecb9cada2015-12-08 15:45:58 -070055always_inline uword
56clib_bitmap_is_zero (uword * ai)
57{
58 uword i;
59 for (i = 0; i < vec_len (ai); i++)
60 if (ai[i] != 0)
61 return 0;
62 return 1;
63}
64
Dave Barach310f7fe2016-08-05 14:36:27 -040065/** predicate function; are two bitmaps equal?
66 @param a - pointer to a bitmap
67 @param b - pointer to a bitmap
68 @returns 1 if the bitmaps are equal, 0 otherwise
69*/
Ed Warnickecb9cada2015-12-08 15:45:58 -070070always_inline uword
71clib_bitmap_is_equal (uword * a, uword * b)
72{
73 uword i;
74 if (vec_len (a) != vec_len (b))
75 return 0;
76 for (i = 0; i < vec_len (a); i++)
77 if (a[i] != b[i])
78 return 0;
79 return 1;
80}
81
Dave Barach310f7fe2016-08-05 14:36:27 -040082/** Duplicate a bitmap
Chris Luked4024f52016-09-06 09:32:36 -040083 @param v - pointer to a bitmap
Dave Barach310f7fe2016-08-05 14:36:27 -040084 @returns a duplicate of the bitmap
85*/
Ed Warnickecb9cada2015-12-08 15:45:58 -070086#define clib_bitmap_dup(v) vec_dup(v)
87
Dave Barach310f7fe2016-08-05 14:36:27 -040088/** Free a bitmap
89 @param v - pointer to the bitmap to free
90*/
Ed Warnickecb9cada2015-12-08 15:45:58 -070091#define clib_bitmap_free(v) vec_free(v)
92
Dave Barach310f7fe2016-08-05 14:36:27 -040093/** Number of bytes in a bitmap
94 @param v - pointer to the bitmap
95*/
Ed Warnickecb9cada2015-12-08 15:45:58 -070096#define clib_bitmap_bytes(v) vec_bytes(v)
97
Dave Barach310f7fe2016-08-05 14:36:27 -040098/** Clear a bitmap
99 @param v - pointer to the bitmap to clear
100*/
Ed Warnickecb9cada2015-12-08 15:45:58 -0700101#define clib_bitmap_zero(v) vec_zero(v)
102
Dave Barach310f7fe2016-08-05 14:36:27 -0400103/** Allocate a bitmap with the supplied number of bits
104 @param [out] v - the resulting bitmap
105 @param n_bits - the required number of bits
106*/
107
Ed Warnickecb9cada2015-12-08 15:45:58 -0700108#define clib_bitmap_alloc(v,n_bits) \
109 v = vec_new (uword, ((n_bits) + BITS (uword) - 1) / BITS (uword))
110
111#define clib_bitmap_vec_validate(v,i) vec_validate_aligned((v),(i),sizeof(uword))
112
113/* Make sure that a bitmap is at least n_bits in size */
114#define clib_bitmap_validate(v,n_bits) \
115 clib_bitmap_vec_validate ((v), ((n_bits) - 1) / BITS (uword))
116
Neale Rannsc19ac302021-10-25 09:06:48 +0000117/** Copy a bitmap
118 @param dst - copy to
119 @param src - copy from
120*/
121static_always_inline void
122clib_bitmap_copy (clib_bitmap_t **dst, const clib_bitmap_t *src)
123{
124 if (vec_len (src))
125 {
126 clib_bitmap_vec_validate (*dst, vec_len (src) - 1);
127 vec_copy (*dst, src);
128 }
129 else
130 {
131 vec_reset_length (*dst);
132 }
133}
134
Ed Warnickecb9cada2015-12-08 15:45:58 -0700135/* low-level routine to remove trailing zeros from a bitmap */
136always_inline uword *
137_clib_bitmap_remove_trailing_zeros (uword * a)
138{
139 word i;
140 if (a)
141 {
142 for (i = _vec_len (a) - 1; i >= 0; i--)
143 if (a[i] != 0)
144 break;
145 _vec_len (a) = i + 1;
146 }
147 return a;
148}
149
Dave Barach310f7fe2016-08-05 14:36:27 -0400150/** Sets the ith bit of a bitmap to new_value.
Dave Barachc3799992016-08-15 11:12:27 -0400151 No sanity checking. Be careful.
Dave Barach310f7fe2016-08-05 14:36:27 -0400152 @param a - pointer to the bitmap
153 @param i - the bit position to interrogate
154 @param new_value - new value for the bit
155 @returns the old value of the bit
156*/
Ed Warnickecb9cada2015-12-08 15:45:58 -0700157always_inline uword
158clib_bitmap_set_no_check (uword * a, uword i, uword new_value)
159{
160 uword i0 = i / BITS (a[0]);
161 uword i1 = i % BITS (a[0]);
162 uword bit = (uword) 1 << i1;
163 uword ai, old_value;
164
165 /* Removed ASSERT since uword * a may not be a vector. */
166 /* ASSERT (i0 < vec_len (a)); */
167
168 ai = a[i0];
169 old_value = (ai & bit) != 0;
Dave Barachc3799992016-08-15 11:12:27 -0400170 ai &= ~bit;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700171 ai |= ((uword) (new_value != 0)) << i1;
172 a[i0] = ai;
173 return old_value;
174}
175
Dave Barach310f7fe2016-08-05 14:36:27 -0400176/** Sets the ith bit of a bitmap to new_value
177 Removes trailing zeros from the bitmap
Chris Luked4024f52016-09-06 09:32:36 -0400178 @param ai - pointer to the bitmap
Dave Barach310f7fe2016-08-05 14:36:27 -0400179 @param i - the bit position to interrogate
Chris Luked4024f52016-09-06 09:32:36 -0400180 @param value - new value for the bit
Dave Barach310f7fe2016-08-05 14:36:27 -0400181 @returns the old value of the bit
182*/
Ed Warnickecb9cada2015-12-08 15:45:58 -0700183always_inline uword *
184clib_bitmap_set (uword * ai, uword i, uword value)
185{
186 uword i0 = i / BITS (ai[0]);
187 uword i1 = i % BITS (ai[0]);
188 uword a;
189
190 /* Check for writing a zero to beyond end of bitmap. */
191 if (value == 0 && i0 >= vec_len (ai))
192 return ai; /* Implied trailing zeros. */
193
194 clib_bitmap_vec_validate (ai, i0);
195
196 a = ai[i0];
197 a &= ~((uword) 1 << i1);
198 a |= ((uword) (value != 0)) << i1;
199 ai[i0] = a;
200
201 /* If bits have been cleared, test for zero. */
202 if (a == 0)
203 ai = _clib_bitmap_remove_trailing_zeros (ai);
204
205 return ai;
206}
207
Stanislav Zaikin09abed62021-11-04 09:32:32 +0100208always_inline u8
209clib_bitmap_will_expand (uword *ai, uword i)
210{
Damjan Marion66d4cb52022-03-17 18:59:46 +0100211 return (i / BITS (ai[0])) < vec_max_len (ai);
Stanislav Zaikin09abed62021-11-04 09:32:32 +0100212}
213
Dave Barach310f7fe2016-08-05 14:36:27 -0400214/** Gets the ith bit value from a bitmap
215 @param ai - pointer to the bitmap
216 @param i - the bit position to interrogate
217 @returns the indicated bit value
218*/
Ed Warnickecb9cada2015-12-08 15:45:58 -0700219always_inline uword
220clib_bitmap_get (uword * ai, uword i)
221{
222 uword i0 = i / BITS (ai[0]);
223 uword i1 = i % BITS (ai[0]);
224 return i0 < vec_len (ai) && 0 != ((ai[i0] >> i1) & 1);
225}
226
Dave Barach310f7fe2016-08-05 14:36:27 -0400227/** Gets the ith bit value from a bitmap
228 Does not sanity-check the bit position. Be careful.
229 @param ai - pointer to the bitmap
230 @param i - the bit position to interrogate
231 @returns the indicated bit value, or garbage if the bit position is
232 out of range.
Ed Warnickecb9cada2015-12-08 15:45:58 -0700233*/
234always_inline uword
235clib_bitmap_get_no_check (uword * ai, uword i)
236{
237 uword i0 = i / BITS (ai[0]);
238 uword i1 = i % BITS (ai[0]);
239 return 0 != ((ai[i0] >> i1) & 1);
240}
241
Ed Warnickecb9cada2015-12-08 15:45:58 -0700242always_inline uword
243clib_bitmap_get_multiple_no_check (uword * ai, uword i, uword n_bits)
244{
245 uword i0 = i / BITS (ai[0]);
246 uword i1 = i % BITS (ai[0]);
247 ASSERT (i1 + n_bits <= BITS (uword));
248 return 0 != ((ai[i0] >> i1) & pow2_mask (n_bits));
249}
250
Dave Barach310f7fe2016-08-05 14:36:27 -0400251/** Gets the ith through ith + n_bits bit values from a bitmap
252 @param bitmap - pointer to the bitmap
253 @param i - the first bit position to retrieve
254 @param n_bits - the number of bit positions to retrieve
255 @returns the indicated range of bits
256*/
Ed Warnickecb9cada2015-12-08 15:45:58 -0700257always_inline uword
258clib_bitmap_get_multiple (uword * bitmap, uword i, uword n_bits)
259{
260 uword i0, i1, result;
261 uword l = vec_len (bitmap);
262
Dave Barachf9c231e2016-08-05 10:10:18 -0400263 ASSERT (n_bits <= BITS (result));
Ed Warnickecb9cada2015-12-08 15:45:58 -0700264
265 i0 = i / BITS (bitmap[0]);
266 i1 = i % BITS (bitmap[0]);
267
268 /* Check first word. */
269 result = 0;
270 if (i0 < l)
271 {
272 result |= (bitmap[i0] >> i1);
273 if (n_bits < BITS (bitmap[0]))
274 result &= (((uword) 1 << n_bits) - 1);
275 }
276
277 /* Check for overlap into next word. */
278 i0++;
279 if (i1 + n_bits > BITS (bitmap[0]) && i0 < l)
280 {
281 n_bits -= BITS (bitmap[0]) - i1;
Dave Barachc3799992016-08-15 11:12:27 -0400282 result |=
283 (bitmap[i0] & (((uword) 1 << n_bits) - 1)) << (BITS (bitmap[0]) - i1);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700284 }
285
286 return result;
287}
288
Dave Barach310f7fe2016-08-05 14:36:27 -0400289/** sets the ith through ith + n_bits bits in a bitmap
290 @param bitmap - pointer to the bitmap
291 @param i - the first bit position to retrieve
292 @param value - the values to set
293 @param n_bits - the number of bit positions to set
294 @returns a pointer to the updated bitmap, which may expand and move
295*/
Ed Warnickecb9cada2015-12-08 15:45:58 -0700296
Ed Warnickecb9cada2015-12-08 15:45:58 -0700297always_inline uword *
298clib_bitmap_set_multiple (uword * bitmap, uword i, uword value, uword n_bits)
299{
300 uword i0, i1, l, t, m;
301
Dave Barachf9c231e2016-08-05 10:10:18 -0400302 ASSERT (n_bits <= BITS (value));
Ed Warnickecb9cada2015-12-08 15:45:58 -0700303
304 i0 = i / BITS (bitmap[0]);
305 i1 = i % BITS (bitmap[0]);
306
307 /* Allocate bitmap. */
308 clib_bitmap_vec_validate (bitmap, (i + n_bits) / BITS (bitmap[0]));
309 l = vec_len (bitmap);
310
311 m = ~0;
312 if (n_bits < BITS (value))
313 m = (((uword) 1 << n_bits) - 1);
314 value &= m;
315
316 /* Insert into first word. */
317 t = bitmap[i0];
318 t &= ~(m << i1);
319 t |= value << i1;
320 bitmap[i0] = t;
321
322 /* Insert into second word. */
323 i0++;
324 if (i1 + n_bits > BITS (bitmap[0]) && i0 < l)
325 {
326 t = BITS (bitmap[0]) - i1;
327 value >>= t;
328 n_bits -= t;
329 t = bitmap[i0];
330 m = ((uword) 1 << n_bits) - 1;
331 t &= ~m;
332 t |= value;
333 bitmap[i0] = t;
334 }
335
336 return bitmap;
337}
338
Ed Warnickecb9cada2015-12-08 15:45:58 -0700339always_inline uword *
Korian Edeline40e6bdf2018-08-08 11:30:30 +0200340clib_bitmap_set_region (uword * bitmap, uword i, uword value, uword n_bits)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700341{
342 uword a0, a1, b0;
343 uword i_end, mask;
344
345 a0 = i / BITS (bitmap[0]);
346 a1 = i % BITS (bitmap[0]);
347
348 i_end = i + n_bits;
349 b0 = i_end / BITS (bitmap[0]);
350
351 clib_bitmap_vec_validate (bitmap, b0);
352
353 /* First word. */
354 mask = n_bits < BITS (bitmap[0]) ? pow2_mask (n_bits) : ~0;
355 mask <<= a1;
356
357 if (value)
358 bitmap[a0] |= mask;
359 else
360 bitmap[a0] &= ~mask;
361
362 for (a0++; a0 < b0; a0++)
363 bitmap[a0] = value ? ~0 : 0;
364
365 if (a0 == b0)
366 {
367 word n_bits_left = n_bits - (BITS (bitmap[0]) - a1);
368 mask = pow2_mask (n_bits_left);
369 if (value)
370 bitmap[a0] |= mask;
371 else
372 bitmap[a0] &= ~mask;
373 }
374
375 return bitmap;
376}
377
Dave Barach310f7fe2016-08-05 14:36:27 -0400378/** Macro to iterate across set bits in a bitmap
379
380 @param i - the current set bit
381 @param ai - the bitmap
382 @param body - the expression to evaluate for each set bit
383*/
Damjan Marionf0ca1e82020-12-13 23:26:56 +0100384#define clib_bitmap_foreach(i,ai) \
385 if (ai) \
386 for (i = clib_bitmap_first_set (ai); \
387 i != ~0; \
388 i = clib_bitmap_next_set (ai, i + 1))
389
Dave Barach310f7fe2016-08-05 14:36:27 -0400390/** Return the lowest numbered set bit in a bitmap
391 @param ai - pointer to the bitmap
392 @returns lowest numbered set bit, or ~0 if the entire bitmap is zero
393*/
Dave Barachc3799992016-08-15 11:12:27 -0400394always_inline uword
395clib_bitmap_first_set (uword * ai)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700396{
Damjan Marion32ab9542018-06-26 01:29:55 +0200397 uword i = 0;
398#if uword_bits == 64
Damjan Marion13c98a22018-06-26 16:05:43 +0200399#if defined(CLIB_HAVE_VEC256)
Damjan Marion32ab9542018-06-26 01:29:55 +0200400 while (i + 7 < vec_len (ai))
401 {
402 u64x4 v;
403 v = u64x4_load_unaligned (ai + i) | u64x4_load_unaligned (ai + i + 4);
404 if (!u64x4_is_all_zero (v))
405 break;
406 i += 8;
407 }
Damjan Marion13c98a22018-06-26 16:05:43 +0200408#elif defined(CLIB_HAVE_VEC128) && defined(CLIB_HAVE_VEC128_UNALIGNED_LOAD_STORE)
Damjan Marion32ab9542018-06-26 01:29:55 +0200409 while (i + 3 < vec_len (ai))
410 {
411 u64x2 v;
412 v = u64x2_load_unaligned (ai + i) | u64x2_load_unaligned (ai + i + 2);
413 if (!u64x2_is_all_zero (v))
414 break;
415 i += 4;
416 }
417#endif
418#endif
419 for (; i < vec_len (ai); i++)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700420 {
421 uword x = ai[i];
422 if (x != 0)
423 return i * BITS (ai[0]) + log2_first_set (x);
424 }
425 return ~0;
426}
427
Dave Barach310f7fe2016-08-05 14:36:27 -0400428/** Return the higest numbered set bit in a bitmap
429 @param ai - pointer to the bitmap
430 @returns lowest numbered set bit, or ~0 if the entire bitmap is zero
431*/
Dave Barachc3799992016-08-15 11:12:27 -0400432always_inline uword
433clib_bitmap_last_set (uword * ai)
Damjan Marion0247b462016-06-08 01:37:11 +0200434{
435 uword i;
436
Dave Barachc3799992016-08-15 11:12:27 -0400437 for (i = vec_len (ai); i > 0; i--)
Damjan Marion0247b462016-06-08 01:37:11 +0200438 {
Damjan Marionec175102016-06-30 01:02:17 +0200439 uword x = ai[i - 1];
Damjan Marion0247b462016-06-08 01:37:11 +0200440 if (x != 0)
441 {
442 uword first_bit;
Damjan Marion11056002018-05-10 13:40:44 +0200443 first_bit = count_leading_zeros (x);
Damjan Marionec175102016-06-30 01:02:17 +0200444 return (i) * BITS (ai[0]) - first_bit - 1;
Damjan Marion0247b462016-06-08 01:37:11 +0200445 }
446 }
447 return ~0;
448}
449
Dave Barach310f7fe2016-08-05 14:36:27 -0400450/** Return the lowest numbered clear bit in a bitmap
451 @param ai - pointer to the bitmap
452 @returns lowest numbered clear bit
453*/
Ed Warnickecb9cada2015-12-08 15:45:58 -0700454always_inline uword
455clib_bitmap_first_clear (uword * ai)
456{
457 uword i;
458 for (i = 0; i < vec_len (ai); i++)
459 {
460 uword x = ~ai[i];
461 if (x != 0)
462 return i * BITS (ai[0]) + log2_first_set (x);
463 }
464 return i * BITS (ai[0]);
465}
466
Dave Barach310f7fe2016-08-05 14:36:27 -0400467/** Return the number of set bits in a bitmap
468 @param ai - pointer to the bitmap
469 @returns the number of set bits in the bitmap
470*/
Ed Warnickecb9cada2015-12-08 15:45:58 -0700471always_inline uword
472clib_bitmap_count_set_bits (uword * ai)
473{
474 uword i;
475 uword n_set = 0;
476 for (i = 0; i < vec_len (ai); i++)
477 n_set += count_set_bits (ai[i]);
478 return n_set;
479}
480
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 and bi. ai is modified, bi is not modified
486*/
Dave Barachc3799992016-08-15 11:12:27 -0400487always_inline uword *clib_bitmap_and (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 & ~bi. ai is modified, bi is not modified
494*/
Dave Barachc3799992016-08-15 11:12:27 -0400495always_inline uword *clib_bitmap_andnot (uword * ai, uword * bi);
Dave Barach310f7fe2016-08-05 14:36:27 -0400496
497/** Logical operator across two bitmaps
498
499 @param ai - pointer to the destination bitmap
500 @param bi - pointer to the source bitmap
501 @returns ai = ai & ~bi. ai is modified, bi is not modified
502*/
Dave Barachc3799992016-08-15 11:12:27 -0400503always_inline uword *clib_bitmap_or (uword * ai, uword * bi);
Dave Barach310f7fe2016-08-05 14:36:27 -0400504/** Logical operator across two bitmaps
505
506 @param ai - pointer to the destination bitmap
507 @param bi - pointer to the source bitmap
508 @returns ai = ai or bi. ai is modified, bi is not modified
509*/
Dave Barachc3799992016-08-15 11:12:27 -0400510always_inline uword *clib_bitmap_or (uword * ai, uword * bi);
Dave Barach310f7fe2016-08-05 14:36:27 -0400511
512/** Logical operator across two bitmaps
513
514 @param ai - pointer to the destination bitmap
515 @param bi - pointer to the source bitmap
516 @returns ai = ai xor bi. ai is modified, bi is not modified
517*/
Dave Barachc3799992016-08-15 11:12:27 -0400518always_inline uword *clib_bitmap_xor (uword * ai, uword * bi);
Dave Barach310f7fe2016-08-05 14:36:27 -0400519
Ed Warnickecb9cada2015-12-08 15:45:58 -0700520/* ALU function definition macro for functions taking two bitmaps. */
521#define _(name, body, check_zero) \
522always_inline uword * \
523clib_bitmap_##name (uword * ai, uword * bi) \
524{ \
525 uword i, a, b, bi_len, n_trailing_zeros; \
526 \
527 n_trailing_zeros = 0; \
528 bi_len = vec_len (bi); \
529 if (bi_len > 0) \
530 clib_bitmap_vec_validate (ai, bi_len - 1); \
531 for (i = 0; i < vec_len (ai); i++) \
532 { \
533 a = ai[i]; \
534 b = i < bi_len ? bi[i] : 0; \
535 do { body; } while (0); \
536 ai[i] = a; \
537 if (check_zero) \
538 n_trailing_zeros = a ? 0 : (n_trailing_zeros + 1); \
539 } \
540 if (check_zero) \
541 _vec_len (ai) -= n_trailing_zeros; \
542 return ai; \
543}
544
545/* ALU functions: */
Florin Corasfcd23682018-06-29 03:22:44 -0700546/* *INDENT-OFF* */
Dave Barachc3799992016-08-15 11:12:27 -0400547_(and, a = a & b, 1)
Florin Corasfcd23682018-06-29 03:22:44 -0700548_(andnot, a = a & ~b, 1)
549_(or, a = a | b, 0)
550_(xor, a = a ^ b, 1)
551/* *INDENT-ON* */
Ed Warnickecb9cada2015-12-08 15:45:58 -0700552#undef _
Dave Barach310f7fe2016-08-05 14:36:27 -0400553/** Logical operator across two bitmaps which duplicates the first bitmap
554
555 @param ai - pointer to the destination bitmap
556 @param bi - pointer to the source bitmap
557 @returns aiDup = ai and bi. Neither ai nor bi are modified
558*/
Florin Corasfcd23682018-06-29 03:22:44 -0700559always_inline uword *clib_bitmap_dup_and (uword * ai, uword * bi);
Dave Barach310f7fe2016-08-05 14:36:27 -0400560
561/** Logical operator across two bitmaps which duplicates the first bitmap
562
563 @param ai - pointer to the destination bitmap
564 @param bi - pointer to the source bitmap
565 @returns aiDup = ai & ~bi. Neither ai nor bi are modified
566*/
Florin Corasfcd23682018-06-29 03:22:44 -0700567always_inline uword *clib_bitmap_dup_andnot (uword * ai, uword * bi);
Dave Barach310f7fe2016-08-05 14:36:27 -0400568
569/** Logical operator across two bitmaps which duplicates the first bitmap
570
571 @param ai - pointer to the destination bitmap
572 @param bi - pointer to the source bitmap
573 @returns aiDup = ai or bi. Neither ai nor bi are modified
574*/
Florin Corasfcd23682018-06-29 03:22:44 -0700575always_inline uword *clib_bitmap_dup_or (uword * ai, uword * bi);
Dave Barach310f7fe2016-08-05 14:36:27 -0400576
577/** Logical operator across two bitmaps which duplicates the first bitmap
578
579 @param ai - pointer to the destination bitmap
580 @param bi - pointer to the source bitmap
581 @returns aiDup = ai xor bi. Neither ai nor bi are modified
582*/
Florin Corasfcd23682018-06-29 03:22:44 -0700583always_inline uword *clib_bitmap_dup_xor (uword * ai, uword * bi);
Dave Barach310f7fe2016-08-05 14:36:27 -0400584
Ed Warnickecb9cada2015-12-08 15:45:58 -0700585#define _(name) \
586 always_inline uword * \
587 clib_bitmap_dup_##name (uword * ai, uword * bi) \
588{ return clib_bitmap_##name (clib_bitmap_dup (ai), bi); }
589
Florin Corasfcd23682018-06-29 03:22:44 -0700590/* *INDENT-OFF* */
Dave Barachc3799992016-08-15 11:12:27 -0400591_(and);
592_(andnot);
593_(or);
594_(xor);
Florin Corasfcd23682018-06-29 03:22:44 -0700595/* *INDENT-ON* */
Ed Warnickecb9cada2015-12-08 15:45:58 -0700596#undef _
597
Florin Corasfcd23682018-06-29 03:22:44 -0700598/* ALU function definition macro for functions taking one bitmap and an
599 * immediate. */
Ed Warnickecb9cada2015-12-08 15:45:58 -0700600#define _(name, body, check_zero) \
601always_inline uword * \
602clib_bitmap_##name (uword * ai, uword i) \
603{ \
604 uword i0 = i / BITS (ai[0]); \
605 uword i1 = i % BITS (ai[0]); \
606 uword a, b; \
607 clib_bitmap_vec_validate (ai, i0); \
608 a = ai[i0]; \
609 b = (uword) 1 << i1; \
610 do { body; } while (0); \
611 ai[i0] = a; \
612 if (check_zero && a == 0) \
613 ai = _clib_bitmap_remove_trailing_zeros (ai); \
614 return ai; \
615}
616
617/* ALU functions immediate: */
Florin Corasfcd23682018-06-29 03:22:44 -0700618/* *INDENT-OFF* */
Dave Barachc3799992016-08-15 11:12:27 -0400619_(andi, a = a & b, 1)
Florin Corasfcd23682018-06-29 03:22:44 -0700620_(andnoti, a = a & ~b, 1)
621_(ori, a = a | b, 0)
622_(xori, a = a ^ b, 1)
623/* *INDENT-ON* */
Ed Warnickecb9cada2015-12-08 15:45:58 -0700624#undef _
Florin Corasfcd23682018-06-29 03:22:44 -0700625
626/* ALU function definition macro for functions taking one bitmap and an
627 * immediate. No tail trimming */
628#define _(name, body) \
629always_inline uword * \
630clib_bitmap_##name##_notrim (uword * ai, uword i) \
631{ \
632 uword i0 = i / BITS (ai[0]); \
633 uword i1 = i % BITS (ai[0]); \
634 uword a, b; \
635 clib_bitmap_vec_validate (ai, i0); \
636 a = ai[i0]; \
637 b = (uword) 1 << i1; \
638 do { body; } while (0); \
639 ai[i0] = a; \
640 return ai; \
641}
642
643/* ALU functions immediate: */
644/* *INDENT-OFF* */
645_(andi, a = a & b)
646_(andnoti, a = a & ~b)
647_(ori, a = a | b)
648_(xori, a = a ^ b)
649#undef _
650/* *INDENT-ON* */
651
Dave Barach310f7fe2016-08-05 14:36:27 -0400652/** Return a random bitmap of the requested length
653 @param ai - pointer to the destination bitmap
654 @param n_bits - number of bits to allocate
Chris Luked4024f52016-09-06 09:32:36 -0400655 @param [in,out] seed - pointer to the random number seed
Dave Barach310f7fe2016-08-05 14:36:27 -0400656 @returns a reasonably random bitmap based. See random.h.
657*/
Florin Corasfcd23682018-06-29 03:22:44 -0700658always_inline uword *
659clib_bitmap_random (uword * ai, uword n_bits, u32 * seed)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700660{
661 vec_reset_length (ai);
662
663 if (n_bits > 0)
664 {
665 uword i = n_bits - 1;
666 uword i0, i1;
667 uword log2_rand_max;
668
669 log2_rand_max = min_log2 (random_u32_max ());
670
671 i0 = i / BITS (ai[0]);
672 i1 = i % BITS (ai[0]);
673
674 clib_bitmap_vec_validate (ai, i0);
675 for (i = 0; i <= i0; i++)
676 {
677 uword n;
678 for (n = 0; n < BITS (ai[i]); n += log2_rand_max)
679 ai[i] |= random_u32 (seed) << n;
680 }
681 if (i1 + 1 < BITS (ai[0]))
682 ai[i0] &= (((uword) 1 << (i1 + 1)) - 1);
683 }
684 return ai;
685}
686
Dave Barach310f7fe2016-08-05 14:36:27 -0400687/** Return the next set bit in a bitmap starting at bit i
688 @param ai - pointer to the bitmap
689 @param i - first bit position to test
Dave Barachc3799992016-08-15 11:12:27 -0400690 @returns first set bit position at or after i,
Dave Barach310f7fe2016-08-05 14:36:27 -0400691 ~0 if no further set bits are found
692*/
Ed Warnickecb9cada2015-12-08 15:45:58 -0700693always_inline uword
694clib_bitmap_next_set (uword * ai, uword i)
695{
696 uword i0 = i / BITS (ai[0]);
697 uword i1 = i % BITS (ai[0]);
698 uword t;
Dave Barachc3799992016-08-15 11:12:27 -0400699
Ed Warnickecb9cada2015-12-08 15:45:58 -0700700 if (i0 < vec_len (ai))
701 {
702 t = (ai[i0] >> i1) << i1;
703 if (t)
704 return log2_first_set (t) + i0 * BITS (ai[0]);
705
706 for (i0++; i0 < vec_len (ai); i0++)
707 {
708 t = ai[i0];
709 if (t)
710 return log2_first_set (t) + i0 * BITS (ai[0]);
711 }
712 }
713
714 return ~0;
715}
716
Dave Barach310f7fe2016-08-05 14:36:27 -0400717/** Return the next clear bit in a bitmap starting at bit i
718 @param ai - pointer to the bitmap
719 @param i - first bit position to test
720 @returns first clear bit position at or after i
721*/
Ed Warnickecb9cada2015-12-08 15:45:58 -0700722always_inline uword
723clib_bitmap_next_clear (uword * ai, uword i)
724{
725 uword i0 = i / BITS (ai[0]);
726 uword i1 = i % BITS (ai[0]);
727 uword t;
Dave Barachc3799992016-08-15 11:12:27 -0400728
Ed Warnickecb9cada2015-12-08 15:45:58 -0700729 if (i0 < vec_len (ai))
730 {
731 t = (~ai[i0] >> i1) << i1;
732 if (t)
733 return log2_first_set (t) + i0 * BITS (ai[0]);
734
735 for (i0++; i0 < vec_len (ai); i0++)
736 {
Dave Barachc3799992016-08-15 11:12:27 -0400737 t = ~ai[i0];
Ed Warnickecb9cada2015-12-08 15:45:58 -0700738 if (t)
739 return log2_first_set (t) + i0 * BITS (ai[0]);
740 }
John Loef8db362018-07-04 16:27:59 -0400741
jiangxiaominga3d8c2c2021-12-30 08:52:38 +0000742 return i0 * BITS (ai[0]);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700743 }
744 return i;
745}
746
Damjan Marion7f57f502021-04-15 16:13:20 +0200747uword unformat_bitmap_mask (unformat_input_t *input, va_list *va);
748uword unformat_bitmap_list (unformat_input_t *input, va_list *va);
749u8 *format_bitmap_hex (u8 *s, va_list *args);
750u8 *format_bitmap_list (u8 *s, va_list *args);
Yi Hee4a9eb72018-07-17 14:18:41 +0800751
Ed Warnickecb9cada2015-12-08 15:45:58 -0700752#endif /* included_clib_bitmap_h */
Dave Barachc3799992016-08-15 11:12:27 -0400753
754/*
755 * fd.io coding-style-patch-verification: ON
756 *
757 * Local Variables:
758 * eval: (c-set-style "gnu")
759 * End:
760 */