bit_vector.cpp

Go to the documentation of this file.
00001 #ifndef BIT_VECTOR_IMPLEMENTATION_FILE
00002 #define BIT_VECTOR_IMPLEMENTATION_FILE
00003 
00004 /*****************************************************************************\
00005 *                                                                             *
00006 *  Name   : bit_vector                                                        *
00007 *  Author : Chris Koeritz                                                     *
00008 *                                                                             *
00009 *******************************************************************************
00010 * Copyright (c) 1990-$now By Author.  This program is free software; you can  *
00011 * redistribute it and/or modify it under the terms of the GNU General Public  *
00012 * License as published by the Free Software Foundation; either version 2 of   *
00013 * the License or (at your option) any later version.  This is online at:      *
00014 *     http://www.fsf.org/copyleft/gpl.html                                    *
00015 * Please send any updates to: fred@gruntose.com                               *
00016 \*****************************************************************************/
00017 
00018 #include "bit_vector.h"
00019 
00020 #include <basis/byte_array.h>
00021 #include <basis/function.h>
00022 #include <basis/guards.h>
00023 #include <basis/log_base.h>
00024 
00025 //#define DEBUG_BIT_VECTOR
00026   // uncomment this to get debugging noise.
00027 
00028 #undef LOG
00029 #ifdef DEBUG_BIT_VECTOR
00030   #define LOG(s) CLASS_EMERGENCY_LOG(program_wide_logger(), s)
00031 #else
00032   #define LOG(s) {}
00033 #endif
00034 
00035 bit_vector::bit_vector()
00036 : _implementation(new byte_array(0, NIL)), _number_of_bits(0)
00037 {}
00038 
00039 bit_vector::bit_vector(int number_of_bits, const byte *initial)
00040 : _implementation(new byte_array(0, NIL)), _number_of_bits(0)
00041 {
00042   reset(number_of_bits);
00043   if (!initial) return;
00044   _implementation->reset(number_of_packets(number_of_bits,
00045       int(BITS_PER_BYTE)), initial);
00046 }
00047 
00048 bit_vector::bit_vector(const bit_vector &to_copy)
00049 : _implementation(new byte_array(*to_copy._implementation)),
00050   _number_of_bits(to_copy._number_of_bits)
00051 {}
00052 
00053 bit_vector::~bit_vector() { WHACK(_implementation); }
00054 
00055 bit_vector &bit_vector::operator = (const bit_vector &to_copy)
00056 {
00057   if (this == &to_copy) return *this;
00058   *_implementation = *to_copy._implementation;
00059   _number_of_bits = to_copy._number_of_bits;
00060   return *this;
00061 }
00062 
00063 bit_vector::operator const byte_array & () const { return *_implementation; }
00064 
00065 int bit_vector::bits() const { return _number_of_bits; }
00066 
00067 bool bit_vector::whole() const { return negative(find_first(0)); }
00068 
00069 bool bit_vector::empty() const { return negative(find_first(1)); }
00070 
00071 bool bit_vector::operator == (const bit_vector &that) const
00072 { return compare(that, 0, _number_of_bits); }
00073 
00074 bool bit_vector::operator != (const bit_vector &that) const
00075 { return !(*this == that); }
00076 
00077 bool bit_vector::on(int position) const
00078 { return get_bit(into_two_dim(position)); }
00079 
00080 bool bit_vector::off(int position) const { return !on(position); }
00081 
00082 void bit_vector::resize(int number_of_bits)
00083 {
00084 //printf("resize invoked, old size %d, new size %d...\n", bits(), number_of_bits);
00085   if (negative(number_of_bits)) return;
00086   if (bits() == number_of_bits) return;
00087   int old_size = bits();
00088   _number_of_bits = number_of_bits;
00089   int number_of_bytes = number_of_packets(number_of_bits, int(BITS_PER_BYTE));
00090   _implementation->resize(number_of_bytes);
00091   // clear new space if the vector got larger.
00092   if (old_size < number_of_bits) {
00093     // lazy reset doesn't compute byte boundary, just does 8 bits.
00094     for (int i = old_size; i < old_size + 8; i++) {
00095       clear(i);
00096 //printf("clearing bit %d.\n", i);
00097     }
00098     // clear the bytes remaining.
00099     int old_bytes = number_of_packets(old_size + 8, int(BITS_PER_BYTE));
00100     for (int j = old_bytes; j < number_of_bytes; j++) {
00101 //printf("clearing bit %d through %d.\n", j * 8, j * 8 + 7);
00102       _implementation->use(j) = 0;
00103     }
00104   }
00105 }
00106 
00107 void bit_vector::reset(int number_of_bits)
00108 {
00109   resize(number_of_bits);
00110   memset(_implementation->access(), 0, _implementation->length());
00111 }
00112 
00113 bit_vector::two_dim_location bit_vector::into_two_dim(int position) const
00114 {
00115   two_dim_location to_return;
00116   to_return.byte = position / BITS_PER_BYTE;
00117   to_return.offset = position % BITS_PER_BYTE;
00118   return to_return;
00119 }
00120 
00121 bool bit_vector::get_bit(const two_dim_location &pos_in2) const
00122 {
00123   bounds_return(pos_in2.byte * BITS_PER_BYTE + pos_in2.offset, 0,
00124     _number_of_bits - 1, false);
00125   byte test_mask = byte(1 << pos_in2.offset);
00126   return TEST(byte(_implementation->get(pos_in2.byte)), test_mask);
00127 }
00128 
00129 void bit_vector::set_bit(int position, bool value)
00130 {
00131   bounds_return(position, 0, bits() - 1, );
00132   set_bit(into_two_dim(position), value);
00133 }
00134 
00135 void bit_vector::set_bit(const two_dim_location &pos_in2, bool set_it)
00136 {
00137   byte test_mask = byte(1 << pos_in2.offset);
00138   if (set_it) SET(_implementation->use(pos_in2.byte), test_mask);
00139   else CLEAR((byte &)_implementation->get(pos_in2.byte), test_mask);
00140 }
00141 
00142 bool bit_vector::operator [](int position) const
00143 {
00144   bounds_return(position, 0, _number_of_bits - 1, false);
00145   return get_bit(into_two_dim(position));
00146 }
00147 
00148 void bit_vector::light(int position)
00149 {
00150   bounds_return(position, 0, _number_of_bits - 1, );
00151   set_bit(into_two_dim(position), true);
00152 }
00153 
00154 void bit_vector::clear(int position)
00155 {
00156   bounds_return(position, 0, _number_of_bits - 1, );
00157   set_bit(into_two_dim(position), false);
00158 }
00159 
00160 int bit_vector::find_first(bool to_find) const
00161 {
00162   const byte whole_set = byte(0xFF);
00163   // search through the whole bytes first.
00164   for (int full_byte = 0; full_byte < _implementation->length(); full_byte++) {
00165     if ( (to_find && _implementation->get(full_byte))
00166          || (!to_find && (_implementation->get(full_byte) != whole_set)) ) {
00167       // the first appropriate byte is searched for the first appropriate bit.
00168       for (int i = full_byte * BITS_PER_BYTE; i < minimum
00169           (int(_number_of_bits), (full_byte+1)*BITS_PER_BYTE); i++) {
00170         if (on(i) == to_find) return i;
00171       }
00172       return common::NOT_FOUND;
00173     }
00174   }
00175   return common::NOT_FOUND;
00176 }
00177 
00178 bool bit_vector::compare(const bit_vector &that, int start, int stop) const
00179 {
00180   for (int i = start; i <= stop; i++) {
00181     if (on(i) != that.on(i)) return false;
00182   }
00183   return true;
00184 }
00185 
00186 istring bit_vector::text_form() const
00187 {
00188   istring to_return;
00189   int bits_on_line = 0;
00190   const int max_bits_on_line = 64;
00191   for (int i = 0; i < _number_of_bits; i++) {
00192     // below prints out the bit number heading.
00193     if (bits_on_line == 0) {
00194       if (i != 0) to_return += log_base::platform_ending();
00195       if (i < 10000) to_return += " ";
00196       if (i < 1000) to_return += " ";
00197       if (i < 100) to_return += " ";
00198       if (i < 10) to_return += " ";
00199       to_return += isprintf("%d", i);
00200       to_return += " | ";
00201     }
00202     if (on(i)) to_return += "1";
00203     else to_return += "0";
00204     bits_on_line++;
00205     if (bits_on_line >= max_bits_on_line) bits_on_line = 0;
00206     else if ( !(bits_on_line % BITS_PER_BYTE) ) to_return += " ";
00207   }
00208   to_return += log_base::platform_ending();
00209   return to_return;
00210 }
00211 
00212 bit_vector bit_vector::subvector(int start, int end) const
00213 {
00214   bounds_return(start, 0, bits() - 1, bit_vector());
00215   bounds_return(end, 0, bits() - 1, bit_vector());
00216   int size = end - start + 1;
00217   bit_vector to_return(size);
00218   for (int i = start; i <= end; i++) to_return.set_bit(i - start, on(i));
00219   return to_return;
00220 }
00221 
00222 bool bit_vector::overwrite(int start, const bit_vector &to_write)
00223 {
00224   bounds_return(start, 0, bits() - 1, false);
00225   int end = start + to_write.bits() - 1;
00226   bounds_return(end, 0, bits() - 1, false);
00227   for (int i = start; i <= end; i++) set_bit(i, to_write[i - start]);
00228   return true;
00229 }
00230 
00231 enum endian { LEFT_ENDIAN, RIGHT_ENDIAN };
00232 endian host_byte_order = LEFT_ENDIAN;  // bytes within words.
00233 endian host_bit_order = LEFT_ENDIAN;  // bits within bytes.
00234 
00235 // probably the treatment for right endian in either case
00236 // of bytes or bits is wrong.
00237 
00238 bool bit_vector::set(int start, int size, u_int source)
00239 {
00240   bounds_return(start, 0, bits() - 1, false);
00241   int end = start + size - 1;
00242   bounds_return(end, 0, bits() - 1, false);
00243   bounds_return(size, 1, 32, false);
00244   bit_vector from_int(32, (byte *)&source);
00245 
00246 // is this algorithm even remotely near the truth?
00247   if (host_bit_order == RIGHT_ENDIAN)
00248     from_int._implementation->resize(size, common::NEW_AT_BEGINNING);
00249   else from_int.resize(size);  // left endian machine.
00250   overwrite(start, from_int);
00251   return true;
00252 }
00253 
00254 u_int bit_vector::get(int start, int size) const
00255 {
00256   int end = start + size - 1;
00257   bit_vector segment = subvector(start, end);
00258   // padding to bytes.
00259   int new_length = segment.bits();
00260   if (new_length % 8) {
00261     new_length = ( (new_length+8) / 8) * 8;
00262     LOG(isprintf("new size is %d.", new_length));
00263   }
00264   segment.resize(new_length);
00265 
00266   if (host_bit_order == RIGHT_ENDIAN) {
00267     bit_vector new_segment(segment.bits());
00268     for (int i = 0; i < segment.bits(); i += 8)
00269       for (int j = i; j < i + BITS_PER_BYTE; j++)
00270         if (j < segment.bits())
00271           new_segment.set_bit(i + (7 - (j - i)), segment[j]);
00272     segment = new_segment;  // copy the new form.
00273   }
00274 
00275   LOG("new seg after bit copy:");
00276   LOG(segment);
00277 
00278   u_int to_return = 0;
00279 
00280   int bytes_used = number_of_packets(segment.bits(), int(BITS_PER_BYTE));
00281   // 4 = # of bytes in a int.
00282   for (int i = minimum(4, bytes_used) - 1; i >= 0; i--) {
00283 #ifdef DEBUG_BIT_VECTOR
00284     bit_vector tmp(8, &segment._implementation->get(i));
00285     LOG(isprintf("%d: src bits %s", i, tmp.text_form().s()));
00286 #endif
00287 
00288 #ifdef DEBUG_BIT_VECTOR
00289     bit_vector tmp4(32, (byte *)&to_return);
00290     LOG(isprintf("%d: pre shift dest %s", i, tmp4.text_form().s()));
00291 #endif
00292     if (host_byte_order == LEFT_ENDIAN) to_return <<= 8;
00293     else to_return >>= 8;
00294 #ifdef DEBUG_BIT_VECTOR
00295     bit_vector tmp5(32, (byte *)&to_return);
00296     LOG(isprintf("%d: post shift dest %s", i, tmp5.text_form().s()));
00297 #endif
00298 
00299     u_int mask = segment._implementation->get(i);
00300     if (host_byte_order == RIGHT_ENDIAN) mask <<= 23;
00301 #ifdef DEBUG_BIT_VECTOR
00302     bit_vector tmp3(32, (byte *)&to_return);
00303     LOG(isprintf("%d: pre dest bits %s", i, tmp3.text_form().s()));
00304 #endif
00305     SET(to_return, mask);
00306 #ifdef DEBUG_BIT_VECTOR
00307     bit_vector tmp2(32, (byte *)&to_return);
00308     LOG(isprintf("%d: post dest bits %s", i, tmp2.text_form().s()));
00309 #endif
00310   }
00311 
00312 #ifdef DEBUG_BIT_VECTOR
00313   bit_vector tmp(32, (byte *)&to_return);
00314   LOG(isprintf("final bits %s", tmp.text_form().s()));
00315 #endif
00316   return to_return;
00317 }
00318 
00319 
00320 #endif //BIT_VECTOR_IMPLEMENTATION_FILE
00321 

Generated on Fri Nov 28 04:29:11 2008 for HOOPLE Libraries by  doxygen 1.5.1