MayaChemTools

   1 package BitVector;
   2 #
   3 # $RCSfile: BitVector.pm,v $
   4 # $Date: 2008/04/25 00:00:44 $
   5 # $Revision: 1.17 $
   6 #
   7 # Author: Manish Sud <msud@san.rr.com>
   8 #
   9 # Copyright (C) 2004-2008 Manish Sud. All rights reserved.
  10 #
  11 # This file is part of MayaChemTools.
  12 #
  13 # MayaChemTools is free software; you can redistribute it and/or modify it under
  14 # the terms of the GNU Lesser General Public License as published by the Free
  15 # Software Foundation; either version 3 of the License, or (at your option) any
  16 # later version.
  17 #
  18 # MayaChemTools is distributed in the hope that it will be useful, but without
  19 # any warranty; without even the implied warranty of merchantability of fitness
  20 # for a particular purpose.  See the GNU Lesser General Public License for more
  21 # details.
  22 #
  23 # You should have received a copy of the GNU Lesser General Public License
  24 # along with MayaChemTools; if not, see <http://www.gnu.org/licenses/> or
  25 # write to the Free Software Foundation Inc., 59 Temple Place, Suite 330,
  26 # Boston, MA, 02111-1307, USA.
  27 #
  28 use 5.006;
  29 use strict;
  30 use Carp;
  31 use Exporter;
  32 use Scalar::Util ();
  33 use TextUtil ();
  34 use ConversionsUtil ();
  35 use MathUtil;
  36 
  37 use vars qw($VERSION @ISA @EXPORT @EXPORT_OK %EXPORT_TAGS);
  38 
  39 $VERSION = '1.00';
  40 @ISA = qw(Exporter);
  41 @EXPORT = qw(IsBitVector);
  42 @EXPORT_OK = qw(NewFromBinaryString NewFromDecimalString NewFromHexadecimalString NewFromOctalString NewFromRawBinaryString);
  43 
  44 %EXPORT_TAGS = (all  => [@EXPORT, @EXPORT_OK]);
  45 
  46 # Setup class variables...
  47 my($ClassName, $ValueFormat, $ValueBitOrder);
  48 _InitializeClass();
  49 
  50 #
  51 # Overload bitwise and some logical operators...
  52 #
  53 # 'fallback' is set to 'false' to raise exception for all other operators.
  54 #
  55 use overload '""' => 'StringifyBitVector',
  56   '&' => '_BitVectorAndOperator',
  57   '|' => '_BitVectorOrOperator',
  58   '^' => '_BitVectorExclusiveOrOperator',
  59 
  60   '~' => '_BitVectorNegationOperator',
  61 
  62   '==' => '_BitVectorEqualOperator',
  63   '!=' => '_BitVectorNotEqualOperator',
  64 
  65   'fallback' => undef;
  66 
  67 # Class constructor...
  68 #
  69 sub new {
  70   my($Class, $Size) = @_;
  71 
  72   # Initialize object...
  73   my $This = {};
  74   bless $This, ref($Class) || $Class;
  75   $This->_InitializeBitVector($Size);
  76 
  77   return $This;
  78 }
  79 
  80 # Initialize object data...
  81 #
  82 # Note:
  83 #  . Perl pack function used to initialize vector automatically sets its size to
  84 #    nearest power of 2 value.
  85 #
  86 sub _InitializeBitVector {
  87   my($This, $Size) = @_;
  88 
  89   if (!defined $Size) {
  90     croak "Error: ${ClassName}->new: BitVector object instantiated without specifying its size ...";
  91   }
  92   if ($Size <=0) {
  93     croak "Error: ${ClassName}->new: Bit vector size, $Size, must be a positive integer...";
  94   }
  95 
  96   # Initialize vector with zeros...
  97   $This->{BitValues} = pack("b*", "0" x $Size);
  98 
  99   # Size to automatically set to nearest power of 2 by Perl pack function. So use the length
 100   # of packed vector to set size...
 101   $This->{Size} = length($This->GetBitsAsBinaryString());
 102 
 103   return $This;
 104 }
 105 
 106 # Initialize class ...
 107 sub _InitializeClass {
 108   #Class name...
 109   $ClassName = __PACKAGE__;
 110 
 111   # Print format for bit vectore values...
 112   $ValueFormat = "Binary";
 113 
 114   # Bit ordering for printing bit vector values. Default is to print LSB bit in each
 115   # byte on the right. Internally, bits are stored in ascending order using Perl vec
 116   # function and LSB bit in each byte on the left.
 117   $ValueBitOrder = 'descending';
 118 }
 119 
 120 # Create a new bit vector using binary string. This functionality can be
 121 # either invoked as a class function or an object method.
 122 #
 123 # The size of bit vector is automatically set to reflect the string.
 124 #
 125 sub NewFromBinaryString ($;$) {
 126 
 127   return _NewBitVectorFromString(@_, 'Binary');
 128 }
 129 
 130 # Create a new bit vector using hexadecimal string. This functionality can be
 131 # either invoked as a class function or an object method.
 132 #
 133 # The size of bit vector is automatically set to reflect the string.
 134 #
 135 sub NewFromHexadecimalString ($;$) {
 136 
 137   return _NewBitVectorFromString(@_, 'Hexadecimal');
 138 }
 139 
 140 # Create a new bit vector using octal string. This functionality can be
 141 # either invoked as a class function or an object method.
 142 #
 143 # The size of bit vector is automatically set to reflect the string.
 144 #
 145 sub NewFromOctalString ($) {
 146   return _NewBitVectorFromString(@_, 'Octal');
 147 }
 148 
 149 # Create a new bit vector using decimal string. This functionality can be
 150 # either invoked as a class function or an object method.
 151 #
 152 # The size of bit vector is automatically set to reflect the string.
 153 #
 154 sub NewFromDecimalString ($;$) {
 155 
 156   return _NewBitVectorFromString(@_, 'Decimal');
 157 }
 158 
 159 # Create a new bit vector using raw binary string. This functionality can be
 160 # either invoked as a class function or an object method.
 161 #
 162 # The size of bit vector is automatically set to reflect the string.
 163 #
 164 sub NewFromRawBinaryString ($;$) {
 165 
 166   return _NewBitVectorFromString(@_, 'RawBinary');
 167 }
 168 
 169 # Create a new bit vector from a string...
 170 #
 171 sub _NewBitVectorFromString ($$;$) {
 172   my($FirstParameter, $SecondParameter, $ThirdParameter) = @_;
 173   my($This, $Format, $String, $Size, $BitVector);
 174 
 175   if (@_ == 3) {
 176     ($This, $String, $Format) = ($FirstParameter, $SecondParameter, $ThirdParameter);
 177   }
 178   else {
 179     ($This, $String, $Format) = (undef, $FirstParameter, $SecondParameter);
 180   }
 181   $Size = _CalculateStringSizeInBits($Format, $String);
 182   if (defined $This) {
 183     $BitVector = (ref $This)->new($Size);
 184   }
 185   else {
 186     $BitVector = new BitVector($Size);
 187   }
 188   $BitVector->_SetBitsAsString($Format, $String);
 189 
 190   return $BitVector;
 191 }
 192 
 193 # Copy bit vector...
 194 sub Copy {
 195   my($This) = @_;
 196   my($BitVector);
 197 
 198   # Make a new bit vector...
 199   $BitVector = (ref $This)->new($This->{Size});
 200 
 201   # Copy bit values...
 202   $BitVector->{BitValues} = $This->{BitValues};
 203 
 204   # Copy value format for stringification...
 205   if (exists $This->{ValueFormat}) {
 206     $BitVector->{ValueFormat} = $This->{ValueFormat};
 207   }
 208   # Copy value bit order for stringification...
 209   if (exists $This->{ValueBitOrder}) {
 210     $BitVector->{ValueBitOrder} = $This->{ValueBitOrder};
 211   }
 212   return $BitVector;
 213 }
 214 
 215 # Reverse bit values in bit vector...
 216 sub Reverse {
 217   my($This) = @_;
 218   my($BitNum, $ReverseBitNum, $BitValue, $ReverseBitValue);
 219 
 220   $BitNum = 0; $ReverseBitNum = $This->{Size} - 1;
 221 
 222   while ($BitNum < $ReverseBitNum) {
 223     $BitValue = $This->_GetBitValue($BitNum);
 224     $ReverseBitValue = $This->_GetBitValue($ReverseBitNum);
 225 
 226     $This->_SetBitValue($BitNum, $ReverseBitValue);
 227     $This->_SetBitValue($ReverseBitNum, $BitValue);
 228 
 229     $BitNum++; $ReverseBitNum--;
 230   }
 231   return $This;
 232 }
 233 
 234 # Is it a bit vector object?
 235 sub IsBitVector ($) {
 236   my($Object) = @_;
 237 
 238   return _IsBitVector($Object);
 239 }
 240 
 241 # Get size...
 242 sub GetSize {
 243   my($This) = @_;
 244 
 245   return $This->{Size};
 246 }
 247 
 248 # Set a bit...
 249 #
 250 sub SetBit {
 251   my($This, $BitNum, $SkipCheck) = @_;
 252 
 253   # Just set it...
 254   if ($SkipCheck) {
 255     return $This->_SetBitValue($BitNum, 1);
 256   }
 257 
 258   # Check and set...
 259   $This->_ValidateBitNumber("SetBit", $BitNum);
 260 
 261   return $This->_SetBitValue($BitNum, 1);
 262 }
 263 
 264 # Set arbitrary bits specified as a list of bit numbers...
 265 #
 266 sub SetBits {
 267   my($This, @BitNums) = @_;
 268   my($BitNum);
 269 
 270   for $BitNum (@BitNums) {
 271     $This->SetBit($BitNum);
 272   }
 273   return $This;
 274 }
 275 
 276 # Set bits in a specified range...
 277 #
 278 sub SetBitsRange {
 279   my($This, $MinBitNum, $MaxBitNum) = @_;
 280   my($BitNum);
 281 
 282   $This->_ValidateBitNumber("SetBitsRange", $MinBitNum);
 283   $This->_ValidateBitNumber("SetBitsRange", $MaxBitNum);
 284 
 285   for $BitNum ($MinBitNum .. $MaxBitNum) {
 286     $This->_SetBitValue($BitNum, 1);
 287   }
 288   return $This;
 289 }
 290 
 291 # Set all bits...
 292 #
 293 sub SetAllBits {
 294   my($This) = @_;
 295 
 296   $This->{BitValues} = pack("b*", "1" x $This->{Size});
 297 }
 298 
 299 # Clear a bit...
 300 #
 301 sub ClearBit {
 302   my($This, $BitNum) = @_;
 303 
 304   $This->_ValidateBitNumber("ClearBit", $BitNum);
 305 
 306   return $This->_SetBitValue($BitNum, 0);
 307 }
 308 
 309 # Clear arbitrary bits specified as a list of bit numbers...
 310 #
 311 sub ClearBits {
 312   my($This, @BitNums) = @_;
 313   my($BitNum);
 314 
 315   for $BitNum (@BitNums) {
 316     $This->ClearBit($BitNum);
 317   }
 318   return $This;
 319 }
 320 
 321 # Clear bits in a specified range...
 322 #
 323 sub ClearBitsRange {
 324   my($This, $MinBitNum, $MaxBitNum) = @_;
 325   my($BitNum);
 326 
 327   $This->_ValidateBitNumber("ClearBitsRange", $MinBitNum);
 328   $This->_ValidateBitNumber("ClearBitsRange", $MaxBitNum);
 329 
 330   for $BitNum ($MinBitNum .. $MaxBitNum) {
 331     $This->_SetBitValue($BitNum, 0);
 332   }
 333   return $This;
 334 }
 335 
 336 # Clear all bits...
 337 #
 338 sub ClearAllBits {
 339   my($This) = @_;
 340 
 341   $This->{BitValues} = pack("b*", "0" x $This->{Size});
 342 
 343   return $This;
 344 }
 345 
 346 # Set or clear bit...
 347 #
 348 sub SetBitValue {
 349   my($This, $BitNum, $BitValue) = @_;
 350 
 351  BITVALUE: {
 352     if ($BitValue == 1) { return $This->SetBit($BitNum); last BITVALUE; }
 353     if ($BitValue == 0) { return $This->ClearBit($BitNum); last BITVALUE; }
 354     croak "Error: ${ClassName}->SetBit: Specified bit value, $BitValue, must be 0 or 1...";
 355   }
 356   return $This;
 357 }
 358 
 359 # Flip bit value...
 360 #
 361 sub FlipBit {
 362   my($This, $BitNum) = @_;
 363 
 364   $This->_ValidateBitNumber("FlipBit", $BitNum);
 365   return $This->_FlipBit($BitNum);
 366 }
 367 
 368 # Flip arbitrary bits specified as a list of bit numbers...
 369 #
 370 sub FlipBits {
 371   my($This, @BitNums) = @_;
 372   my($BitNum);
 373 
 374   for $BitNum (@BitNums) {
 375     $This->FlipBit();
 376   }
 377   return $This;
 378 }
 379 
 380 # Flip bit value in a specified bit range...
 381 #
 382 sub FlipBitsRange {
 383   my($This, $MinBitNum, $MaxBitNum) = @_;
 384   my($BitNum);
 385 
 386   $This->_ValidateBitNumber("FlipBitsRange", $MinBitNum);
 387   $This->_ValidateBitNumber("FlipBitsRange", $MaxBitNum);
 388 
 389   for $BitNum ($MinBitNum .. $MaxBitNum) {
 390     $This->_FlipBit();
 391   }
 392   return $This;
 393 }
 394 
 395 # Flip all bit valus...
 396 #
 397 sub FlipAllBits {
 398   my($This) = @_;
 399 
 400   return $This->FlipBits(0, ($This->{Size} - 1));
 401 }
 402 
 403 # Flip bit value...
 404 sub _FlipBit {
 405   my($This, $BitNum) = @_;
 406 
 407   if ($This->_GetBitValue($BitNum)) {
 408     return $This->_SetBitValue($BitNum, 0);
 409   }
 410   else {
 411     return $This->_SetBitValue($BitNum, 1);
 412   }
 413 }
 414 
 415 # Get bit value...
 416 #
 417 sub GetBit {
 418   my($This, $BitNum) = @_;
 419 
 420   $This->_ValidateBitNumber("GetBit", $BitNum);
 421 
 422   return $This->_GetBitValue($BitNum);
 423 }
 424 
 425 # Is a specific bit set?
 426 #
 427 sub IsBitSet {
 428   my($This, $BitNum) = @_;
 429 
 430   if (!(defined($BitNum) && ($BitNum >= 0) && ($BitNum < $This->{Size}))) {
 431     return undef;
 432   }
 433 
 434   return $This->_GetBitValue($BitNum) ? 1 : 0;
 435 }
 436 
 437 # Is a specific bit clear?
 438 #
 439 sub IsBitClear {
 440   my($This, $BitNum) = @_;
 441 
 442   if (!(defined($BitNum) && ($BitNum >= 0) && ($BitNum < $This->{Size}))) {
 443     return undef;
 444   }
 445 
 446   return $This->_GetBitValue($BitNum) ? 0 : 1;
 447 }
 448 
 449 # Get number of set bits...
 450 #
 451 sub GetNumOfSetBits {
 452   my($This) = @_;
 453 
 454   return unpack("%b*", $This->{BitValues});
 455 }
 456 
 457 # Get number of clear bits...
 458 #
 459 sub GetNumOfClearBits {
 460   my($This) = @_;
 461 
 462   return ($This->{Size} - $This->GetNumOfSetBits());
 463 }
 464 
 465 # Get density of set bits...
 466 #
 467 sub GetDensityOfSetBits {
 468   my($This) = @_;
 469 
 470   return $This->GetNumOfSetBits()/$This->{Size};
 471 }
 472 
 473 # Get density of clear bits...
 474 #
 475 sub GetDensityOfClearBits {
 476   my($This) = @_;
 477 
 478   return $This->GetNumOfClearBits()/$This->{Size};
 479 }
 480 
 481 # Convert internal bit values stored using Perl vec function with least significat bit and
 482 # least significant byte on the left into a binary string with least significant bit
 483 # and least significant byte on the right.
 484 #
 485 sub GetBitsAsBinaryString {
 486   my($This) = @_;
 487 
 488   return $This->_GetBitsAsString('Binary', 'Descending');
 489 }
 490 
 491 # Convert internal bit values stored using Perl vec function with least significat bit and
 492 # least significant byte on the left into a hexadecimal string with least significant bit
 493 # and least significant byte on the right.
 494 #
 495 sub GetBitsAsHexadecimalString {
 496   my($This) = @_;
 497 
 498   return $This->_GetBitsAsString('Hexadecimal', 'Descending');
 499 }
 500 
 501 # Convert bit values into a octal string value...
 502 #
 503 sub GetBitsAsOctalString {
 504   my($This) = @_;
 505 
 506   return $This->_GetBitsAsString('Octal', 'Descending');
 507 }
 508 
 509 # Convert bit values into a decimal string value...
 510 #
 511 sub GetBitsAsDecimalString {
 512   my($This) = @_;
 513 
 514   return $This->_GetBitsAsString('Decimal', 'Descending');
 515 }
 516 
 517 # Return packed bit values which also contains nonprintable characters...
 518 #
 519 sub GetBitsAsRawBinaryString {
 520   my($This) = @_;
 521 
 522   return $This->_GetBitsAsString('RawBinary');
 523 }
 524 
 525 # Convert internal bit values stored using Perl vec function with least significat bit and
 526 # least significant byte on the left into a specified string format with least significant bit
 527 # and least significant byte on the right.
 528 #
 529 sub _GetBitsAsString {
 530   my($This, $Format, $BitOrder) = @_;
 531   my($BinaryTemplate, $HexadecimalTemplate);
 532 
 533   ($BinaryTemplate, $HexadecimalTemplate) = $This->_SetupBitsPackUnpackTemplate($BitOrder);
 534 
 535   FORMAT : {
 536     if ($Format =~ /^(Hexadecimal|Hex)$/i) { return unpack($HexadecimalTemplate, $This->{BitValues}); last FORMAT; }
 537     if ($Format =~ /^(Octal|Oct)$/i) { return ConversionsUtil::HexadecimalToOctal(unpack($HexadecimalTemplate, $This->{BitValues})); last FORMAT; }
 538     if ($Format =~ /^(Decimal|Dec)$/i) { return ConversionsUtil::HexadecimalToDecimal(unpack($HexadecimalTemplate, $This->{BitValues})); last FORMAT; }
 539     if ($Format =~ /^(Binary|Bin)$/i) { return unpack($BinaryTemplate, $This->{BitValues}); last FORMAT; }
 540     if ($Format =~ /^(RawBinary|RawBin)$/i) { return $This->{BitValues}; last FORMAT; }
 541     croak "Error: ${ClassName}->_GetBitsAsString: Specified bit vector string format, $Format, is not supported. Value values: Binary, Bin, Hexdecimal, Hex, Decimal, Dec, Octal, Oct, RawBinary, RawBin...";
 542   }
 543 }
 544 
 545 # Setup templates to unpack bits...
 546 #
 547 sub _SetupBitsPackUnpackTemplate {
 548   my($This, $BitOrder) = @_;
 549   my($BinaryTemplate, $HexadecimalTemplate);
 550 
 551   $BitOrder = (defined($BitOrder) && $BitOrder) ? $BitOrder : 'Descending';
 552 
 553   if ($BitOrder =~ /^Ascending$/i) {
 554     $BinaryTemplate = "b*";
 555     $HexadecimalTemplate = "h*";
 556   }
 557   else {
 558     $BinaryTemplate = "B*";
 559     $HexadecimalTemplate = "H*";
 560   }
 561   return ($BinaryTemplate, $HexadecimalTemplate);
 562 }
 563 
 564 # Set bit values using hexadecimal string. The initial size of bit vector is not changed.
 565 #
 566 sub SetBitsAsHexadecimalString {
 567   my($This, $Hexadecimal) = @_;
 568 
 569   if ($Hexadecimal =~ /^0x/i) {
 570     $Hexadecimal =~ s/^0x//i;
 571   }
 572   return $This->_SetBitsAsString('Hexadecimal', $Hexadecimal);
 573 }
 574 
 575 # Set bit values using octal string. The initial size of bit vector is not changed.
 576 #
 577 sub SetBitsAsOctalString {
 578   my($This, $Octal) = @_;
 579 
 580   if ($Octal =~ /^0/i) {
 581     $Octal =~ s/^0//i;
 582   }
 583   return $This->_SetBitsAsString('Octal', $Octal);
 584 }
 585 
 586 # Set bit values using a decimal number. The initial size of bit vector is not changed.
 587 #
 588 sub SetBitsAsDecimalString {
 589   my($This, $Decimal) = @_;
 590 
 591   if (!TextUtil::IsPositiveInteger($Decimal)) {
 592     croak "Error: ${ClassName}->SetBitsAsDecimalString: Specified decimal value, $Decimal, must be a positive integer...";
 593   }
 594   if ($Decimal =~ /[+]/) {
 595     $Decimal =~ s/[+]//;
 596   }
 597   return $This->_SetBitsAsString('Decimal', $Decimal);
 598 }
 599 
 600 # Set bit values using hexadecimal string. The initial size of bit vector is not changed.
 601 #
 602 sub SetBitsAsBinaryString {
 603   my($This, $Binary) = @_;
 604 
 605   if ($Binary =~ /^0b/i) {
 606     $Binary =~ s/^0b//i;
 607   }
 608   return $This->_SetBitsAsString('Binary', $Binary);
 609 }
 610 
 611 # Set bit values using packed binary string. The size of bit vector is changed to reflect
 612 # the input raw string...
 613 #
 614 sub SetBitsAsRawBinaryString {
 615   my($This, $RawBinary) = @_;
 616 
 617   return $This->_SetBitsAsString('RawBinary', $RawBinary);
 618 }
 619 
 620 # Set bits using string in a specified format. This size of bit vector is not changed except for
 621 # RawBinary string type...
 622 #
 623 sub _SetBitsAsString {
 624   my($This, $Format, $String) = @_;
 625   my($Size, $BinaryTemplate, $HexadecimalTemplate);
 626 
 627   ($BinaryTemplate, $HexadecimalTemplate) = $This->_SetupBitsPackUnpackTemplate();
 628 
 629   $Size = $This->{Size};
 630   FORMAT : {
 631     if ($Format =~ /^(Hexadecimal|Hex)$/i) { $This->{BitValues} = pack($HexadecimalTemplate, $String); last FORMAT; }
 632     if ($Format =~ /^(Octal|Oct)$/i) { vec($This->{BitValues}, 0, $Size) = ConversionsUtil::OctalToDecimal($String); last FORMAT; }
 633     if ($Format =~ /^(Decimal|Dec)$/i) { vec($This->{BitValues}, 0, $Size) = $String; last FORMAT; }
 634     if ($Format =~ /^(Binary|Bin)$/i) { $This->{BitValues} = pack($BinaryTemplate, $String); last FORMAT; }
 635     if ($Format =~ /^(RawBinary|RawBin)$/i) { $This->{BitValues} = $String; last FORMAT; }
 636     croak "Error: ${ClassName}->_SetBitsAsString: Specified bit vector string format, $Format, is not supported. Value values: Binary, Bin, Hexdecimal, Hex, Decimal, Dec, RawBinary, RawBin...";
 637   }
 638 
 639   # Set size using packed string...
 640   $Size = length($This->GetBitsAsBinaryString());
 641   if ($Size <=0) {
 642     croak "Error: ${ClassName}->_SetBitsAsString: Bit vector size, $Size, must be a positive integer...";
 643   }
 644   $This->{Size} = $Size;
 645 
 646   return $This;
 647 }
 648 
 649 # Calculate string size in bits...
 650 #
 651 sub _CalculateStringSizeInBits ($$;$) {
 652   my($FirstParameter, $SecondParameter, $ThisParameter) = @_;
 653   my($This, $Format, $String, $Size);
 654 
 655   if ((@_ == 3) && (_IsBitVector($FirstParameter))) {
 656     ($This, $Format, $String) = ($FirstParameter, $SecondParameter, $ThisParameter);
 657   }
 658   else {
 659     ($This, $Format, $String) = (undef, $FirstParameter, $SecondParameter);
 660   }
 661 
 662   FORMAT : {
 663     if ($Format =~ /^(Hexadecimal|Hex)$/i) { $Size = length($String) * 4; last FORMAT; }
 664     if ($Format =~ /^(Octal|Oct)$/i) { $Size = length($String) * 3; last FORMAT; }
 665     if ($Format =~ /^(Decimal|Dec)$/i) { $Size = length(ConversionsUtil::DecimalToHexadecimal($String)) * 4; last FORMAT; }
 666     if ($Format =~ /^(Binary|Bin)$/i) { $Size = length($String); last FORMAT; }
 667     if ($Format =~ /^(RawBinary|RawBin)$/i) { $Size = length(unpack("B*", $String)); last FORMAT; }
 668     croak "Error: ${ClassName}::_CalculateStringSizeInBits: Specified bit vector string format, $Format, is not supported. Value values: Binary, Bin, Hexdecimal, Hex, Decimal, Dec, RawBinary, RawBin...";
 669   }
 670   return $Size;
 671 }
 672 
 673 # Set bit value using Perl vec function with bit numbers going from left to right.
 674 # First bit number corresponds to 0.
 675 #
 676 sub _SetBitValue {
 677   my($This, $BitNum, $BitValue) = @_;
 678   my($Offset, $Width);
 679 
 680   $Offset = $BitNum;
 681   $Width = 1;
 682 
 683   vec($This->{BitValues}, $Offset, $Width) = $BitValue;
 684 
 685   return $This;
 686 }
 687 
 688 # Get bit value Perl vec function with bit numbers going from left to right.
 689 # First bit number corresponds to 0.
 690 #
 691 sub _GetBitValue {
 692   my($This, $BitNum) = @_;
 693   my($Offset, $Width, $BitValue);
 694 
 695   $Offset = $BitNum;
 696   $Width = 1;
 697 
 698   $BitValue = vec($This->{BitValues}, $Offset, $Width);
 699 
 700   return $BitValue;
 701 }
 702 
 703 # Check to make sure it's a valid bit number...
 704 #
 705 sub _ValidateBitNumber {
 706   my($This, $CallerName, $BitNum) = @_;
 707 
 708   if (!defined $BitNum) {
 709     croak "Error: ${ClassName}->${CallerName}: Bit number is not defined...";
 710   }
 711   if ($BitNum < 0) {
 712     croak "Error: ${ClassName}->${CallerName}: Bit number value, $BitNum, must be >= 0 ...";
 713   }
 714   if ($BitNum >= $This->{Size}) {
 715     croak "Error: ${ClassName}->${CallerName}: Bit number number value, $BitNum, must be less than the size of bit vector, ", $This->{Size}, "...";
 716   }
 717 
 718   return $This;
 719 }
 720 
 721 # Set bit values print format for an individual object or the whole class...
 722 #
 723 sub SetBitValuePrintFormat ($;$) {
 724   my($FirstParameter, $SecondParameter) = @_;
 725 
 726   if ((@_ == 2) && (_IsBitVector($FirstParameter))) {
 727     # Set bit values print format for the specific object...
 728     my($This, $ValuePrintFormat) = ($FirstParameter, $SecondParameter);
 729 
 730     if (!_ValidateBitValuePrintFormat($ValuePrintFormat)) {
 731       return;
 732     }
 733 
 734     $This->{ValueFormat} = $ValuePrintFormat;
 735   }
 736   else {
 737     # Set value print format for the class...
 738     my($ValuePrintFormat) = ($FirstParameter);
 739 
 740     if (!_ValidateBitValuePrintFormat($ValuePrintFormat)) {
 741       return;
 742     }
 743 
 744     $ValueFormat = $ValuePrintFormat;
 745   }
 746 }
 747 
 748 # Set bit values bit order for an individual object or the whole class...
 749 #
 750 sub SetBitValueBitOrder ($;$) {
 751   my($FirstParameter, $SecondParameter) = @_;
 752 
 753   if ((@_ == 2) && (_IsBitVector($FirstParameter))) {
 754     # Set bit value bit order for the specific object...
 755     my($This, $BitOrder) = ($FirstParameter, $SecondParameter);
 756 
 757     if (!_ValidateBitValueBitOrder($BitOrder)) {
 758       return;
 759     }
 760 
 761     $This->{ValueBitOrder} = $BitOrder;
 762   }
 763   else {
 764     # Set bit value bit order for the class...
 765     my($BitOrder) = ($FirstParameter);
 766 
 767     if (!_ValidateBitValueBitOrder($BitOrder)) {
 768       return;
 769     }
 770 
 771     $ValueBitOrder = $BitOrder;
 772   }
 773 }
 774 
 775 # Validate print format for bit values...
 776 sub _ValidateBitValueBitOrder {
 777   my($BitOrder) = @_;
 778 
 779   if ($BitOrder !~ /^(Ascending|Descending)$/i) {
 780     carp "Warning: ${ClassName}::_ValidateBitValueBitOrder: Specified bit order value, $BitOrder, is not supported. Supported values: Ascending, Descending...";
 781     return 0;
 782   }
 783   return 1;
 784 }
 785 
 786 # Validate print format for bit values...
 787 sub _ValidateBitValuePrintFormat {
 788   my($ValuePrintFormat) = @_;
 789 
 790   if ($ValuePrintFormat !~ /^(Binary|Bin|Hexadecimal|Hex|Decimal|Dec|Octal|Oct|RawBinary|RawBin)$/i) {
 791     carp "Warning: ${ClassName}::_ValidateBitValuePrintFormat: Specified bit vector print format value, $ValuePrintFormat, is not supported. Supported values: Binary, Bin, Hexdecimal, Hex, Decimal, Dec, Octal, Oct, RawBinary, RawBin...";
 792     return 0;
 793   }
 794   return 1;
 795 }
 796 
 797 # Bitwise AND operation for BitVectors...
 798 #
 799 sub _BitVectorAndOperator {
 800   my($This, $Other, $OrderFlipped, $OtherIsBitVector, $ErrorMsg, $CheckBitVectorSizes);
 801 
 802   $ErrorMsg = "_BitVectorAndOperator: Bitwise AND oparation failed";
 803   $CheckBitVectorSizes = 1;
 804   ($This, $Other, $OrderFlipped, $OtherIsBitVector) = _ProcessOverloadedOperatorParameters($ErrorMsg, @_, $CheckBitVectorSizes);
 805 
 806   if (!$OtherIsBitVector) {
 807     if ($OrderFlipped) {
 808       croak "Error: ${ClassName}->${ErrorMsg}: First object must be a bit vector...";
 809     }
 810   }
 811   my($BitVector);
 812   $BitVector = (ref $This)->new($This->{Size});
 813   $BitVector->{BitValues} = $This->{BitValues} & $Other->{BitValues};
 814 
 815   return $BitVector;
 816 }
 817 
 818 # Bitwise OR operation for BitVectors...
 819 #
 820 sub _BitVectorOrOperator {
 821   my($This, $Other, $OrderFlipped, $OtherIsBitVector, $ErrorMsg, $CheckBitVectorSizes);
 822 
 823   $ErrorMsg = "_BitVectorAndOperator: Bitwise OR oparation failed";
 824   $CheckBitVectorSizes = 1;
 825   ($This, $Other, $OrderFlipped, $OtherIsBitVector) = _ProcessOverloadedOperatorParameters($ErrorMsg, @_, $CheckBitVectorSizes);
 826 
 827   if (!$OtherIsBitVector) {
 828     if ($OrderFlipped) {
 829       croak "Error: ${ClassName}->${ErrorMsg}: First object must be a bit vector...";
 830     }
 831   }
 832   my($BitVector);
 833   $BitVector = (ref $This)->new($This->{Size});
 834   $BitVector->{BitValues} = $This->{BitValues} | $Other->{BitValues};
 835 
 836   return $BitVector;
 837 }
 838 
 839 # Bitwise XOR operation for BitVectors...
 840 #
 841 sub _BitVectorExclusiveOrOperator {
 842   my($This, $Other, $OrderFlipped, $OtherIsBitVector, $ErrorMsg, $CheckBitVectorSizes);
 843 
 844   $ErrorMsg = "_BitVectorAndOperator: Bitwise XOR oparation failed";
 845   $CheckBitVectorSizes = 1;
 846   ($This, $Other, $OrderFlipped, $OtherIsBitVector) = _ProcessOverloadedOperatorParameters($ErrorMsg, @_, $CheckBitVectorSizes);
 847 
 848   if (!$OtherIsBitVector) {
 849     if ($OrderFlipped) {
 850       croak "Error: ${ClassName}->${ErrorMsg}: First object must be a bit vector...";
 851     }
 852   }
 853   my($BitVector);
 854   $BitVector = (ref $This)->new($This->{Size});
 855   $BitVector->{BitValues} = $This->{BitValues} ^ $Other->{BitValues};
 856 
 857   return $BitVector;
 858 }
 859 
 860 # Bitwise negation operation for BitVectors...
 861 #
 862 sub _BitVectorNegationOperator {
 863   my($This, $Other, $OrderFlipped, $OtherIsBitVector, $ErrorMsg, $CheckBitVectorSizes);
 864 
 865   $ErrorMsg = "_BitVectorAndOperator: Bitwise negation oparation failed";
 866   $CheckBitVectorSizes = 1;
 867   ($This, $Other, $OrderFlipped, $OtherIsBitVector) = _ProcessOverloadedOperatorParameters($ErrorMsg, @_, $CheckBitVectorSizes);
 868 
 869   my($BitVector);
 870   $BitVector = (ref $This)->new($This->{Size});
 871   $BitVector->{BitValues} = ~ $This->{BitValues};
 872 
 873   return $BitVector;
 874 }
 875 
 876 # Bit vector equla operator. Two bit vectors are considered equal assuming their size
 877 # is same and bits are on at the same positions...
 878 #
 879 sub _BitVectorEqualOperator {
 880   my($This, $Other, $OrderFlipped, $OtherIsBitVector, $ErrorMsg, $CheckBitVectorSizes);
 881 
 882   $ErrorMsg = "_BitVectorEqualOperator: BitVector == oparation failed";
 883   $CheckBitVectorSizes = 0;
 884   ($This, $Other, $OrderFlipped, $OtherIsBitVector) = _ProcessOverloadedOperatorParameters($ErrorMsg, @_, $CheckBitVectorSizes);
 885 
 886   if (!$OtherIsBitVector) {
 887     if ($OrderFlipped) {
 888       croak "Error: ${ClassName}->${ErrorMsg}: First object must be a bit vector...";
 889     }
 890   }
 891   if ($This->GetSize() != $Other->GetSize()) {
 892     return 0;
 893   }
 894   if ($This->GetNumOfSetBits() != $Other->GetNumOfSetBits()) {
 895     return 0;
 896   }
 897   # Check number of On bits only in This vector. It must be zero for vectors to be equal...
 898   my($BitVector);
 899   $BitVector = $This & ~$Other;
 900 
 901   return $BitVector->GetNumOfSetBits() ? 0 : 1;
 902 }
 903 
 904 # Bit vector not equal operator. Two bit vectors are considered not equal when their size
 905 # is different or bits are on at the same positions...
 906 #
 907 sub _BitVectorNotEqualOperator {
 908   my($This, $Other, $OrderFlipped, $OtherIsBitVector, $ErrorMsg, $CheckBitVectorSizes);
 909 
 910   $ErrorMsg = "_BitVectorEqualOperator: BitVector != oparation failed";
 911   $CheckBitVectorSizes = 0;
 912   ($This, $Other, $OrderFlipped, $OtherIsBitVector) = _ProcessOverloadedOperatorParameters($ErrorMsg, @_, $CheckBitVectorSizes);
 913 
 914   if (!$OtherIsBitVector) {
 915     if ($OrderFlipped) {
 916       croak "Error: ${ClassName}->${ErrorMsg}: First object must be a bit vector...";
 917     }
 918   }
 919   if ($This->GetSize() != $Other->GetSize()) {
 920     return 1;
 921   }
 922   if ($This->GetNumOfSetBits() != $Other->GetNumOfSetBits()) {
 923     return 1;
 924   }
 925   # Check number of On bits only in This vector. It must be zero for vectors to be equal...
 926   my($BitVector);
 927   $BitVector = $This & ~$Other;
 928 
 929   return $BitVector->GetNumOfSetBits() ? 1 : 0;
 930 }
 931 
 932 # Process parameters passed to overloaded operators...
 933 #
 934 # For uninary operators, $SecondParameter is not defined.
 935 sub _ProcessOverloadedOperatorParameters {
 936   my($ErrorMsg, $FirstParameter, $SecondParameter, $ParametersOrderStatus, $CheckBitVectorSizesStatus) = @_;
 937   my($This, $Other, $OrderFlipped, $OtherIsBitVector, $CheckBitVectorSizes);
 938 
 939   ($This, $Other) =  ($FirstParameter, $SecondParameter);
 940   $OrderFlipped = (defined($ParametersOrderStatus) && $ParametersOrderStatus) ? 1 : 0;
 941   $CheckBitVectorSizes = (defined $CheckBitVectorSizesStatus) ? $CheckBitVectorSizesStatus : 1;
 942 
 943   _ValidateBitVector($ErrorMsg, $This);
 944 
 945   $OtherIsBitVector = 0;
 946   if (defined($Other) && (ref $Other)) {
 947     # Make sure $Other is a vector...
 948     _ValidateBitVector($ErrorMsg, $Other);
 949     if ($CheckBitVectorSizes) {
 950       _ValidateBitVectorSizesAreEqual($ErrorMsg, $This, $Other);
 951     }
 952     $OtherIsBitVector = 1;
 953   }
 954   return ($This, $Other, $OrderFlipped, $OtherIsBitVector);
 955 }
 956 
 957 # Is it a bit vector object?
 958 sub _IsBitVector {
 959   my($Object) = @_;
 960 
 961   return (Scalar::Util::blessed($Object) && $Object->isa($ClassName)) ? 1 : 0;
 962 }
 963 
 964 # Make sure it's a bit vector reference...
 965 sub _ValidateBitVector {
 966   my($ErrorMsg, $Vector) = @_;
 967 
 968   if (!_IsBitVector($Vector)) {
 969     croak "Error: ${ClassName}->${ErrorMsg}: Object must be a bit vector...";
 970   }
 971 }
 972 
 973 # Make sure size of the two bit vectors are equal...
 974 sub _ValidateBitVectorSizesAreEqual {
 975   my($ErrorMsg, $BitVector1, $BitVector2) = @_;
 976 
 977   if ($BitVector1->GetSize() != $BitVector2->GetSize()) {
 978     croak "Error: ${ClassName}->${ErrorMsg}: Size of the bit vectors must be same...";
 979   }
 980 }
 981 
 982 # Return a string containing vector values...
 983 sub StringifyBitVector {
 984   my($This) = @_;
 985   my($BitVectorString, $PrintFormat, $BitOrder, $BitsValue);
 986 
 987   $PrintFormat = (exists $This->{ValueFormat}) ? $This->{ValueFormat} : $ValueFormat;
 988   $BitOrder = (exists $This->{ValueBitOrder}) ? $This->{ValueBitOrder} : $ValueBitOrder;
 989   $BitVectorString = '';
 990 
 991   FORMAT: {
 992       if ($PrintFormat =~ /^(Hexadecimal|Hex)$/i) { $BitsValue = $This->_GetBitsAsString('Hexadecimal', $BitOrder);  last FORMAT; }
 993       if ($PrintFormat =~ /^(Octal|Oct)$/i) { $BitsValue = $This->_GetBitsAsString('Octal', $BitOrder);  last FORMAT; }
 994       if ($PrintFormat =~ /^(Decimal|Dec)$/i) { $BitsValue = $This->_GetBitsAsString('Decimal', $BitOrder);  last FORMAT; }
 995       if ($PrintFormat =~ /^(RawBinary|RawBin)$/i) { $BitsValue = $This->_GetBitsAsString('RawBinary');  last FORMAT; }
 996       # Default is bninary format...
 997       $BitsValue = $This->_GetBitsAsString('Binary', $BitOrder);
 998   }
 999   $BitVectorString = "<Size: ". $This->GetSize() . "; Value: " . $BitsValue . ">";
1000 
1001   return $BitVectorString;
1002 }
1003