BRL-CAD
bitv.h
Go to the documentation of this file.
1/* B I T V . H
2 * BRL-CAD
3 *
4 * Copyright (c) 2004-2023 United States Government as represented by
5 * the U.S. Army Research Laboratory.
6 *
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public License
9 * version 2.1 as published by the Free Software Foundation.
10 *
11 * This library is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this file; see the file named COPYING for more
18 * information.
19 */
20
21#ifndef BU_BITV_H
22#define BU_BITV_H
23
24#include "common.h"
25
26#include <limits.h> /* for CHAR_BIT */
27
28#include "bu/defines.h"
29#include "bu/magic.h"
30#include "bu/list.h"
31#include "bu/vls.h"
32
33__BEGIN_DECLS
34
35/*----------------------------------------------------------------------*/
36/** @addtogroup bu_bitv
37 *
38 * @brief
39 * Routines for managing efficient high-performance bit vectors of
40 * arbitrary length.
41 *
42 * The basic type "bitv_t" is defined in include/bu.h; it is the
43 * widest integer datatype for which efficient hardware support
44 * exists. BU_BITV_SHIFT and BU_BITV_MASK are also defined in bu.h
45 *
46 * These bit vectors are "little endian", bit 0 is in the right hand
47 * side of the [0] word.
48 *
49 */
50/** @{*/
51/** @file bu/bitv.h */
52
53/**
54 * bitv_t should be a fast integer type for implementing bit vectors.
55 *
56 * On many machines, this is a 32-bit "long", but on some machines a
57 * compiler/vendor-specific type such as "long long" or even 'char'
58 * can give access to faster integers.
59 *
60 * THE SIZE OF bitv_t MUST MATCH BU_BITV_SHIFT.
61 */
62typedef unsigned char bitv_t;
63
64/**
65 * Bit vector shift size
66 *
67 * Should equal to: log2(sizeof(bitv_t)*8.0). Using bu_bitv_shift()
68 * will return a run-time computed shift size if the size of a bitv_t
69 * changes. Performance impact is rather minimal for most models but
70 * disabled for a handful of primitives that heavily rely on bit
71 * vectors.
72 *
73 * (8-bit type: 3, 16-bit type: 4, 32-bit type: 5, 64-bit type: 6)
74 */
75#ifdef CHAR_BIT
76# if CHAR_BIT == 8
77# define BU_BITV_SHIFT 3
78# elif CHAR_BIT == 16
79# define BU_BITV_SHIFT 4
80# elif CHAR_BIT == 32
81# define BU_BITV_SHIFT 5
82# elif CHAR_BIT == 64
83# define BU_BITV_SHIFT 6
84# endif
85#else
86# define BU_BITV_SHIFT bu_bitv_shift()
87#endif
88
89/** Bit vector mask */
90#define BU_BITV_MASK ((1<<BU_BITV_SHIFT)-1)
91
92/**
93 * Bit vector data structure.
94 *
95 * bu_bitv uses a little-endian encoding, placing bit 0 on the right
96 * side of the 0th word.
97 *
98 * This is done only because left-shifting a 1 can be done in an
99 * efficient word-length-independent manner; going the other way would
100 * require a compile-time constant with only the sign bit set, and an
101 * unsigned right shift, which some machines don't have in hardware,
102 * or an extra subtraction.
103 *
104 * Application code should *never* peek at the bit-buffer; use the
105 * macros. The external hex form is most significant byte first (bit
106 * 0 is at the right). Note that MUVES does it differently.
107 */
108struct bu_bitv {
109 struct bu_list l; /**< linked list for caller's use */
110 size_t nbits; /**< actual size of bits[], in bits */
111 bitv_t bits[2]; /**< variable size array */
112};
113typedef struct bu_bitv bu_bitv_t;
114#define BU_BITV_NULL ((struct bu_bitv *)0)
115
116/**
117 * asserts the integrity of a non-head node bu_bitv struct.
118 */
119#define BU_CK_BITV(_bp) BU_CKMAG(_bp, BU_BITV_MAGIC, "bu_bitv")
120
121/**
122 * initializes a bu_bitv struct without allocating any memory. this
123 * macro is not suitable for initializing a head list node.
124 */
125#define BU_BITV_INIT(_bp) { \
126 BU_LIST_INIT_MAGIC(&(_bp)->l, BU_BITV_MAGIC); \
127 (_bp)->nbits = 0; \
128 (_bp)->bits[0] = 0; \
129 (_bp)->bits[1] = 0; \
130 }
131
132/**
133 * macro suitable for declaration statement initialization of a bu_bitv
134 * struct. does not allocate memory. not suitable for a head node.
135 */
136#define BU_BITV_INIT_ZERO { {BU_BITV_MAGIC, BU_LIST_NULL, BU_LIST_NULL}, 0, {0, 0} }
137
138/**
139 * returns truthfully whether a bu_bitv has been initialized
140 */
141#define BU_BITV_IS_INITIALIZED(_bp) (((struct bu_bitv *)(_bp) != BU_BITV_NULL) && LIKELY((_bp)->l.magic == BU_BITV_MAGIC))
142
143/**
144 * returns floor(log2(sizeof(bitv_t)*8.0)), i.e. the number of bits
145 * required with base-2 encoding to index any bit in an array of
146 * length sizeof(bitv_t)*8.0 bits long. users should not call this
147 * directly, instead calling the BU_BITV_SHIFT macro instead.
148 */
149BU_EXPORT extern size_t bu_bitv_shift(void);
150
151/**
152 * Convert a number of words into the corresponding (bitv_t type) size
153 * as a bit-vector size.
154 */
155#define BU_WORDS2BITS(_nw) ((size_t)(_nw>0?_nw:0)*sizeof(bitv_t)*8)
156
157/**
158 * Convert a bit-vector (stored in a bitv_t array) size into the
159 * corresponding word size.
160 */
161#define BU_BITS2WORDS(_nb) (((size_t)(_nb>0?_nb:0)+BU_BITV_MASK)>>BU_BITV_SHIFT)
162
163/**
164 * Convert a bit-vector (stored in a bitv_t array) size into the
165 * corresponding total memory size (in bytes) of the bitv_t array.
166 */
167#define BU_BITS2BYTES(_nb) (BU_BITS2WORDS(_nb)*sizeof(bitv_t))
168
169
170#if 1
171#define BU_BITTEST(_bv, bit) \
172 (((_bv)->bits[(bit)>>BU_BITV_SHIFT] & (((bitv_t)1)<<((bit)&BU_BITV_MASK)))!=0)
173#else
174static __inline__ int BU_BITTEST(volatile void * addr, int nr)
175{
176 int oldbit;
177
178 __asm__ __volatile__(
179 "btl %2, %1\n\tsbbl %0, %0"
180 :"=r" (oldbit)
181 :"m" (addr), "Ir" (nr));
182 return oldbit;
183}
184#endif
185
186#define BU_BITSET(_bv, bit) \
187 ((_bv)->bits[(bit)>>BU_BITV_SHIFT] |= (((bitv_t)1)<<((bit)&BU_BITV_MASK)))
188#define BU_BITCLR(_bv, bit) \
189 ((_bv)->bits[(bit)>>BU_BITV_SHIFT] &= ~(((bitv_t)1)<<((bit)&BU_BITV_MASK)))
190
191/**
192 * zeros all of the internal storage bytes in a bit vector array
193 */
194#define BU_BITV_ZEROALL(_bv) \
195 { \
196 if (LIKELY((_bv) && (_bv)->nbits != 0)) { \
197 unsigned char *bvp = (unsigned char *)(_bv)->bits; \
198 size_t nbytes = BU_BITS2BYTES((_bv)->nbits); \
199 do { \
200 *bvp++ = (unsigned char)0; \
201 } while (--nbytes != 0); \
202 } \
203 }
204
205
206/* This is not done by default for performance reasons */
207#ifdef NO_BOMBING_MACROS
208# define BU_BITV_BITNUM_CHECK(_bv, _bit) (void)(_bv)
209#else
210# define BU_BITV_BITNUM_CHECK(_bv, _bit) /* Validate bit number */ \
211 if (UNLIKELY(((unsigned)(_bit)) >= (_bv)->nbits)) {\
212 bu_log("BU_BITV_BITNUM_CHECK bit number (%u) out of range (0..%u)\n", \
213 ((unsigned)(_bit)), (_bv)->nbits); \
214 bu_bomb("process self-terminating\n");\
215 }
216#endif
217
218#ifdef NO_BOMBING_MACROS
219# define BU_BITV_NBITS_CHECK(_bv, _nbits) (void)(_bv)
220#else
221# define BU_BITV_NBITS_CHECK(_bv, _nbits) /* Validate number of bits */ \
222 if (UNLIKELY(((unsigned)(_nbits)) > (_bv)->nbits)) {\
223 bu_log("BU_BITV_NBITS_CHECK number of bits (%u) out of range (> %u)", \
224 ((unsigned)(_nbits)), (_bv)->nbits); \
225 bu_bomb("process self-terminating"); \
226 }
227#endif
228
229
230/**
231 * Macros to efficiently find all the ONE bits in a bit vector.
232 * Counts words down, counts bits in words going up, for speed &
233 * portability. It does not matter if the shift causes the sign bit
234 * to smear to the right.
235 *
236 * @par Example:
237 * @code
238 *
239 * BU_BITV_LOOP_START(bv) {
240 * fiddle(BU_BITV_LOOP_INDEX);
241 * } BU_BITV_LOOP_END;
242 *
243 * @endcode
244 *
245 */
246#define BU_BITV_LOOP_START(_bv) \
247 { \
248 int _wd; /* Current word number */ \
249 BU_CK_BITV(_bv); \
250 for (_wd=BU_BITS2WORDS((_bv)->nbits)-1; _wd>=0; _wd--) { \
251 int _b; /* Current bit-in-word number */ \
252 bitv_t _val; /* Current word value */ \
253 if ((_val = (_bv)->bits[_wd])==0) continue; \
254 for (_b=0; _b < BU_BITV_MASK+1; _b++, _val >>= 1) { \
255 if (!(_val & 1)) continue;
256
257/**
258 * This macro is valid only between a BU_BITV_LOOP_START/LOOP_END
259 * pair, and gives the bit number of the current iteration.
260 */
261#define BU_BITV_LOOP_INDEX ((_wd << BU_BITV_SHIFT) | _b)
262
263/**
264 * Paired with BU_BITV_LOOP_START()
265 */
266#define BU_BITV_LOOP_END } /* end for (_b) */ \
267 } /* end for (_wd) */ \
268 } /* end block */
269
270/**
271 * Allocate storage for a new bit vector of at least 'nbits' in
272 * length. The bit vector itself is guaranteed to be initialized to
273 * all zero.
274 */
275BU_EXPORT extern struct bu_bitv *bu_bitv_new(size_t nbits);
276
277/**
278 * Release all internal storage for this bit vector.
279 *
280 * It is the caller's responsibility to not use the pointer 'bv' any
281 * longer. It is the caller's responsibility to dequeue from any
282 * linked list first.
283 */
284BU_EXPORT extern void bu_bitv_free(struct bu_bitv *bv);
285
286/**
287 * Set all the bits in the bit vector to zero.
288 *
289 * Also available as a BU_BITV_ZEROALL macro if you don't desire the
290 * pointer checking.
291 */
292BU_EXPORT extern void bu_bitv_clear(struct bu_bitv *bv);
293
294/**
295 * TBD
296 */
297BU_EXPORT extern void bu_bitv_or(struct bu_bitv *ov, const struct bu_bitv *iv);
298
299/**
300 * TBD
301 */
302BU_EXPORT extern void bu_bitv_and(struct bu_bitv *ov, const struct bu_bitv *iv);
303
304/**
305 * Print the bits set in a bit vector.
306 */
307BU_EXPORT extern void bu_bitv_vls(struct bu_vls *v, const struct bu_bitv *bv);
308
309/**
310 * Print the bits set in a bit vector. Use bu_vls stuff, to make only
311 * a single call to bu_log().
312 */
313BU_EXPORT extern void bu_pr_bitv(const char *str, const struct bu_bitv *bv);
314
315/**
316 * Convert a bit vector to an ascii string of hex digits. The string
317 * is from MSB to LSB (bytes and bits).
318 */
319BU_EXPORT extern void bu_bitv_to_hex(struct bu_vls *v, const struct bu_bitv *bv);
320
321/**
322 * Convert a string of HEX digits (as produced by bu_bitv_to_hex) into
323 * a bit vector.
324 */
325BU_EXPORT extern struct bu_bitv *bu_hex_to_bitv(const char *str);
326
327/**
328 * Convert a bit vector to an ascii string of binary digits in the GCC
329 * format ("0bn..."). The string is from MSB to LSB (bytes and bits).
330 */
331BU_EXPORT extern void bu_bitv_to_binary(struct bu_vls *v, const struct bu_bitv *bv);
332
333/**
334 * Convert a string of BINARY digits (as produced by
335 * bu_bitv_to_binary) into a bit vector.
336 */
337BU_EXPORT extern struct bu_bitv *bu_binary_to_bitv(const char *str);
338
339/**
340 * Convert a string of BINARY digits (as produced by
341 * bu_bitv_to_binary) into a bit vector. The "nbytes" argument may be
342 * zero if the user has no minimum length preference.
343 */
344BU_EXPORT extern struct bu_bitv *bu_binary_to_bitv2(const char *str, const int nbytes);
345
346/**
347 * Compare two bit vectors for equality. They are considered equal iff
348 * their lengths and each bit are equal. Returns 1 for true, zero for
349 * false.
350 */
351BU_EXPORT extern int bu_bitv_compare_equal(const struct bu_bitv *, const struct bu_bitv *);
352
353/**
354 * Compare two bit vectors for equality. They are considered equal iff
355 * their non-zero bits are equal (leading zero bits are ignored so
356 * lengths are not considered explicitly). Returns 1 for true, 0 for
357 * false.
358 */
359BU_EXPORT extern int bu_bitv_compare_equal2(const struct bu_bitv *, const struct bu_bitv *);
360
361/**
362 * Make a copy of a bit vector
363 */
364BU_EXPORT extern struct bu_bitv *bu_bitv_dup(const struct bu_bitv *bv);
365
366
367/**
368 * Convert a string of hex characters to an equivalent string of
369 * binary characters.
370 *
371 * The input hex string may have an optional prefix of '0x' or '0X' in
372 * which case the resulting binary string will be prefixed with '0b'.
373 *
374 * The input string is expected to represent an integral number of
375 * bytes but will have leading zeroes prepended as necessary to fulfill
376 * that requirement.
377 *
378 * Returns BRLCAD_OK for success, BRLCAD_ERROR for errors.
379 */
380BU_EXPORT extern int bu_hexstr_to_binstr(const char *hexstr, struct bu_vls *b);
381
382
383/**
384 * Convert a string of binary characters to an equivalent string of
385 * hex characters.
386 *
387 * The input binary string may have an optional prefix of '0b' or '0B'
388 * in which case the resulting hex string will be prefixed with '0x'.
389 *
390 * The input string is expected to represent an integral number of
391 * bytes but will have leading zeroes prepended as necessary to fulfill
392 * that requirement.
393 *
394 * Returns BRLCAD_OK for success, BRLCAD_ERROR for errors.
395 *
396 */
397BU_EXPORT extern int bu_binstr_to_hexstr(const char *binstr, struct bu_vls *h);
398
399
400/** @brief Bit field printing implementation. */
401
402
403/**
404 * Print a bit field according to a format specification via bu_log().
405 *
406 * Line printed is of the form "String Label: x1234 <FOO,BAR,RAB,OOF>"
407 * and is commonly used by debugging code to print which debug bits
408 * are enabled.
409 *
410 * @param label string label
411 * @param bits integer with the bits to print
412 * @param format format specification
413 *
414 * The 'format' begins with a desired printing base (8 or 16), i.e.,
415 * \\010 means print octal and \\020 for hex. Remaining string is the
416 * little endian bit position (i.e., 1 to 32 encoded in octal format)
417 * followed by a label for that bit (e.g., "\010\2Bit_one\1BIT_zero")
418 *
419 * Note octal counting is used for the bit position label:
420 * \01 -> ... \07 -> \10 -> \11 -> ... \17 -> \20 ... etc
421 */
422BU_EXPORT extern void bu_printb(const char *label,
423 unsigned long bits,
424 const char *format);
425
426/**
427 * Same as bu_printb() but with output going to a vls instead of stderr
428 */
429BU_EXPORT extern void bu_vls_printb(struct bu_vls *vls,
430 const char *label, unsigned long bits,
431 const char *format);
432
433/** @} */
434
435__END_DECLS
436
437#endif /* BU_BITV_H */
438
439/*
440 * Local Variables:
441 * mode: C
442 * tab-width: 8
443 * indent-tabs-mode: t
444 * c-file-style: "stroustrup"
445 * End:
446 * ex: shiftwidth=4 tabstop=8
447 */
Header file for the BRL-CAD common definitions.
struct bu_bitv * bu_hex_to_bitv(const char *str)
struct bu_bitv * bu_bitv_new(size_t nbits)
void bu_bitv_to_binary(struct bu_vls *v, const struct bu_bitv *bv)
struct bu_bitv * bu_binary_to_bitv2(const char *str, const int nbytes)
struct bu_bitv * bu_binary_to_bitv(const char *str)
void bu_bitv_free(struct bu_bitv *bv)
int bu_bitv_compare_equal2(const struct bu_bitv *, const struct bu_bitv *)
void bu_bitv_to_hex(struct bu_vls *v, const struct bu_bitv *bv)
void bu_bitv_and(struct bu_bitv *ov, const struct bu_bitv *iv)
void bu_bitv_vls(struct bu_vls *v, const struct bu_bitv *bv)
#define BU_BITTEST(_bv, bit)
Definition: bitv.h:171
void bu_bitv_clear(struct bu_bitv *bv)
int bu_binstr_to_hexstr(const char *binstr, struct bu_vls *h)
void bu_bitv_or(struct bu_bitv *ov, const struct bu_bitv *iv)
size_t bu_bitv_shift(void)
struct bu_bitv * bu_bitv_dup(const struct bu_bitv *bv)
int bu_bitv_compare_equal(const struct bu_bitv *, const struct bu_bitv *)
void bu_printb(const char *label, unsigned long bits, const char *format)
Bit field printing implementation.
int bu_hexstr_to_binstr(const char *hexstr, struct bu_vls *b)
void bu_pr_bitv(const char *str, const struct bu_bitv *bv)
void bu_vls_printb(struct bu_vls *vls, const char *label, unsigned long bits, const char *format)
unsigned char bitv_t
Definition: bitv.h:62
Global registry of recognized magic numbers.
Definition: bitv.h:108
size_t nbits
Definition: bitv.h:110
bitv_t bits[2]
Definition: bitv.h:111
struct bu_list l
Definition: bitv.h:109
Definition: list.h:131
Definition: vls.h:53