Main Page | Modules | Alphabetical List | Data Structures | File List | Data Fields | Related Pages

bitstring.c

00001 /* 00002 00003 The BLAH library, a container library 00004 Copyright (C) 1997-2004 The CDG Team <cdg@nats.informatik.uni-hamburg.de> 00005 00006 This program is free software; you can redistribute it and/or modify 00007 it under the terms of the GNU General Public License as published by 00008 the Free Software Foundation; either version 2 of the License, or 00009 (at your option) any later version. 00010 00011 This program is distributed in the hope that it will be useful, 00012 but WITHOUT ANY WARRANTY; without even the implied warranty of 00013 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00014 GNU General Public License for more details. 00015 00016 You should have received a copy of the GNU General Public License 00017 along with this program; if not, write to the Free Software 00018 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 00019 00020 Contact: blah@nats.informatik.uni-hamburg.de 00021 00022 $Id: bitstring.c,v 1.7 2004/09/23 15:45:25 micha Exp $ 00023 00024 */ 00025 00026 /* ---------------------------------------------------------------------- 00027 * @defgroup BitString BitStrings 00028 * 00029 * Implementation of a string of bits. 00030 * 00031 * A bitstring is a memory efficient implementation of a sequence of 00032 * Boolean information with arbitrary but fixed length. 00033 * 00034 * @{ 00035 */ 00036 00037 00038 /* -- INCLUDES ------------------------------------------------------- */ 00039 #include <stdio.h> 00040 #include <string.h> 00041 #include "blah.h" 00042 00043 /* --MACROS ---------------------------------------------------------- */ 00044 00045 /* ---------------------------------------------------------------------- 00046 * defines our version of a BYTE definition 00047 */ 00048 #define BITS_PER_BYTE 8 00049 00050 /* ---------------------------------------------------------------------- 00051 * defines the size of an unsigned long 00052 */ 00053 #define BYTES_PER_LONG sizeof(unsigned long) 00054 00055 /* ---------------------------------------------------------------------- 00056 * defines the number of bits in an unsigned long integer 00057 */ 00058 #define BITS_PER_LONG (BITS_PER_BYTE*BYTES_PER_LONG) 00059 00060 /* ---------------------------------------------------------------------- 00061 * return code for size error messages 00062 */ 00063 #define E_SIZEMISMATCH -1 00064 00065 /* -- TYPE DEFINITIONS ----------------------------------------------- */ 00066 00067 /* ---------------------------------------------------------------------- 00068 * internal structure of a string of bits. 00069 */ 00070 00071 struct BitStringStruct { 00072 #ifdef BITSTRINGS_DEBUG 00073 int magic; /**< magic number to identify bitstrings */ 00074 int magic; /**< magic number to identify bitstrings */ 00075 #endif 00076 int size; /**< size of bitstring in bits */ 00077 int length; /**< length of array; 00078 length=capacity/BITS_PER_LONG */ 00079 unsigned long mask; /**< mask for the last unsigned long */ 00080 unsigned long *bits; /**< array of longs */ 00081 }; 00082 00083 /* -- VARIABLES ------------------------------------------------------ */ 00084 #ifdef BITSTRINGS_DEBUG 00085 static int magic_constant=-321934; 00086 #endif 00087 00088 /* -- FUNCTIONS ------------------------------------------------------ */ 00089 00090 #ifdef BITSTRINGS_DEBUG 00091 static void print_long_as_binary(unsigned long l) 00092 { 00093 int i; 00094 00095 for (i=0; i<BITS_PER_LONG; i++) 00096 { 00097 printf("%d", l & (1<<i) ? 1 : 0); 00098 } 00099 } 00100 00101 static void check_magic_function(BitString bs, char *file, int no) 00102 { 00103 if (bs->magic!=magic_constant) 00104 { 00105 fprintf(stderr, "%s:%d: not a bitstring\n", file, no); 00106 abort(); 00107 } 00108 } 00109 /* ---------------------------------------------------------------------- 00110 * a magic checking routine used when compiled with -DBITSTRINGS_DEBUG 00111 */ 00112 #define check_magic(bs) check_magic_function(bs, __FILE__, __LINE__) 00113 00114 #else /* #ifdef BITSTRINGS_DEBUG */ 00115 00116 /* ---------------------------------------------------------------------- 00117 * this is defined to a null operation when debugging is switched off. 00118 * 00119 * Switch it on by compiling with -DBITSTRINGS_DEBUG 00120 */ 00121 #define check_magic(bs) 00122 00123 #endif /* #ifdef BITSTRINGS_DEBUG */ 00124 00125 00126 /* ---------------------------------------------------------------------- 00127 * creates a new bitstring with an initial size of \a size bits. 00128 * 00129 * @param size specifies the size of the new bit vector to be created. 00130 * @returns a new bit vector of the specified size. 00131 */ 00132 BitString bitNew(int size) 00133 { 00134 BitString bs; 00135 int s; 00136 int i; 00137 00138 if(size <= 0) { 00139 size = 1; 00140 } 00141 00142 s=size/BITS_PER_LONG; 00143 if (0 != size%BITS_PER_LONG) { s++; } 00144 00145 bs=(BitString)memMalloc(sizeof(BitStringStruct)); 00146 #ifdef BITSTRINGS_DEBUG 00147 bs->magic=magic_constant; 00148 #endif 00149 bs->size=size; 00150 bs->length=s; 00151 00152 /* 00153 * bs->mask has all significant bits in the last unsigned long 00154 * set and all unsignificant bits cleared. 00155 */ 00156 bs->mask = ~(unsigned long)0; 00157 for (i=bs->size%BITS_PER_LONG; i<BITS_PER_LONG; i++) 00158 { 00159 /* clear ith bit */ 00160 bs->mask &= ~(1 << i); 00161 } 00162 bs->bits=(unsigned long *)memMalloc(s*BYTES_PER_LONG); 00163 /* memset(bs->bits, 0x55, s*BYTES_PER_LONG); */ 00164 memset(bs->bits, 0, s*BYTES_PER_LONG); 00165 00166 return(bs); 00167 } 00168 00169 /* ---------------------------------------------------------------------- 00170 * creates a new bitstring which is a complete clone of bs. 00171 * 00172 * @param bs the bit string that has to be cloned 00173 * @returns a copy of the bitstring after cloning. 00174 */ 00175 BitString bitClone(BitString bs) 00176 { 00177 BitString new; 00178 00179 check_magic(bs); 00180 00181 new=bitNew(bs->size); 00182 memcpy(new->bits, bs->bits, bs->length*BYTES_PER_LONG); 00183 00184 return(new); 00185 } 00186 00187 /* ---------------------------------------------------------------------- 00188 * copies information from src to dst. 00189 * 00190 * dst and src must be bitstrings of the same size 00191 * 00192 * @param dst destination BitString 00193 * @param src source Bitstring 00194 * @returns 1 on success, 0 on failure (e. g. , due to size mismatch) 00195 * 00196 */ 00197 BitString bitCopy(BitString dst, BitString src) 00198 { 00199 check_magic(dst); 00200 check_magic(src); 00201 00202 if (dst->size!=src->size) { return NULL; } 00203 memcpy(dst->bits, src->bits, src->length*BYTES_PER_LONG); 00204 00205 return dst; 00206 } 00207 00208 00209 /* ---------------------------------------------------------------------- 00210 * deletes bitstring \a bs and frees memory. 00211 * 00212 * @param bs the bitstring that has to be deleted. 00213 */ 00214 void bitDelete(BitString bs) 00215 { 00216 check_magic(bs); 00217 00218 memFree(bs->bits); 00219 memFree(bs); 00220 } 00221 00222 /* ---------------------------------------------------------------------- 00223 * returns the size of bitstring \a bs. 00224 * 00225 * @param bs the bitstring whose size has to be determined. 00226 * @returns the size of the bitstring bs 00227 */ 00228 int bitSize(BitString bs) 00229 { 00230 check_magic(bs); 00231 00232 return bs->size; 00233 } 00234 00235 /* ---------------------------------------------------------------------- 00236 * prints a bitstring to stdout. 00237 * 00238 * @param bs the BitString to be printed 00239 */ 00240 void bitPrint(BitString bs) 00241 { 00242 int i; 00243 00244 check_magic(bs); 00245 00246 for(i=0; i<bs->size; i++) 00247 { 00248 printf("%d", bitGet(bs, i) ? 1 : 0); 00249 } 00250 } 00251 00252 /* ---------------------------------------------------------------------- 00253 * resize bs to size \a size; sets length, mask and size. 00254 * 00255 * @param bs the bitstring that has to be resized. 00256 * @param size the size to which the bitstring has to be resized. 00257 * @returns the new resized bitstring. 00258 */ 00259 static void resize(BitString bs, int size) 00260 { 00261 int i; 00262 00263 if (size>bs->length*BITS_PER_LONG) 00264 { 00265 int l; 00266 00267 #ifdef BITSTRINGS_DEBUG 00268 fprintf(stderr, "resize: re-alloc necessary\n"); 00269 #endif 00270 l=size/BITS_PER_LONG; 00271 if (0 != size%BITS_PER_LONG) { l++; } 00272 bs->bits=(unsigned long *)memRealloc(bs->bits, l*BYTES_PER_LONG); 00273 /* clear those bits that are new */ 00274 memset(&bs->bits[bs->length], 0, (l-bs->length)*BYTES_PER_LONG); 00275 bs->length=l; 00276 } 00277 00278 bs->size=size; 00279 00280 /* 00281 * bs->mask has all significant bits in the last unsigned long 00282 * set and all unsignificant bits cleared. 00283 */ 00284 bs->mask = ~(unsigned long)0; 00285 for (i=bs->size%BITS_PER_LONG; i<BITS_PER_LONG; i++) 00286 { 00287 /* clear ith bit */ 00288 bs->mask &= ~(1 << i); 00289 } 00290 } 00291 00292 /* ---------------------------------------------------------------------- 00293 * sets a bit. 00294 * 00295 * if \a no is larger than current size the bitstring is enlarged. 00296 * intermediate bits are cleared. 00297 * Bits are numbered from zero upwards. 00298 * 00299 * @param bs the bitstring in which a bit has to be set. 00300 * @param no the number of the bit that has to be set 00301 */ 00302 void bitSet(BitString bs, int no) 00303 { 00304 check_magic(bs); 00305 00306 if (bs->size<=no) { resize(bs, no+1); } 00307 bs->bits[no/BITS_PER_LONG] |= (1<<(no%BITS_PER_LONG)); 00308 } 00309 00310 00311 /* ---------------------------------------------------------------------- 00312 * clears a bit. 00313 * 00314 * if no is larger than current size the bitstring is enlarged. 00315 * intermediate bits are cleared. 00316 * Bits are numbered from zero upward 00317 * 00318 * @param bs the bitstring from which a bit has to be cleared. 00319 * @param no the bit number that has to be cleared. 00320 */ 00321 void bitClear(BitString bs, int no) 00322 { 00323 check_magic(bs); 00324 00325 if (bs->size<=no) { resize(bs, no+1); } 00326 bs->bits[no/BITS_PER_LONG] &= ~(1<<(no%BITS_PER_LONG)); 00327 } 00328 00329 00330 /* ---------------------------------------------------------------------- 00331 * sets all the bits to one. 00332 * 00333 * @param bs the bitstring whose bits are to be set. 00334 * @returns the new bitstring after setting all its bits to 1. 00335 */ 00336 void bitSetAll(BitString bs) 00337 { 00338 check_magic(bs); 00339 00340 memset(bs->bits, ~0, bs->length*BYTES_PER_LONG); 00341 bs->bits[bs->length-1] &= bs->mask; 00342 } 00343 00344 /* ---------------------------------------------------------------------- 00345 * sets all bits to zero. 00346 * 00347 * @param bs the bitstring whose bits are to be cleared. 00348 * @returns the new bitstring after setting all its bits to zero. 00349 */ 00350 void bitClearAll(BitString bs) 00351 { 00352 check_magic(bs); 00353 00354 memset(bs->bits, 0, bs->length*BYTES_PER_LONG); 00355 } 00356 00357 /* ---------------------------------------------------------------------- 00358 * computes a logical \a AND between two sets of bits 00359 * 00360 * sets all the bits in bitstring a that are set to 0 in bitstring b to 0. 00361 * bitstring b is never modified. 00362 * the bitstrings must be of the same size. 00363 * 00364 * @param a the first set of bits 00365 * @param b the second set of bits 00366 * @returns a on success and NULL on failure. 00367 */ 00368 BitString bitAnd(BitString a, BitString b) 00369 { 00370 int i; 00371 00372 check_magic(a); 00373 check_magic(b); 00374 00375 if (a->size!=b->size) { return NULL; } 00376 00377 for (i=0; i<a->length; i++) 00378 { 00379 a->bits[i] &= b->bits[i]; 00380 } 00381 00382 return a; 00383 } 00384 00385 00386 /* ---------------------------------------------------------------------- 00387 * computes a logical \a OR between two sets of bits 00388 * 00389 * sets all the bits in bitstring a that are set to 1 in bitstring b to 1. 00390 * bitstring b is never modified. 00391 * the bitstrings must be of the same size. 00392 * 00393 * @param a the first set of bits 00394 * @param b the second set of bits 00395 * @returns a on success and NULL on failure. 00396 */ 00397 BitString bitOr(BitString a, BitString b) 00398 { 00399 int i; 00400 00401 check_magic(a); 00402 check_magic(b); 00403 00404 if (a->size!=b->size) { return NULL; } 00405 00406 for (i=0; i<a->length; i++) 00407 { 00408 a->bits[i] |= b->bits[i]; 00409 } 00410 00411 return a; 00412 } 00413 00414 /* ---------------------------------------------------------------------- 00415 * checks whether two sets have bits switched on in common 00416 * 00417 * @param a the first set 00418 * @param b the second set of bits 00419 * @returns TRUE on the first common bit (i.e. two bits at the same position 00420 * which are switched on); otherwise false is returned, that there are no 00421 * common bits switched on. 00422 * @requires a->size == b->size 00423 */ 00424 Boolean bitCheck(BitString a, BitString b) 00425 { 00426 int i; 00427 00428 check_magic(a); 00429 check_magic(b); 00430 00431 if (a->size != b->size) { 00432 return FALSE; 00433 } 00434 00435 for (i = 0; i < a->length; i++) { 00436 if (a->bits[i] & b->bits[i]) { 00437 return TRUE; 00438 } 00439 } 00440 00441 return FALSE; 00442 } 00443 00444 /* ---------------------------------------------------------------------- 00445 * test for a bit 00446 * 00447 * This function checks whether a bitstring has bit at a certain 00448 * position switched on. 00449 * 00450 * @param bs the bitstring 00451 * @param no the position where to look at 00452 * @returns the state of the bit at the given position 00453 */ 00454 Boolean bitGet(BitString bs, int no) 00455 { 00456 check_magic(bs); 00457 #ifdef BITSTRINGS_DEBUG 00458 if (bs->size <= no) { 00459 fprintf(stderr, "bitGet: no >= bs->size\n"); 00460 abort(); 00461 } 00462 #endif 00463 00464 return (bs-> bits[no / BITS_PER_LONG] & (1 << (no % BITS_PER_LONG)) ? TRUE : 00465 FALSE); 00466 } 00467 00468 /* ---------------------------------------------------------------------- 00469 * checks whether all bits are cleared 00470 * 00471 * @param bs the bitstring we are talking about 00472 * @returns FALSE on the first bit being switched on, or TRUE if all are 00473 * switched off 00474 */ 00475 Boolean bitIsAllCleared(BitString bs) 00476 { 00477 int i; 00478 00479 check_magic(bs); 00480 00481 for (i = 0; i < bs->length; i++) { 00482 if (bs->bits[i]) { 00483 return (FALSE); 00484 } 00485 } 00486 00487 return (TRUE); 00488 } 00489 00490 /* ---------------------------------------------------------------------- 00491 * checks whether all bits are set 00492 * 00493 * @see bitIsAllCleared 00494 * @param bs the current bitstring 00495 * @returns FALSE on the first bit being swithced off, or TRUE of all bits 00496 * are switched on 00497 */ 00498 Boolean bitIsAllSet(BitString bs) 00499 { 00500 int i; 00501 00502 check_magic(bs); 00503 00504 for (i = 0; i < bs->length - 1; i++) { 00505 if (~bs->bits[i]) { 00506 return (FALSE); 00507 } 00508 } 00509 00510 return bs->bits[bs->length - 1] == bs->mask ? TRUE : FALSE; 00511 } 00512 00513 /* ---------------------------------------------------------------------- */ 00514 /* ---------------------------------------------------------------------- */ 00515 /** @} */

BLAH 0.95 (20 Oct 2004)