00001 #include <string.h>
00002 #include "charm++.h"
00003 #include "ckbitvector.h"
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033 CkBitVector::CkBitVector() : usedBits(0), data(NULL) {
00034 }
00035
00036
00037 CkBitVector::CkBitVector(const CkBitVector &b) : usedBits(b.usedBits) {
00038 if ( b.data ) {
00039 data = new prio_t[chunks(usedBits)];
00040 memcpy(data, b.data, chunks(usedBits)*chunkSize());
00041 } else {
00042 data = NULL;
00043 }
00044 }
00045
00046
00047 CkBitVector::CkBitVector(prio_t bits) : usedBits(bits) {
00048 if ( bits != 0 ) {
00049 data = new prio_t[chunks(usedBits)];
00050 memset(data, 0, chunks(usedBits)*chunkSize());
00051 } else {
00052 data = NULL;
00053 }
00054 }
00055
00056
00057
00058 CkBitVector::CkBitVector(prio_t value, prio_t choices) {
00059
00060 if ( value >= choices ) {
00061 CkAbort("User asked for a bit vector too large for the number of choices specified!");
00062 }
00063
00064
00065
00066 usedBits = ilog2(choices);
00067 if ( usedBits != 0 ) {
00068 data = new prio_t[chunks(usedBits)];
00069 data[0] = value << (chunkBits() - usedBits);
00070 } else {
00071 data = NULL;
00072 }
00073 }
00074
00075
00076 CkBitVector::~CkBitVector() {
00077 wipeData();
00078 }
00079
00080
00081 void CkBitVector::wipeData() {
00082 if ( data ) {
00083 delete [] data;
00084 data = NULL;
00085 }
00086
00087 usedBits = 0;
00088 }
00089
00090
00091
00092 CkBitVector & CkBitVector::operator=(const CkBitVector &b) {
00093
00094 wipeData();
00095
00096
00097 if ( b.usedBits == 0 || b.data == NULL ) {
00098 usedBits = 0;
00099 data = NULL;
00100 } else {
00101
00102 usedBits = b.usedBits;
00103 data = new prio_t[chunks(usedBits)];
00104 memcpy(data, b.data, chunks(usedBits)*chunkSize());
00105 }
00106
00107
00108 return *this;
00109 }
00110
00111
00112
00113 CkBitVector & CkBitVector::Zero() {
00114
00115 if ( data == NULL ) { return *this; }
00116
00117
00118 memset(data, 0, chunkSize()*chunks(usedBits));
00119
00120 return *this;
00121 }
00122
00123
00124 CkBitVector & CkBitVector::Invert() {
00125
00126 if ( data == NULL ) { return *this; }
00127
00128
00129
00130
00131 int i;
00132 for ( i = 0 ; i < chunks(usedBits) ; i++ ) {
00133 data[i] = ~(data[i]);
00134 }
00135 if ( usedBits % chunkBits() != 0 ) {
00136 i = chunks(usedBits) - 1;
00137 data[i] = data[i] & ((~(unsigned int)0)<<(chunkBits()-(usedBits%chunkBits())));
00138 }
00139
00140 return *this;
00141 }
00142
00143
00144 CkBitVector & CkBitVector::Clear(prio_t bit) {
00145
00146
00147 if ( bit+1 > usedBits ) {
00148 Resize(bit+1);
00149 return *this;
00150 }
00151
00152
00153 prio_t index = offset(bit);
00154 prio_t bitMask = ~(mask(bit));
00155
00156
00157 data[index] = data[index] & bitMask;
00158
00159
00160 return *this;
00161 }
00162
00163
00164 CkBitVector & CkBitVector::Set(prio_t bit) {
00165
00166 if ( bit+1 > usedBits ) {
00167 Resize(bit+1);
00168 }
00169
00170
00171 prio_t index = offset(bit);
00172 prio_t bitMask = mask(bit);
00173
00174
00175 data[index] = data[index] | bitMask;
00176
00177
00178 return *this;
00179 }
00180
00181
00182 bool CkBitVector::Test(prio_t bit) const {
00183
00184 if ( bit+1 > usedBits ) { return false; }
00185
00186
00187 prio_t index = offset(bit);
00188 prio_t bitMask = mask(bit);
00189
00190
00191
00192
00193 return ((data[index]&bitMask) != 0);
00194 }
00195
00196
00197
00198
00199 CkBitVector & CkBitVector::ShiftUp(prio_t bits) {
00200
00201
00202 if ( ! data || bits == 0 ) { return *this; }
00203
00204
00205 prio_t whole = bits / chunkBits();
00206 prio_t rem = bits % chunkBits();
00207 for ( int i = 0 ; i < chunks(usedBits) ; i++ ) {
00208 if ( i+whole < chunks(usedBits) ) {
00209 data[i] = data[i+whole] << rem;
00210
00211 if ( i+whole+1 < chunks(usedBits) ) {
00212 data[i] = data[i] | (data[i+whole+1] >> (chunkBits()-rem));
00213 }
00214 } else {
00215 data[i] = 0;
00216 }
00217 }
00218
00219 return *this;
00220 }
00221
00222 CkBitVector & CkBitVector::ShiftDown(prio_t bits) {
00223
00224
00225 if ( ! data || bits == 0 ) { return *this; }
00226
00227
00228 int whole = bits / chunkBits();
00229 int rem = bits % chunkBits();
00230 for ( int i = chunks(usedBits)-1 ; i >= 0 ; i-- ) {
00231 if ( i-whole >= 0 ) {
00232 data[i] = data[i-whole] >> rem;
00233
00234 if ( i-whole-1 < chunks(usedBits) ) {
00235 data[i] = data[i] | (data[i-whole-1] << (chunkBits()-rem));
00236 }
00237 } else {
00238 data[i] = 0;
00239 }
00240 }
00241
00242 return *this;
00243 }
00244
00245
00246
00247
00248
00249
00250
00251 CkBitVector & CkBitVector::Resize(prio_t bits) {
00252
00253 if ( bits == usedBits ) { return *this; }
00254
00255
00256
00257 if ( ! data ) {
00258 usedBits = bits;
00259 data = new prio_t[chunks(usedBits)];
00260 memset(data, 0, chunks(usedBits)*chunkSize());
00261 return *this;
00262 }
00263
00264
00265 if ( bits == 0 ) {
00266 wipeData();
00267 return *this;
00268 }
00269
00270
00271 if ( bits > usedBits ) {
00272 prio_t shift = bits - usedBits;
00273 prio_t *oldData = data;
00274 data = new prio_t[chunks(bits)];
00275 memset(data, 0, chunks(bits)*chunkSize());
00276 memcpy(data, oldData, chunks(usedBits)*chunkSize());
00277 delete [] oldData;
00278 usedBits = bits;
00279 return ShiftDown(shift);
00280 }
00281
00282
00283 if ( bits < usedBits ) {
00284 ShiftUp(usedBits - bits);
00285 prio_t *oldData = data;
00286 data = new prio_t[chunks(bits)];
00287 memset(data, 0, chunks(bits)*chunkSize());
00288 memcpy(data, oldData, chunks(bits)*chunkSize());
00289 delete [] oldData;
00290 usedBits = bits;
00291 return *this;
00292 }
00293
00294
00295 CkAbort("What in heck did you do!!?!?! CkBitVector error in Resize()!");
00296 return *this;
00297 }
00298
00299
00300
00301
00302 CkBitVector & CkBitVector::Union(CkBitVector const &b) {
00303
00304 if ( usedBits != b.usedBits ) {
00305 CkAbort("CkBitVector Union operands must be of the same length!");
00306 }
00307
00308
00309 if ( data == NULL || b.data == NULL ) { return *this; }
00310
00311
00312 for ( int i = 0 ; i < chunks(usedBits) ; i++ ) {
00313 data[i] = data[i] | b.data[i];
00314 }
00315
00316 return *this;
00317 }
00318
00319
00320 CkBitVector & CkBitVector::Intersection(CkBitVector const &b) {
00321
00322 if ( usedBits != b.usedBits ) {
00323 CkAbort("CkBitVector Intersection operands must be of the same length!");
00324 }
00325
00326
00327 if ( data == NULL || b.data == NULL ) { return *this; }
00328
00329
00330 for ( int i = 0 ; i < chunks(usedBits) ; i++ ) {
00331 data[i] = data[i] & b.data[i];
00332 }
00333
00334 return *this;
00335 }
00336
00337
00338 CkBitVector & CkBitVector::Difference(CkBitVector const &b) {
00339
00340 if ( usedBits != b.usedBits ) {
00341 CkAbort("CkBitVector Difference operands must be of the same length!");
00342 }
00343
00344
00345 if ( data == NULL || b.data == NULL ) { return *this; }
00346
00347
00348 for ( int i = 0 ; i < chunks(usedBits) ; i++ ) {
00349 data[i] = data[i] & ~(b.data[i]);
00350 }
00351
00352 return *this;
00353 }
00354
00355
00356
00357
00358
00359 CkBitVector & CkBitVector::Concat(CkBitVector const &b) {
00360
00361 if ( ! data ) {
00362 *this = b;
00363 return *this;
00364 }
00365
00366
00367 CkBitVector tmp(b);
00368
00369
00370 tmp.Resize(usedBits + b.usedBits);
00371
00372
00373 unsigned int shiftBy = b.usedBits;
00374 Resize(usedBits + b.usedBits);
00375 ShiftUp(shiftBy);
00376
00377
00378 Union(tmp);
00379
00380 return *this;
00381 }
00382
00383
00384
00385
00386 CkOutStream& operator<< (CkOutStream& ckos, CkBitVector const b ) {
00387 if ( b.data ) {
00388 char *buff = new char[b.usedBits+1];
00389 for ( int i = b.usedBits-1 ; i >= 0 ; i-- ) {
00390 buff[(b.usedBits-1)-i] = (b.Test(i) ? '1' : '0');
00391 }
00392 buff[b.usedBits] = '\0';
00393 ckos << buff;
00394 delete[] buff;
00395 }
00396
00397 return ckos;
00398 }
00399
00400 CkErrStream& operator<< (CkErrStream& ckes, CkBitVector const b ) {
00401 if ( b.data ) {
00402 char *buff = new char[b.usedBits+1];
00403 for ( int i = b.usedBits-1 ; i >= 0 ; i-- ) {
00404 buff[(b.usedBits-1)-i] = (b.Test(i) ? '1' : '0');
00405 }
00406 buff[b.usedBits] = '\0';
00407 ckes << buff;
00408 delete[] buff;
00409 }
00410
00411 return ckes;
00412 }
00413
00414 int CkBitVector::Compare(const CkBitVector &b) const
00415 {
00416 int result = 0;
00417 int length, i;
00418 if(usedBits > b.usedBits)
00419 {
00420 result = 1;
00421 length = chunks(b.usedBits);
00422 }
00423 else if (usedBits < b.usedBits)
00424 {
00425 result = -1;
00426 length = chunks(usedBits);
00427 }
00428 else
00429 {
00430 result = 0;
00431 length = chunks(usedBits);
00432 }
00433
00434 for(i=0; i<length; i++)
00435 {
00436 if(data[i] > b.data[i])
00437 {
00438 result = 1;
00439 break;
00440 }else if (data[i] < b.data[i])
00441 {
00442 result = -1;
00443 break;
00444 }
00445 }
00446 return result;
00447 }
00448
00449
00450 void CkBitVector::pup(PUP::er &p) {
00451 p|usedBits;
00452
00453 if ( usedBits == 0 ) {
00454 data = NULL;
00455 } else {
00456 if ( p.isUnpacking() ) {
00457 delete [] data;
00458 data = new prio_t[chunks(usedBits)];
00459 memset(data, 0, chunks(usedBits)*chunkSize());
00460 }
00461 p(data, chunks(usedBits));
00462 }
00463 }