blob: d9bdd0fac7ded05f24823fc32c6372dd7b42afa7 [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
Neale Rannsc19ac302021-10-25 09:06:48 +0000118/** Copy a bitmap
119 @param dst - copy to
120 @param src - copy from
121*/
122static_always_inline void
123clib_bitmap_copy (clib_bitmap_t **dst, const clib_bitmap_t *src)
124{
125 if (vec_len (src))
126 {
127 clib_bitmap_vec_validate (*dst, vec_len (src) - 1);
128 vec_copy (*dst, src);
129 }
130 else
131 {
132 vec_reset_length (*dst);
133 }
134}
135
Ed Warnickecb9cada2015-12-08 15:45:58 -0700136/* low-level routine to remove trailing zeros from a bitmap */
137always_inline uword *
138_clib_bitmap_remove_trailing_zeros (uword * a)
139{
140 word i;
141 if (a)
142 {
143 for (i = _vec_len (a) - 1; i >= 0; i--)
144 if (a[i] != 0)
145 break;
146 _vec_len (a) = i + 1;
147 }
148 return a;
149}
150
Dave Barach310f7fe2016-08-05 14:36:27 -0400151/** Sets the ith bit of a bitmap to new_value.
Dave Barachc3799992016-08-15 11:12:27 -0400152 No sanity checking. Be careful.
Dave Barach310f7fe2016-08-05 14:36:27 -0400153 @param a - pointer to the bitmap
154 @param i - the bit position to interrogate
155 @param new_value - new value for the bit
156 @returns the old value of the bit
157*/
Ed Warnickecb9cada2015-12-08 15:45:58 -0700158always_inline uword
159clib_bitmap_set_no_check (uword * a, uword i, uword new_value)
160{
161 uword i0 = i / BITS (a[0]);
162 uword i1 = i % BITS (a[0]);
163 uword bit = (uword) 1 << i1;
164 uword ai, old_value;
165
166 /* Removed ASSERT since uword * a may not be a vector. */
167 /* ASSERT (i0 < vec_len (a)); */
168
169 ai = a[i0];
170 old_value = (ai & bit) != 0;
Dave Barachc3799992016-08-15 11:12:27 -0400171 ai &= ~bit;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700172 ai |= ((uword) (new_value != 0)) << i1;
173 a[i0] = ai;
174 return old_value;
175}
176
Dave Barach310f7fe2016-08-05 14:36:27 -0400177/** Sets the ith bit of a bitmap to new_value
178 Removes trailing zeros from the bitmap
Chris Luked4024f52016-09-06 09:32:36 -0400179 @param ai - pointer to the bitmap
Dave Barach310f7fe2016-08-05 14:36:27 -0400180 @param i - the bit position to interrogate
Chris Luked4024f52016-09-06 09:32:36 -0400181 @param value - new value for the bit
Dave Barach310f7fe2016-08-05 14:36:27 -0400182 @returns the old value of the bit
183*/
Ed Warnickecb9cada2015-12-08 15:45:58 -0700184always_inline uword *
185clib_bitmap_set (uword * ai, uword i, uword value)
186{
187 uword i0 = i / BITS (ai[0]);
188 uword i1 = i % BITS (ai[0]);
189 uword a;
190
191 /* Check for writing a zero to beyond end of bitmap. */
192 if (value == 0 && i0 >= vec_len (ai))
193 return ai; /* Implied trailing zeros. */
194
195 clib_bitmap_vec_validate (ai, i0);
196
197 a = ai[i0];
198 a &= ~((uword) 1 << i1);
199 a |= ((uword) (value != 0)) << i1;
200 ai[i0] = a;
201
202 /* If bits have been cleared, test for zero. */
203 if (a == 0)
204 ai = _clib_bitmap_remove_trailing_zeros (ai);
205
206 return ai;
207}
208
Stanislav Zaikin09abed62021-11-04 09:32:32 +0100209always_inline u8
210clib_bitmap_will_expand (uword *ai, uword i)
211{
212 uword i0 = i / BITS (ai[0]);
213 return _vec_resize_will_expand (ai, 1, i0 * sizeof (ai[0]), 0,
214 sizeof (uword));
215}
216
Dave Barach310f7fe2016-08-05 14:36:27 -0400217/** Gets the ith bit value from a bitmap
218 @param ai - pointer to the bitmap
219 @param i - the bit position to interrogate
220 @returns the indicated bit value
221*/
Ed Warnickecb9cada2015-12-08 15:45:58 -0700222always_inline uword
223clib_bitmap_get (uword * ai, uword i)
224{
225 uword i0 = i / BITS (ai[0]);
226 uword i1 = i % BITS (ai[0]);
227 return i0 < vec_len (ai) && 0 != ((ai[i0] >> i1) & 1);
228}
229
Dave Barach310f7fe2016-08-05 14:36:27 -0400230/** Gets the ith bit value from a bitmap
231 Does not sanity-check the bit position. Be careful.
232 @param ai - pointer to the bitmap
233 @param i - the bit position to interrogate
234 @returns the indicated bit value, or garbage if the bit position is
235 out of range.
Ed Warnickecb9cada2015-12-08 15:45:58 -0700236*/
237always_inline uword
238clib_bitmap_get_no_check (uword * ai, uword i)
239{
240 uword i0 = i / BITS (ai[0]);
241 uword i1 = i % BITS (ai[0]);
242 return 0 != ((ai[i0] >> i1) & 1);
243}
244
Ed Warnickecb9cada2015-12-08 15:45:58 -0700245always_inline uword
246clib_bitmap_get_multiple_no_check (uword * ai, uword i, uword n_bits)
247{
248 uword i0 = i / BITS (ai[0]);
249 uword i1 = i % BITS (ai[0]);
250 ASSERT (i1 + n_bits <= BITS (uword));
251 return 0 != ((ai[i0] >> i1) & pow2_mask (n_bits));
252}
253
Dave Barach310f7fe2016-08-05 14:36:27 -0400254/** Gets the ith through ith + n_bits bit values from a bitmap
255 @param bitmap - pointer to the bitmap
256 @param i - the first bit position to retrieve
257 @param n_bits - the number of bit positions to retrieve
258 @returns the indicated range of bits
259*/
Ed Warnickecb9cada2015-12-08 15:45:58 -0700260always_inline uword
261clib_bitmap_get_multiple (uword * bitmap, uword i, uword n_bits)
262{
263 uword i0, i1, result;
264 uword l = vec_len (bitmap);
265
Dave Barachf9c231e2016-08-05 10:10:18 -0400266 ASSERT (n_bits <= BITS (result));
Ed Warnickecb9cada2015-12-08 15:45:58 -0700267
268 i0 = i / BITS (bitmap[0]);
269 i1 = i % BITS (bitmap[0]);
270
271 /* Check first word. */
272 result = 0;
273 if (i0 < l)
274 {
275 result |= (bitmap[i0] >> i1);
276 if (n_bits < BITS (bitmap[0]))
277 result &= (((uword) 1 << n_bits) - 1);
278 }
279
280 /* Check for overlap into next word. */
281 i0++;
282 if (i1 + n_bits > BITS (bitmap[0]) && i0 < l)
283 {
284 n_bits -= BITS (bitmap[0]) - i1;
Dave Barachc3799992016-08-15 11:12:27 -0400285 result |=
286 (bitmap[i0] & (((uword) 1 << n_bits) - 1)) << (BITS (bitmap[0]) - i1);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700287 }
288
289 return result;
290}
291
Dave Barach310f7fe2016-08-05 14:36:27 -0400292/** sets the ith through ith + n_bits bits in a bitmap
293 @param bitmap - pointer to the bitmap
294 @param i - the first bit position to retrieve
295 @param value - the values to set
296 @param n_bits - the number of bit positions to set
297 @returns a pointer to the updated bitmap, which may expand and move
298*/
Ed Warnickecb9cada2015-12-08 15:45:58 -0700299
Ed Warnickecb9cada2015-12-08 15:45:58 -0700300always_inline uword *
301clib_bitmap_set_multiple (uword * bitmap, uword i, uword value, uword n_bits)
302{
303 uword i0, i1, l, t, m;
304
Dave Barachf9c231e2016-08-05 10:10:18 -0400305 ASSERT (n_bits <= BITS (value));
Ed Warnickecb9cada2015-12-08 15:45:58 -0700306
307 i0 = i / BITS (bitmap[0]);
308 i1 = i % BITS (bitmap[0]);
309
310 /* Allocate bitmap. */
311 clib_bitmap_vec_validate (bitmap, (i + n_bits) / BITS (bitmap[0]));
312 l = vec_len (bitmap);
313
314 m = ~0;
315 if (n_bits < BITS (value))
316 m = (((uword) 1 << n_bits) - 1);
317 value &= m;
318
319 /* Insert into first word. */
320 t = bitmap[i0];
321 t &= ~(m << i1);
322 t |= value << i1;
323 bitmap[i0] = t;
324
325 /* Insert into second word. */
326 i0++;
327 if (i1 + n_bits > BITS (bitmap[0]) && i0 < l)
328 {
329 t = BITS (bitmap[0]) - i1;
330 value >>= t;
331 n_bits -= t;
332 t = bitmap[i0];
333 m = ((uword) 1 << n_bits) - 1;
334 t &= ~m;
335 t |= value;
336 bitmap[i0] = t;
337 }
338
339 return bitmap;
340}
341
Ed Warnickecb9cada2015-12-08 15:45:58 -0700342always_inline uword *
Korian Edeline40e6bdf2018-08-08 11:30:30 +0200343clib_bitmap_set_region (uword * bitmap, uword i, uword value, uword n_bits)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700344{
345 uword a0, a1, b0;
346 uword i_end, mask;
347
348 a0 = i / BITS (bitmap[0]);
349 a1 = i % BITS (bitmap[0]);
350
351 i_end = i + n_bits;
352 b0 = i_end / BITS (bitmap[0]);
353
354 clib_bitmap_vec_validate (bitmap, b0);
355
356 /* First word. */
357 mask = n_bits < BITS (bitmap[0]) ? pow2_mask (n_bits) : ~0;
358 mask <<= a1;
359
360 if (value)
361 bitmap[a0] |= mask;
362 else
363 bitmap[a0] &= ~mask;
364
365 for (a0++; a0 < b0; a0++)
366 bitmap[a0] = value ? ~0 : 0;
367
368 if (a0 == b0)
369 {
370 word n_bits_left = n_bits - (BITS (bitmap[0]) - a1);
371 mask = pow2_mask (n_bits_left);
372 if (value)
373 bitmap[a0] |= mask;
374 else
375 bitmap[a0] &= ~mask;
376 }
377
378 return bitmap;
379}
380
Dave Barach310f7fe2016-08-05 14:36:27 -0400381/** Macro to iterate across set bits in a bitmap
382
383 @param i - the current set bit
384 @param ai - the bitmap
385 @param body - the expression to evaluate for each set bit
386*/
Damjan Marionf0ca1e82020-12-13 23:26:56 +0100387#define clib_bitmap_foreach(i,ai) \
388 if (ai) \
389 for (i = clib_bitmap_first_set (ai); \
390 i != ~0; \
391 i = clib_bitmap_next_set (ai, i + 1))
392
Dave Barach310f7fe2016-08-05 14:36:27 -0400393/** Return the lowest numbered set bit in a bitmap
394 @param ai - pointer to the bitmap
395 @returns lowest numbered set bit, or ~0 if the entire bitmap is zero
396*/
Dave Barachc3799992016-08-15 11:12:27 -0400397always_inline uword
398clib_bitmap_first_set (uword * ai)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700399{
Damjan Marion32ab9542018-06-26 01:29:55 +0200400 uword i = 0;
401#if uword_bits == 64
Damjan Marion13c98a22018-06-26 16:05:43 +0200402#if defined(CLIB_HAVE_VEC256)
Damjan Marion32ab9542018-06-26 01:29:55 +0200403 while (i + 7 < vec_len (ai))
404 {
405 u64x4 v;
406 v = u64x4_load_unaligned (ai + i) | u64x4_load_unaligned (ai + i + 4);
407 if (!u64x4_is_all_zero (v))
408 break;
409 i += 8;
410 }
Damjan Marion13c98a22018-06-26 16:05:43 +0200411#elif defined(CLIB_HAVE_VEC128) && defined(CLIB_HAVE_VEC128_UNALIGNED_LOAD_STORE)
Damjan Marion32ab9542018-06-26 01:29:55 +0200412 while (i + 3 < vec_len (ai))
413 {
414 u64x2 v;
415 v = u64x2_load_unaligned (ai + i) | u64x2_load_unaligned (ai + i + 2);
416 if (!u64x2_is_all_zero (v))
417 break;
418 i += 4;
419 }
420#endif
421#endif
422 for (; i < vec_len (ai); i++)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700423 {
424 uword x = ai[i];
425 if (x != 0)
426 return i * BITS (ai[0]) + log2_first_set (x);
427 }
428 return ~0;
429}
430
Dave Barach310f7fe2016-08-05 14:36:27 -0400431/** Return the higest numbered set bit in a bitmap
432 @param ai - pointer to the bitmap
433 @returns lowest numbered set bit, or ~0 if the entire bitmap is zero
434*/
Dave Barachc3799992016-08-15 11:12:27 -0400435always_inline uword
436clib_bitmap_last_set (uword * ai)
Damjan Marion0247b462016-06-08 01:37:11 +0200437{
438 uword i;
439
Dave Barachc3799992016-08-15 11:12:27 -0400440 for (i = vec_len (ai); i > 0; i--)
Damjan Marion0247b462016-06-08 01:37:11 +0200441 {
Damjan Marionec175102016-06-30 01:02:17 +0200442 uword x = ai[i - 1];
Damjan Marion0247b462016-06-08 01:37:11 +0200443 if (x != 0)
444 {
445 uword first_bit;
Damjan Marion11056002018-05-10 13:40:44 +0200446 first_bit = count_leading_zeros (x);
Damjan Marionec175102016-06-30 01:02:17 +0200447 return (i) * BITS (ai[0]) - first_bit - 1;
Damjan Marion0247b462016-06-08 01:37:11 +0200448 }
449 }
450 return ~0;
451}
452
Dave Barach310f7fe2016-08-05 14:36:27 -0400453/** Return the lowest numbered clear bit in a bitmap
454 @param ai - pointer to the bitmap
455 @returns lowest numbered clear bit
456*/
Ed Warnickecb9cada2015-12-08 15:45:58 -0700457always_inline uword
458clib_bitmap_first_clear (uword * ai)
459{
460 uword i;
461 for (i = 0; i < vec_len (ai); i++)
462 {
463 uword x = ~ai[i];
464 if (x != 0)
465 return i * BITS (ai[0]) + log2_first_set (x);
466 }
467 return i * BITS (ai[0]);
468}
469
Dave Barach310f7fe2016-08-05 14:36:27 -0400470/** Return the number of set bits in a bitmap
471 @param ai - pointer to the bitmap
472 @returns the number of set bits in the bitmap
473*/
Ed Warnickecb9cada2015-12-08 15:45:58 -0700474always_inline uword
475clib_bitmap_count_set_bits (uword * ai)
476{
477 uword i;
478 uword n_set = 0;
479 for (i = 0; i < vec_len (ai); i++)
480 n_set += count_set_bits (ai[i]);
481 return n_set;
482}
483
Dave Barach310f7fe2016-08-05 14:36:27 -0400484/** Logical operator across two bitmaps
485
486 @param ai - pointer to the destination bitmap
487 @param bi - pointer to the source bitmap
488 @returns ai = ai and bi. ai is modified, bi is not modified
489*/
Dave Barachc3799992016-08-15 11:12:27 -0400490always_inline uword *clib_bitmap_and (uword * ai, uword * bi);
Dave Barach310f7fe2016-08-05 14:36:27 -0400491
492/** Logical operator across two bitmaps
493
494 @param ai - pointer to the destination bitmap
495 @param bi - pointer to the source bitmap
496 @returns ai = ai & ~bi. ai is modified, bi is not modified
497*/
Dave Barachc3799992016-08-15 11:12:27 -0400498always_inline uword *clib_bitmap_andnot (uword * ai, uword * bi);
Dave Barach310f7fe2016-08-05 14:36:27 -0400499
500/** Logical operator across two bitmaps
501
502 @param ai - pointer to the destination bitmap
503 @param bi - pointer to the source bitmap
504 @returns ai = ai & ~bi. ai is modified, bi is not modified
505*/
Dave Barachc3799992016-08-15 11:12:27 -0400506always_inline uword *clib_bitmap_or (uword * ai, uword * bi);
Dave Barach310f7fe2016-08-05 14:36:27 -0400507/** Logical operator across two bitmaps
508
509 @param ai - pointer to the destination bitmap
510 @param bi - pointer to the source bitmap
511 @returns ai = ai or bi. ai is modified, bi is not modified
512*/
Dave Barachc3799992016-08-15 11:12:27 -0400513always_inline uword *clib_bitmap_or (uword * ai, uword * bi);
Dave Barach310f7fe2016-08-05 14:36:27 -0400514
515/** Logical operator across two bitmaps
516
517 @param ai - pointer to the destination bitmap
518 @param bi - pointer to the source bitmap
519 @returns ai = ai xor bi. ai is modified, bi is not modified
520*/
Dave Barachc3799992016-08-15 11:12:27 -0400521always_inline uword *clib_bitmap_xor (uword * ai, uword * bi);
Dave Barach310f7fe2016-08-05 14:36:27 -0400522
Ed Warnickecb9cada2015-12-08 15:45:58 -0700523/* ALU function definition macro for functions taking two bitmaps. */
524#define _(name, body, check_zero) \
525always_inline uword * \
526clib_bitmap_##name (uword * ai, uword * bi) \
527{ \
528 uword i, a, b, bi_len, n_trailing_zeros; \
529 \
530 n_trailing_zeros = 0; \
531 bi_len = vec_len (bi); \
532 if (bi_len > 0) \
533 clib_bitmap_vec_validate (ai, bi_len - 1); \
534 for (i = 0; i < vec_len (ai); i++) \
535 { \
536 a = ai[i]; \
537 b = i < bi_len ? bi[i] : 0; \
538 do { body; } while (0); \
539 ai[i] = a; \
540 if (check_zero) \
541 n_trailing_zeros = a ? 0 : (n_trailing_zeros + 1); \
542 } \
543 if (check_zero) \
544 _vec_len (ai) -= n_trailing_zeros; \
545 return ai; \
546}
547
548/* ALU functions: */
Florin Corasfcd23682018-06-29 03:22:44 -0700549/* *INDENT-OFF* */
Dave Barachc3799992016-08-15 11:12:27 -0400550_(and, a = a & b, 1)
Florin Corasfcd23682018-06-29 03:22:44 -0700551_(andnot, a = a & ~b, 1)
552_(or, a = a | b, 0)
553_(xor, a = a ^ b, 1)
554/* *INDENT-ON* */
Ed Warnickecb9cada2015-12-08 15:45:58 -0700555#undef _
Dave Barach310f7fe2016-08-05 14:36:27 -0400556/** Logical operator across two bitmaps which duplicates the first bitmap
557
558 @param ai - pointer to the destination bitmap
559 @param bi - pointer to the source bitmap
560 @returns aiDup = ai and bi. Neither ai nor bi are modified
561*/
Florin Corasfcd23682018-06-29 03:22:44 -0700562always_inline uword *clib_bitmap_dup_and (uword * ai, uword * bi);
Dave Barach310f7fe2016-08-05 14:36:27 -0400563
564/** Logical operator across two bitmaps which duplicates the first bitmap
565
566 @param ai - pointer to the destination bitmap
567 @param bi - pointer to the source bitmap
568 @returns aiDup = ai & ~bi. Neither ai nor bi are modified
569*/
Florin Corasfcd23682018-06-29 03:22:44 -0700570always_inline uword *clib_bitmap_dup_andnot (uword * ai, uword * bi);
Dave Barach310f7fe2016-08-05 14:36:27 -0400571
572/** Logical operator across two bitmaps which duplicates the first bitmap
573
574 @param ai - pointer to the destination bitmap
575 @param bi - pointer to the source bitmap
576 @returns aiDup = ai or bi. Neither ai nor bi are modified
577*/
Florin Corasfcd23682018-06-29 03:22:44 -0700578always_inline uword *clib_bitmap_dup_or (uword * ai, uword * bi);
Dave Barach310f7fe2016-08-05 14:36:27 -0400579
580/** Logical operator across two bitmaps which duplicates the first bitmap
581
582 @param ai - pointer to the destination bitmap
583 @param bi - pointer to the source bitmap
584 @returns aiDup = ai xor bi. Neither ai nor bi are modified
585*/
Florin Corasfcd23682018-06-29 03:22:44 -0700586always_inline uword *clib_bitmap_dup_xor (uword * ai, uword * bi);
Dave Barach310f7fe2016-08-05 14:36:27 -0400587
Ed Warnickecb9cada2015-12-08 15:45:58 -0700588#define _(name) \
589 always_inline uword * \
590 clib_bitmap_dup_##name (uword * ai, uword * bi) \
591{ return clib_bitmap_##name (clib_bitmap_dup (ai), bi); }
592
Florin Corasfcd23682018-06-29 03:22:44 -0700593/* *INDENT-OFF* */
Dave Barachc3799992016-08-15 11:12:27 -0400594_(and);
595_(andnot);
596_(or);
597_(xor);
Florin Corasfcd23682018-06-29 03:22:44 -0700598/* *INDENT-ON* */
Ed Warnickecb9cada2015-12-08 15:45:58 -0700599#undef _
600
Florin Corasfcd23682018-06-29 03:22:44 -0700601/* ALU function definition macro for functions taking one bitmap and an
602 * immediate. */
Ed Warnickecb9cada2015-12-08 15:45:58 -0700603#define _(name, body, check_zero) \
604always_inline uword * \
605clib_bitmap_##name (uword * ai, uword i) \
606{ \
607 uword i0 = i / BITS (ai[0]); \
608 uword i1 = i % BITS (ai[0]); \
609 uword a, b; \
610 clib_bitmap_vec_validate (ai, i0); \
611 a = ai[i0]; \
612 b = (uword) 1 << i1; \
613 do { body; } while (0); \
614 ai[i0] = a; \
615 if (check_zero && a == 0) \
616 ai = _clib_bitmap_remove_trailing_zeros (ai); \
617 return ai; \
618}
619
620/* ALU functions immediate: */
Florin Corasfcd23682018-06-29 03:22:44 -0700621/* *INDENT-OFF* */
Dave Barachc3799992016-08-15 11:12:27 -0400622_(andi, a = a & b, 1)
Florin Corasfcd23682018-06-29 03:22:44 -0700623_(andnoti, a = a & ~b, 1)
624_(ori, a = a | b, 0)
625_(xori, a = a ^ b, 1)
626/* *INDENT-ON* */
Ed Warnickecb9cada2015-12-08 15:45:58 -0700627#undef _
Florin Corasfcd23682018-06-29 03:22:44 -0700628
629/* ALU function definition macro for functions taking one bitmap and an
630 * immediate. No tail trimming */
631#define _(name, body) \
632always_inline uword * \
633clib_bitmap_##name##_notrim (uword * ai, uword i) \
634{ \
635 uword i0 = i / BITS (ai[0]); \
636 uword i1 = i % BITS (ai[0]); \
637 uword a, b; \
638 clib_bitmap_vec_validate (ai, i0); \
639 a = ai[i0]; \
640 b = (uword) 1 << i1; \
641 do { body; } while (0); \
642 ai[i0] = a; \
643 return ai; \
644}
645
646/* ALU functions immediate: */
647/* *INDENT-OFF* */
648_(andi, a = a & b)
649_(andnoti, a = a & ~b)
650_(ori, a = a | b)
651_(xori, a = a ^ b)
652#undef _
653/* *INDENT-ON* */
654
Dave Barach310f7fe2016-08-05 14:36:27 -0400655/** Return a random bitmap of the requested length
656 @param ai - pointer to the destination bitmap
657 @param n_bits - number of bits to allocate
Chris Luked4024f52016-09-06 09:32:36 -0400658 @param [in,out] seed - pointer to the random number seed
Dave Barach310f7fe2016-08-05 14:36:27 -0400659 @returns a reasonably random bitmap based. See random.h.
660*/
Florin Corasfcd23682018-06-29 03:22:44 -0700661always_inline uword *
662clib_bitmap_random (uword * ai, uword n_bits, u32 * seed)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700663{
664 vec_reset_length (ai);
665
666 if (n_bits > 0)
667 {
668 uword i = n_bits - 1;
669 uword i0, i1;
670 uword log2_rand_max;
671
672 log2_rand_max = min_log2 (random_u32_max ());
673
674 i0 = i / BITS (ai[0]);
675 i1 = i % BITS (ai[0]);
676
677 clib_bitmap_vec_validate (ai, i0);
678 for (i = 0; i <= i0; i++)
679 {
680 uword n;
681 for (n = 0; n < BITS (ai[i]); n += log2_rand_max)
682 ai[i] |= random_u32 (seed) << n;
683 }
684 if (i1 + 1 < BITS (ai[0]))
685 ai[i0] &= (((uword) 1 << (i1 + 1)) - 1);
686 }
687 return ai;
688}
689
Dave Barach310f7fe2016-08-05 14:36:27 -0400690/** Return the next set bit in a bitmap starting at bit i
691 @param ai - pointer to the bitmap
692 @param i - first bit position to test
Dave Barachc3799992016-08-15 11:12:27 -0400693 @returns first set bit position at or after i,
Dave Barach310f7fe2016-08-05 14:36:27 -0400694 ~0 if no further set bits are found
695*/
Ed Warnickecb9cada2015-12-08 15:45:58 -0700696always_inline uword
697clib_bitmap_next_set (uword * ai, uword i)
698{
699 uword i0 = i / BITS (ai[0]);
700 uword i1 = i % BITS (ai[0]);
701 uword t;
Dave Barachc3799992016-08-15 11:12:27 -0400702
Ed Warnickecb9cada2015-12-08 15:45:58 -0700703 if (i0 < vec_len (ai))
704 {
705 t = (ai[i0] >> i1) << i1;
706 if (t)
707 return log2_first_set (t) + i0 * BITS (ai[0]);
708
709 for (i0++; i0 < vec_len (ai); i0++)
710 {
711 t = ai[i0];
712 if (t)
713 return log2_first_set (t) + i0 * BITS (ai[0]);
714 }
715 }
716
717 return ~0;
718}
719
Dave Barach310f7fe2016-08-05 14:36:27 -0400720/** Return the next clear bit in a bitmap starting at bit i
721 @param ai - pointer to the bitmap
722 @param i - first bit position to test
723 @returns first clear bit position at or after i
724*/
Ed Warnickecb9cada2015-12-08 15:45:58 -0700725always_inline uword
726clib_bitmap_next_clear (uword * ai, uword i)
727{
728 uword i0 = i / BITS (ai[0]);
729 uword i1 = i % BITS (ai[0]);
730 uword t;
Dave Barachc3799992016-08-15 11:12:27 -0400731
Ed Warnickecb9cada2015-12-08 15:45:58 -0700732 if (i0 < vec_len (ai))
733 {
734 t = (~ai[i0] >> i1) << i1;
735 if (t)
736 return log2_first_set (t) + i0 * BITS (ai[0]);
737
738 for (i0++; i0 < vec_len (ai); i0++)
739 {
Dave Barachc3799992016-08-15 11:12:27 -0400740 t = ~ai[i0];
Ed Warnickecb9cada2015-12-08 15:45:58 -0700741 if (t)
742 return log2_first_set (t) + i0 * BITS (ai[0]);
743 }
John Loef8db362018-07-04 16:27:59 -0400744
jiangxiaominga3d8c2c2021-12-30 08:52:38 +0000745 return i0 * BITS (ai[0]);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700746 }
747 return i;
748}
749
Damjan Marion7f57f502021-04-15 16:13:20 +0200750uword unformat_bitmap_mask (unformat_input_t *input, va_list *va);
751uword unformat_bitmap_list (unformat_input_t *input, va_list *va);
752u8 *format_bitmap_hex (u8 *s, va_list *args);
753u8 *format_bitmap_list (u8 *s, va_list *args);
Yi Hee4a9eb72018-07-17 14:18:41 +0800754
Ed Warnickecb9cada2015-12-08 15:45:58 -0700755#endif /* included_clib_bitmap_h */
Dave Barachc3799992016-08-15 11:12:27 -0400756
757/*
758 * fd.io coding-style-patch-verification: ON
759 *
760 * Local Variables:
761 * eval: (c-set-style "gnu")
762 * End:
763 */