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-2024 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  */
62 typedef 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  */
108 struct 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 };
113 typedef 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  */
149 BU_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
174 static __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  */
275 BU_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  */
284 BU_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  */
292 BU_EXPORT extern void bu_bitv_clear(struct bu_bitv *bv);
293 
294 /**
295  * TBD
296  */
297 BU_EXPORT extern void bu_bitv_or(struct bu_bitv *ov, const struct bu_bitv *iv);
298 
299 /**
300  * TBD
301  */
302 BU_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  */
307 BU_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  */
313 BU_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  */
319 BU_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  */
325 BU_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  */
331 BU_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  */
337 BU_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  */
344 BU_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  */
351 BU_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  */
359 BU_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  */
364 BU_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  */
380 BU_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  */
397 BU_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  */
422 BU_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  */
429 BU_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_binary_to_bitv(const char *str)
void bu_bitv_to_binary(struct bu_vls *v, const struct bu_bitv *bv)
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
struct bu_bitv * bu_bitv_dup(const struct bu_bitv *bv)
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)
struct bu_bitv * bu_hex_to_bitv(const char *str)
size_t bu_bitv_shift(void)
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)
struct bu_bitv * bu_binary_to_bitv2(const char *str, const int nbytes)
void bu_pr_bitv(const char *str, const struct bu_bitv *bv)
struct bu_bitv * bu_bitv_new(size_t nbits)
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:132
Definition: vls.h:53