bitv.c

Go to the documentation of this file.
00001 /*                          B I T V . C
00002  * BRL-CAD
00003  *
00004  * Copyright (c) 2004-2006 United States Government as represented by
00005  * the U.S. Army Research Laboratory.
00006  *
00007  * This library is free software; you can redistribute it and/or
00008  * modify it under the terms of the GNU Lesser General Public License
00009  * as published by the Free Software Foundation; either version 2 of
00010  * the License, or (at your option) any later version.
00011  *
00012  * This library is distributed in the hope that it will be useful, but
00013  * WITHOUT ANY WARRANTY; without even the implied warranty of
00014  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00015  * Library General Public License for more details.
00016  *
00017  * You should have received a copy of the GNU Lesser General Public
00018  * License along with this file; see the file named COPYING for more
00019  * information.
00020  */
00021 
00022 /** \addtogroup bitv */
00023 /*@{*/
00024 /**  @file bitv.c
00025  * @brief
00026  *  Routines for managing bit vectors of arbitrary length.
00027  *
00028  *  The basic type "bitv_t" is defined in h/machine.h; it is the
00029  *  widest integer datatype for which efficient hardware support exists.
00030  *  BITV_SHIFT and BITV_MASK are also defined in machine.h
00031  *
00032  *  These bit vectors are "little endian", bit 0 is in the right hand
00033  *  side of the [0] word.
00034  *
00035  *  @author Michael John Muuss
00036  *
00037  *  @par Source -
00038  *      The U. S. Army Research Laboratory
00039  *      Aberdeen Proving Ground, Maryland  21005-5068  USA
00040  *
00041  */
00042 
00043 #ifndef lint
00044 static const char libbu_bitv_RCSid[] = "@(#)$Header: /cvsroot/brlcad/brlcad/src/libbu/bitv.c,v 14.12 2006/08/31 05:50:24 lbutler Exp $ (ARL)";
00045 #endif
00046 
00047 #include "common.h"
00048 
00049 #include <stdio.h>
00050 #include <stdlib.h>
00051 #ifdef HAVE_STRING_H
00052 #  include <string.h>           /* for bzero() */
00053 #else
00054 #  include <strings.h>
00055 #endif
00056 #include <ctype.h>
00057 #include "machine.h"
00058 #include "bu.h"
00059 
00060 /**
00061  *                      B U _ B I T V _ N E W
00062  * @brief
00063  *  Allocate storage for a new bit vector of at least 'nbits' in length.
00064  *  For efficiency, the bit vector itself is not initialized.
00065  */
00066 struct bu_bitv *
00067 bu_bitv_new(unsigned int nbits)
00068 {
00069     struct bu_bitv      *bv;
00070     int         bv_bytes;
00071     int         total_bytes;
00072 
00073     bv_bytes = BU_BITS2BYTES(nbits);
00074     total_bytes = sizeof(struct bu_bitv) - 2*sizeof(bitv_t) + bv_bytes;
00075 
00076     bv = (struct bu_bitv *)bu_malloc( (size_t)total_bytes, "struct bu_bitv" );
00077     BU_LIST_INIT( &bv->l );
00078     bv->l.magic = BU_BITV_MAGIC;
00079     bv->nbits = bv_bytes * 8;
00080     return bv;
00081 }
00082 
00083 /**
00084  *                      B U _ B I T V _ F R E E
00085  * @brief
00086  *  Release all internal storage for this bit vector.
00087  *
00088  *  It is the caller's responsibility to not use the pointer 'bv' any longer.
00089  *  It is the caller's responsibility to dequeue from any linked list first.
00090  */
00091 void
00092 bu_bitv_free(struct bu_bitv *bv)
00093 {
00094     BU_CK_BITV(bv);
00095 
00096     bv->l.forw = bv->l.back = BU_LIST_NULL;     /* sanity */
00097     bu_free( (char *)bv, "struct bu_bitv" );
00098 }
00099 
00100 /**
00101  *                      B U _ B I T V _ C L E A R
00102  * @brief
00103  *  Set all the bits in the bit vector to zero.
00104  *
00105  *  Also available as a macro if you don't desire the pointer checking.
00106  */
00107 void
00108 bu_bitv_clear(struct bu_bitv *bv)
00109 {
00110     BU_CK_BITV(bv);
00111 
00112     BU_BITV_ZEROALL(bv);
00113 }
00114 
00115 /**
00116  *                      B U _ B I T V _ O R
00117  */
00118 void
00119 bu_bitv_or(struct bu_bitv *ov, const struct bu_bitv *iv)
00120 {
00121     register bitv_t             *out;
00122     register const bitv_t       *in;
00123     register int                words;
00124 
00125     if( ov->nbits != iv->nbits )  bu_bomb("bu_bitv_or: length mis-match");
00126     out = ov->bits;
00127     in = iv->bits;
00128     words = BU_BITS2WORDS(iv->nbits);
00129 #ifdef VECTORIZE
00130 #       include "noalias.h"
00131     for( --words; words >= 0; words-- )
00132         out[words] |= in[words];
00133 #else
00134     while( words-- > 0 )
00135         *out++ |= *in++;
00136 #endif
00137 }
00138 
00139 /*
00140  *                      B U _ B I T V _ A N D
00141  */
00142 void
00143 bu_bitv_and(struct bu_bitv *ov, const struct bu_bitv *iv)
00144 {
00145     register bitv_t             *out;
00146     register const bitv_t       *in;
00147     register int                words;
00148 
00149     if( ov->nbits != iv->nbits )  bu_bomb("bu_bitv_and: length mis-match");
00150     out = ov->bits;
00151     in = iv->bits;
00152     words = BU_BITS2WORDS(iv->nbits);
00153 #ifdef VECTORIZE
00154 #       include "noalias.h"
00155     for( --words; words >= 0; words-- )
00156         out[words] &= in[words];
00157 #else
00158     while( words-- > 0 )
00159         *out++ &= *in++;
00160 #endif
00161 }
00162 
00163 /**
00164  *                      B U _ B I T V _ V L S
00165  * @brief
00166  *  Print the bits set in a bit vector.
00167  */
00168 void
00169 bu_bitv_vls(struct bu_vls *v, register const struct bu_bitv *bv)
00170 {
00171     int         seen = 0;
00172     register int        i;
00173     int         len;
00174 
00175     BU_CK_VLS( v );
00176     BU_CK_BITV( bv );
00177 
00178     len = bv->nbits;
00179 
00180     bu_vls_strcat( v, "(" );
00181 
00182     /* Visit all the bits in ascending order */
00183     for( i=0; i<len; i++ )  {
00184         if( BU_BITTEST(bv, i) == 0 )  continue;
00185         if( seen )  bu_vls_strcat( v, ", " );
00186         bu_vls_printf( v, "%d", i );
00187         seen = 1;
00188     }
00189     bu_vls_strcat( v, ") " );
00190 }
00191 
00192 /**
00193  *                      B U _ P R _ B I T V
00194  * @brief
00195  *  Print the bits set in a bit vector.
00196  *  Use bu_vls stuff, to make only a single call to bu_log().
00197  */
00198 void
00199 bu_pr_bitv(const char *str, register const struct bu_bitv *bv)
00200 {
00201     struct bu_vls       v;
00202 
00203     BU_CK_BITV(bv)
00204         bu_vls_init( &v );
00205     bu_vls_strcat( &v, str );
00206     bu_vls_strcat( &v, ": " );
00207     bu_bitv_vls( &v, bv );
00208     bu_log("%s", bu_vls_addr( &v ) );
00209     bu_vls_free( &v );
00210 }
00211 
00212 /**
00213  *                      B U _ B I T V _ T O _ H E X
00214  * @brief
00215  *      Convert a bit vector to an ascii string of hex digits.
00216  *      The string is from MSB to LSB (bytes and bits).
00217  */
00218 void
00219 bu_bitv_to_hex(struct bu_vls *v, register const struct bu_bitv *bv)
00220 {
00221     unsigned int word_count, byte_no;
00222 
00223     BU_CK_VLS( v );
00224     BU_CK_BITV( bv );
00225 
00226     word_count = bv->nbits/8/sizeof( bitv_t );
00227     byte_no = sizeof( bitv_t );
00228 
00229     bu_vls_extend( v, word_count * sizeof( bitv_t ) * 2 + 1 );
00230     while( word_count-- )
00231         {
00232             while( byte_no-- )
00233                 {
00234                     bu_vls_printf( v, "%02lx",
00235                                    ((bv->bits[word_count] & (((bitv_t)0xff)<<(byte_no*8))) >> (byte_no*8)) & (bitv_t)0xff );
00236                 }
00237             byte_no = sizeof( bitv_t );
00238         }
00239 }
00240 
00241 /**
00242  *                      B U _ H E X _ T O _ B I T V
00243  * @brief
00244  *      Convert a string of HEX digits (as produces by bu_bitv_to_hex) into a bit vector.
00245  */
00246 struct bu_bitv *
00247 bu_hex_to_bitv(const char *str)
00248 {
00249     char abyte[3];
00250     const char *str_start;
00251     unsigned int len=0;
00252     int bytes;
00253     struct bu_bitv *bv;
00254     unsigned long c;
00255     int word_count, byte_no;
00256 
00257     abyte[2] = '\0';
00258 
00259     /* skip over any initial white space */
00260     while( isspace( *str ) )
00261         str++;
00262 
00263     str_start = str;
00264     /* count hex digits */
00265     while( isxdigit( *str ) )
00266         str++;
00267 
00268     len = str - str_start;
00269 
00270     if( len < 2 || len%2 )
00271         {
00272             /* Must be two digits per byte */
00273             bu_log( "bu_hex_to_bitv: illegal hex bitv (%s)\n", str_start );
00274             return( (struct bu_bitv *)NULL );
00275         }
00276 
00277     bytes = len / 2; /* two hex digits per byte */
00278     bv = bu_bitv_new( len * 4 ); /* 4 bits per hex digit */
00279     bu_bitv_clear( bv );
00280     word_count = bytes/sizeof( bitv_t );
00281     byte_no = bytes % sizeof( bitv_t );
00282     if( !byte_no )
00283         byte_no = sizeof( bitv_t );
00284     else
00285         word_count++;
00286 
00287     str = str_start;
00288     while( word_count-- )
00289         {
00290             while( byte_no-- )
00291                 {
00292                     /* get next two hex digits from string */
00293                     abyte[0] = *str++;
00294                     abyte[1] = *str++;
00295 
00296                     /* convert into an unsigned long */
00297                     c = strtoul( abyte, (char **)NULL, 16 );
00298 
00299                     /* set the appropriate bits in the bit vector */
00300                     bv->bits[word_count] |= (bitv_t)c<<(byte_no*8);
00301                 }
00302             byte_no = sizeof( bitv_t );
00303         }
00304 
00305     return( bv );
00306 }
00307 
00308 /**
00309  *                      B U _ B I T V _ D U P
00310  * @brief
00311  *      Make a copy of a bit vector
00312  */
00313 struct bu_bitv *
00314 bu_bitv_dup(register const struct bu_bitv *bv)
00315 {
00316     struct bu_bitv *bv2;
00317 
00318     bv2 = bu_bitv_new( bv->nbits );
00319     bu_bitv_clear( bv2 );
00320     bu_bitv_or( bv2, bv );
00321 
00322     return( bv2 );
00323 }
00324 /*@}*/
00325 /*
00326  * Local Variables:
00327  * mode: C
00328  * tab-width: 8
00329  * c-basic-offset: 4
00330  * indent-tabs-mode: t
00331  * End:
00332  * ex: shiftwidth=4 tabstop=8
00333  */

Generated on Mon Sep 18 01:24:47 2006 for BRL-CAD by  doxygen 1.4.6