1 /** 2 * This module contains a packed bit array implementation in the style of D's 3 * built-in dynamic arrays. 4 * 5 * Copyright: Copyright (%C) 2005-2006 Digital Mars, www.digitalmars.com. 6 * All rights reserved. 7 * License: BSD style: $(LICENSE) 8 * Authors: Walter Bright, Sean Kelly 9 */ 10 module tango.core.BitArray; 11 12 import tango.io.Stdout; 13 14 private import tango.core.BitManip; 15 16 17 /** 18 * This struct represents an array of boolean values, each of which occupy one 19 * bit of memory for storage. Thus an array of 32 bits would occupy the same 20 * space as one integer value. The typical array operations--such as indexing 21 * and sorting--are supported, as well as bitwise operations such as and, or, 22 * xor, and complement. 23 */ 24 struct BitArray 25 { 26 size_t len; 27 size_t* ptr; 28 enum bits_in_size=(size_t.sizeof*8); 29 30 /** 31 * This initializes a BitArray of bits.length bits, where each bit value 32 * matches the corresponding boolean value in bits. 33 * 34 * Params: 35 * bits = The initialization value. 36 * 37 * Returns: 38 * A BitArray with the same number and sequence of elements as bits. 39 */ 40 /*static BitArray opCall( bool[] bits ) 41 { 42 BitArray temp; 43 44 temp.length = bits.length; 45 foreach( pos, val; bits ) 46 temp[pos] = val; 47 return temp; 48 }*/ 49 this(size_t _len, size_t* _ptr) pure 50 { 51 len = _len; 52 ptr = _ptr; 53 } 54 55 this(const bool[] bits) pure 56 { 57 this.length = bits.length; 58 foreach( pos, val; bits ) 59 this[pos] = val; 60 } 61 62 /** 63 * Get the number of bits in this array. 64 * 65 * Returns: 66 * The number of bits in this array. 67 */ 68 @property const size_t length() pure 69 { 70 return len; 71 } 72 73 74 /** 75 * Resizes this array to newlen bits. If newlen is larger than the current 76 * length, the new bits will be initialized to zero. 77 * 78 * Params: 79 * newlen = The number of bits this array should contain. 80 */ 81 @property void length(const size_t newlen ) pure 82 { 83 if( newlen != len ) 84 { 85 auto olddim = dim(); 86 auto newdim = (newlen + (bits_in_size-1)) / bits_in_size; 87 88 if( newdim != olddim ) 89 { 90 // Create a fake array so we can use D's realloc machinery 91 size_t[] buf = ptr[0 .. olddim]; 92 93 buf.length = newdim; // realloc 94 ptr = buf.ptr; 95 if( newdim & (bits_in_size-1) ) 96 { 97 // Set any pad bits to 0 98 ptr[newdim - 1] &= ~(~0 << (newdim & (bits_in_size-1))); 99 } 100 } 101 len = newlen; 102 } 103 } 104 105 106 /** 107 * Gets the length of a size_t array large enough to hold all stored bits. 108 * 109 * Returns: 110 * The size a size_t array would have to be to store this array. 111 */ 112 @property size_t dim() const pure 113 { 114 return (len + (bits_in_size-1)) / bits_in_size; 115 } 116 117 118 /** 119 * Duplicates this array, much like the dup property for built-in arrays. 120 * 121 * Returns: 122 * A duplicate of this array. 123 */ 124 @property BitArray dup() const 125 { 126 BitArray ba; 127 128 size_t[] buf = ptr[0 .. dim].dup; 129 ba.len = len; 130 ba.ptr = buf.ptr; 131 return ba; 132 } 133 134 135 debug( UnitTest ) 136 { 137 unittest 138 { 139 BitArray a; 140 BitArray b; 141 142 a.length = 3; 143 a[0] = 1; a[1] = 0; a[2] = 1; 144 b = a.dup; 145 assert( b.length == 3 ); 146 for( int i = 0; i < 3; ++i ) 147 { 148 assert( b[i] == (((i ^ 1) & 1) ? true : false) ); 149 } 150 } 151 } 152 153 154 /** 155 * Resets the length of this array to bits.length and then initializes this 156 * 157 * Resizes this array to hold bits.length bits and initializes each bit 158 * value to match the corresponding boolean value in bits. 159 * 160 * Params: 161 * bits = The initialization value. 162 */ 163 164 this(this) 165 { 166 ptr = ptr; 167 len = len; 168 } 169 void opAssign( bool[] bits ) 170 { 171 length = bits.length; 172 foreach( i, b; bits ) 173 { 174 (this)[i] = b; 175 } 176 } 177 178 /** 179 * Copy the bits from one array into this array. This is not a shallow 180 * copy. 181 * 182 * Params: 183 * rhs = A BitArray with at least the same number of bits as this bit 184 * array. 185 * 186 * Returns: 187 * A shallow copy of this array. 188 * 189 * -------------------- 190 * BitArray ba = [0,1,0,1,0]; 191 * BitArray ba2; 192 * ba2.length = ba.length; 193 * ba2[] = ba; // perform the copy 194 * ba[0] = true; 195 * assert(ba2[0] == false); 196 * -------------------- 197 */ 198 BitArray opSliceAssign(BitArray rhs) 199 in 200 { 201 assert(rhs.len == len); 202 } 203 body 204 { 205 size_t mDim=len/bits_in_size; 206 ptr[0..mDim] = rhs.ptr[0..mDim]; 207 int rest=cast(int)(len & cast(size_t)(bits_in_size-1)); 208 if (rest){ 209 size_t mask=(~0u)<<rest; 210 ptr[mDim]=(rhs.ptr[mDim] & (~mask))|(ptr[mDim] & mask); 211 } 212 return this; 213 } 214 215 216 /** 217 * Map BitArray onto target, with numbits being the number of bits in the 218 * array. Does not copy the data. This is the inverse of opCast. 219 * 220 * Params: 221 * target = The array to map. 222 * numbits = The number of bits to map in target. 223 */ 224 void init( void[] target, size_t numbits ) 225 in 226 { 227 assert( numbits <= target.length * 8 ); 228 assert( (target.length & 3) == 0 ); 229 } 230 body 231 { 232 ptr = cast(size_t*)target.ptr; 233 len = numbits; 234 } 235 236 237 debug( UnitTest ) 238 { 239 unittest 240 { 241 BitArray a = [1,0,1,0,1]; 242 BitArray b; 243 void[] buf; 244 245 buf = cast(void[])a; 246 b.init( buf, a.length ); 247 248 assert( b[0] == 1 ); 249 assert( b[1] == 0 ); 250 assert( b[2] == 1 ); 251 assert( b[3] == 0 ); 252 assert( b[4] == 1 ); 253 254 a[0] = 0; 255 assert( b[0] == 0 ); 256 257 assert( a == b ); 258 259 // test opSliceAssign 260 BitArray c; 261 c.length = a.length; 262 c[] = a; 263 assert( c == a ); 264 a[0] = 1; 265 assert( c != a ); 266 } 267 } 268 269 270 /** 271 * Reverses the contents of this array in place, much like the reverse 272 * property for built-in arrays. 273 * 274 * Returns: 275 * A shallow copy of this array. 276 */ 277 @property ref BitArray reverse() 278 out( result ) 279 { 280 assert( result == this ); 281 } 282 body 283 { 284 if( len >= 2 ) 285 { 286 bool t; 287 size_t lo, hi; 288 289 lo = 0; 290 hi = len - 1; 291 for( ; lo < hi; ++lo, --hi ) 292 { 293 t = (this)[lo]; 294 (this)[lo] = (this)[hi]; 295 (this)[hi] = t; 296 } 297 } 298 return this; 299 } 300 301 302 debug( UnitTest ) 303 { 304 unittest 305 { 306 static bool[5] data = [1,0,1,1,0]; 307 BitArray b = data; 308 b.reverse; 309 310 for( size_t i = 0; i < data.length; ++i ) 311 { 312 assert( b[i] == data[4 - i] ); 313 } 314 } 315 } 316 317 318 /** 319 * Sorts this array in place, with zero entries sorting before one. This 320 * is equivalent to the sort property for built-in arrays. 321 * 322 * Returns: 323 * A shallow copy of this array. 324 */ 325 @property ref BitArray sort() 326 out( result ) 327 { 328 assert( result == this ); 329 } 330 body 331 { 332 if( len >= 2 ) 333 { 334 size_t lo, hi; 335 336 lo = 0; 337 hi = len - 1; 338 while( true ) 339 { 340 while( true ) 341 { 342 if( lo >= hi ) 343 goto Ldone; 344 if( (this)[lo] == true ) 345 break; 346 ++lo; 347 } 348 349 while( true ) 350 { 351 if( lo >= hi ) 352 goto Ldone; 353 if( (this)[hi] == false ) 354 break; 355 --hi; 356 } 357 358 (this)[lo] = false; 359 (this)[hi] = true; 360 361 ++lo; 362 --hi; 363 } 364 Ldone: 365 ; 366 } 367 return this; 368 } 369 370 371 debug( UnitTest ) 372 { 373 unittest 374 { 375 size_t x = 0b1100011000; 376 auto ba = BitArray(10, &x); 377 378 ba.sort; 379 for( size_t i = 0; i < 6; ++i ) 380 assert( ba[i] == false ); 381 for( size_t i = 6; i < 10; ++i ) 382 assert( ba[i] == true ); 383 } 384 } 385 386 387 /** 388 * Operates on all bits in this array. 389 * 390 * Params: 391 * dg = The supplied code as a delegate. 392 */ 393 int opApply(scope int delegate(ref bool) dg ) 394 { 395 int result; 396 397 for( size_t i = 0; i < len; ++i ) 398 { 399 bool b = opIndex( i ); 400 result = dg( b ); 401 opIndexAssign( b, i ); 402 if( result ) 403 break; 404 } 405 return result; 406 } 407 408 409 /** ditto */ 410 int opApply(scope int delegate(ref size_t, ref bool) dg ) 411 { 412 int result; 413 414 for( size_t i = 0; i < len; ++i ) 415 { 416 bool b = opIndex( i ); 417 result = dg( i, b ); 418 opIndexAssign( b, i ); 419 if( result ) 420 break; 421 } 422 return result; 423 } 424 425 426 debug( UnitTest ) 427 { 428 unittest 429 { 430 BitArray a = [1,0,1]; 431 432 int i; 433 foreach( b; a ) 434 { 435 switch( i ) 436 { 437 case 0: assert( b == true ); break; 438 case 1: assert( b == false ); break; 439 case 2: assert( b == true ); break; 440 default: assert( false ); 441 } 442 i++; 443 } 444 445 foreach( j, b; a ) 446 { 447 switch( j ) 448 { 449 case 0: assert( b == true ); break; 450 case 1: assert( b == false ); break; 451 case 2: assert( b == true ); break; 452 default: assert( false ); 453 } 454 } 455 } 456 } 457 458 459 /** 460 * Compares this array to another for equality. Two bit arrays are equal 461 * if they are the same size and contain the same series of bits. 462 * 463 * Params: 464 * rhs = The array to compare against. 465 * 466 * Returns: 467 * false if not equal and non-zero otherwise. 468 */ 469 bool opEquals(ref const(BitArray) rhs) const 470 { 471 if( this.length() != rhs.length() ) 472 return 0; // not equal 473 const size_t* p1 = this.ptr; 474 const size_t* p2 = rhs.ptr; 475 size_t n = this.length / bits_in_size; 476 size_t i; 477 for( i = 0; i < n; ++i ) 478 { 479 if( p1[i] != p2[i] ) 480 return 0; // not equal 481 } 482 int rest = cast(int)(this.length & cast(size_t)(bits_in_size-1)); 483 size_t mask = ~((~0u)<<rest); 484 return (rest == 0) || (p1[i] & mask) == (p2[i] & mask); 485 } 486 487 debug( UnitTest ) 488 { 489 unittest 490 { 491 BitArray a = [1,0,1,0,1]; 492 BitArray b = [1,0,1]; 493 BitArray c = [1,0,1,0,1,0,1]; 494 const(BitArray) d = [1,0,1,1,1]; 495 auto e = immutable(BitArray)([1,0,1,0,1]); 496 497 assert(a != b); 498 assert(a != c); 499 assert(a != d); 500 assert(a == e); 501 } 502 } 503 504 505 /** 506 * Performs a lexicographical comparison of this array to the supplied 507 * array. 508 * 509 * Params: 510 * rhs = The array to compare against. 511 * 512 * Returns: 513 * A value less than zero if this array sorts before the supplied array, 514 * zero if the arrays are equavalent, and a value greater than zero if 515 * this array sorts after the supplied array. 516 */ 517 int opCmp( ref const(BitArray) rhs ) const 518 { 519 auto len = this.length; 520 if( rhs.length < len ) 521 len = rhs.length; 522 auto p1 = this.ptr; 523 auto p2 = rhs.ptr; 524 size_t n = len / bits_in_size; 525 size_t i; 526 for( i = 0; i < n; ++i ) 527 { 528 if( p1[i] != p2[i] ){ 529 return ((p1[i] < p2[i])?-1:1); 530 } 531 } 532 int rest=cast(int)(len & cast(size_t) (bits_in_size-1)); 533 if (rest>0) { 534 size_t mask=~((~0u)<<rest); 535 size_t v1=p1[i] & mask; 536 size_t v2=p2[i] & mask; 537 if (v1 != v2) return ((v1<v2)?-1:1); 538 } 539 return ((this.length<rhs.length)?-1:((this.length==rhs.length)?0:1)); 540 } 541 542 debug( UnitTest ) 543 { 544 unittest 545 { 546 BitArray a = [1,0,1,0,1]; 547 BitArray b = [1,0,1]; 548 BitArray c = [1,0,1,0,1,0,1]; 549 BitArray d = [1,0,1,1,1]; 550 BitArray e = [1,0,1,0,1]; 551 BitArray f = [1,0,1,0]; 552 553 assert( a > b ); 554 assert( a >= b ); 555 assert( a < c ); 556 assert( a <= c ); 557 assert( a < d ); 558 assert( a <= d ); 559 assert( a == e ); 560 assert( a <= e ); 561 assert( a >= e ); 562 assert( f > b ); 563 } 564 } 565 566 567 /** 568 * Convert this array to a void array. 569 * 570 * Returns: 571 * This array represented as a void array. 572 */ 573 void[] opCast() const 574 { 575 return cast(void[])ptr[0 .. dim]; 576 } 577 578 579 debug( UnitTest ) 580 { 581 unittest 582 { 583 BitArray a = [1,0,1,0,1]; 584 void[] v = cast(void[])a; 585 586 assert( v.length == a.dim * size_t.sizeof ); 587 } 588 } 589 590 591 /** 592 * Support for index operations, much like the behavior of built-in arrays. 593 * 594 * Params: 595 * pos = The desired index position. 596 * 597 * In: 598 * pos must be less than the length of this array. 599 * 600 * Returns: 601 * The value of the bit at pos. 602 */ 603 bool opIndex( size_t pos ) const 604 in 605 { 606 assert( pos < len ); 607 } 608 body 609 { 610 return cast(bool)bt( ptr, pos ); 611 } 612 613 614 /** 615 * Generates a copy of this array with the unary complement operation 616 * applied. 617 * 618 * Returns: 619 * A new array which is the complement of this array. 620 */ 621 BitArray opCom() 622 { 623 auto dim = this.dim(); 624 625 BitArray result; 626 627 result.length = len; 628 for( size_t i = 0; i < dim; ++i ) 629 result.ptr[i] = ~this.ptr[i]; 630 if( len & (bits_in_size-1) ) 631 result.ptr[dim - 1] &= ~(~0 << (len & (bits_in_size-1))); 632 return result; 633 } 634 635 636 debug( UnitTest ) 637 { 638 unittest 639 { 640 BitArray a = [1,0,1,0,1]; 641 BitArray b = ~a; 642 643 assert(b[0] == 0); 644 assert(b[1] == 1); 645 assert(b[2] == 0); 646 assert(b[3] == 1); 647 assert(b[4] == 0); 648 } 649 } 650 651 652 /** 653 * Generates a new array which is the result of a bitwise and operation 654 * between this array and the supplied array. 655 * 656 * Params: 657 * rhs = The array with which to perform the bitwise and operation. 658 * 659 * In: 660 * rhs.length must equal the length of this array. 661 * 662 * Returns: 663 * A new array which is the result of a bitwise and with this array and 664 * the supplied array. 665 */ 666 BitArray opAnd( ref const(BitArray) rhs ) const 667 in 668 { 669 assert( len == rhs.length ); 670 } 671 body 672 { 673 auto dim = this.dim(); 674 675 BitArray result; 676 677 result.length = len; 678 for( size_t i = 0; i < dim; ++i ) 679 result.ptr[i] = this.ptr[i] & rhs.ptr[i]; 680 return result; 681 } 682 683 684 debug( UnitTest ) 685 { 686 unittest 687 { 688 BitArray a = [1,0,1,0,1]; 689 BitArray b = [1,0,1,1,0]; 690 691 BitArray c = a & b; 692 693 assert(c[0] == 1); 694 assert(c[1] == 0); 695 assert(c[2] == 1); 696 assert(c[3] == 0); 697 assert(c[4] == 0); 698 } 699 } 700 701 702 /** 703 * Generates a new array which is the result of a bitwise or operation 704 * between this array and the supplied array. 705 * 706 * Params: 707 * rhs = The array with which to perform the bitwise or operation. 708 * 709 * In: 710 * rhs.length must equal the length of this array. 711 * 712 * Returns: 713 * A new array which is the result of a bitwise or with this array and 714 * the supplied array. 715 */ 716 BitArray opOr( ref const(BitArray) rhs ) const 717 in 718 { 719 assert( len == rhs.length ); 720 } 721 body 722 { 723 auto dim = this.dim(); 724 725 BitArray result; 726 727 result.length = len; 728 for( size_t i = 0; i < dim; ++i ) 729 result.ptr[i] = this.ptr[i] | rhs.ptr[i]; 730 return result; 731 } 732 733 734 debug( UnitTest ) 735 { 736 unittest 737 { 738 BitArray a = [1,0,1,0,1]; 739 BitArray b = [1,0,1,1,0]; 740 741 BitArray c = a | b; 742 743 assert(c[0] == 1); 744 assert(c[1] == 0); 745 assert(c[2] == 1); 746 assert(c[3] == 1); 747 assert(c[4] == 1); 748 749 const BitArray d = [1,1,1,0,0]; 750 c = a | d; 751 752 assert(c[0] == 1); 753 assert(c[1] == 1); 754 assert(c[2] == 1); 755 assert(c[3] == 0); 756 assert(c[4] == 1); 757 758 auto e = immutable(BitArray)([1,0,1,0,0]) ; 759 760 c = a | e; 761 762 assert(c[0] == 1); 763 assert(c[1] == 0); 764 assert(c[2] == 1); 765 assert(c[3] == 0); 766 assert(c[4] == 1); 767 768 } 769 } 770 771 772 /** 773 * Generates a new array which is the result of a bitwise xor operation 774 * between this array and the supplied array. 775 * 776 * Params: 777 * rhs = The array with which to perform the bitwise xor operation. 778 * 779 * In: 780 * rhs.length must equal the length of this array. 781 * 782 * Returns: 783 * A new array which is the result of a bitwise xor with this array and 784 * the supplied array. 785 */ 786 BitArray opXor( ref const(BitArray) rhs ) const 787 in 788 { 789 assert( len == rhs.length ); 790 } 791 body 792 { 793 auto dim = this.dim(); 794 795 BitArray result; 796 797 result.length = len; 798 for( size_t i = 0; i < dim; ++i ) 799 result.ptr[i] = this.ptr[i] ^ rhs.ptr[i]; 800 return result; 801 } 802 803 804 debug( UnitTest ) 805 { 806 unittest 807 { 808 BitArray a = [1,0,1,0,1]; 809 BitArray b = [1,0,1,1,0]; 810 811 BitArray c = a ^ b; 812 813 assert(c[0] == 0); 814 assert(c[1] == 0); 815 assert(c[2] == 0); 816 assert(c[3] == 1); 817 assert(c[4] == 1); 818 819 const BitArray d = [0,0,1,1,0]; 820 821 c = a ^ d; 822 823 assert(c[0] == 1); 824 assert(c[1] == 0); 825 assert(c[2] == 0); 826 assert(c[3] == 1); 827 assert(c[4] == 1); 828 829 const BitArray e = [0,0,1,0,0]; 830 831 c = a ^ e; 832 833 assert(c[0] == 1); 834 assert(c[1] == 0); 835 assert(c[2] == 0); 836 assert(c[3] == 0); 837 assert(c[4] == 1); 838 } 839 } 840 841 842 /** 843 * Generates a new array which is the result of this array minus the 844 * supplied array. $(I a - b) for BitArrays means the same thing as 845 * $(I a & ~b). 846 * 847 * Params: 848 * rhs = The array with which to perform the subtraction operation. 849 * 850 * In: 851 * rhs.length must equal the length of this array. 852 * 853 * Returns: 854 * A new array which is the result of this array minus the supplied array. 855 */ 856 BitArray opSub( ref const(BitArray) rhs ) const 857 in 858 { 859 assert( len == rhs.length ); 860 } 861 body 862 { 863 auto dim = this.dim(); 864 865 BitArray result; 866 867 result.length = len; 868 for( size_t i = 0; i < dim; ++i ) 869 result.ptr[i] = this.ptr[i] & ~rhs.ptr[i]; 870 return result; 871 } 872 873 874 debug( UnitTest ) 875 { 876 unittest 877 { 878 BitArray a = [1,0,1,0,1]; 879 BitArray b = [1,0,1,1,0]; 880 881 BitArray c = a - b; 882 883 assert( c[0] == 0 ); 884 assert( c[1] == 0 ); 885 assert( c[2] == 0 ); 886 assert( c[3] == 0 ); 887 assert( c[4] == 1 ); 888 889 const BitArray d = [0,0,1,1,0]; 890 891 c = a - d; 892 893 assert( c[0] == 1 ); 894 assert( c[1] == 0 ); 895 assert( c[2] == 0 ); 896 assert( c[3] == 0 ); 897 assert( c[4] == 1 ); 898 899 auto e = immutable(BitArray)([0,0,0,1,1]); 900 901 c = a - e; 902 903 assert( c[0] == 1 ); 904 assert( c[1] == 0 ); 905 assert( c[2] == 1 ); 906 assert( c[3] == 0 ); 907 assert( c[4] == 0 ); 908 } 909 } 910 911 912 /** 913 * Generates a new array which is the result of this array concatenated 914 * with the supplied array. 915 * 916 * Params: 917 * rhs = The array with which to perform the concatenation operation. 918 * 919 * Returns: 920 * A new array which is the result of this array concatenated with the 921 * supplied array. 922 */ 923 BitArray opCat( bool rhs ) const 924 { 925 BitArray result; 926 927 result = this.dup; 928 result.length = len + 1; 929 result[len] = rhs; 930 return result; 931 } 932 933 934 /** ditto */ 935 BitArray opCat_r( bool lhs ) const 936 { 937 BitArray result; 938 939 result.length = len + 1; 940 result[0] = lhs; 941 for( size_t i = 0; i < len; ++i ) 942 result[1 + i] = (this)[i]; 943 return result; 944 } 945 946 947 /** ditto */ 948 BitArray opCat( ref const(BitArray) rhs ) const 949 { 950 BitArray result; 951 952 result = this.dup(); 953 result ~= rhs; 954 return result; 955 } 956 957 958 debug( UnitTest ) 959 { 960 unittest 961 { 962 BitArray a = [1,0]; 963 BitArray b = [0,1,0]; 964 BitArray c; 965 966 c = (a ~ b); 967 assert( c.length == 5 ); 968 assert( c[0] == 1 ); 969 assert( c[1] == 0 ); 970 assert( c[2] == 0 ); 971 assert( c[3] == 1 ); 972 assert( c[4] == 0 ); 973 974 c = (a ~ true); 975 assert( c.length == 3 ); 976 assert( c[0] == 1 ); 977 assert( c[1] == 0 ); 978 assert( c[2] == 1 ); 979 980 c = (false ~ a); 981 assert( c.length == 3 ); 982 assert( c[0] == 0 ); 983 assert( c[1] == 1 ); 984 assert( c[2] == 0 ); 985 986 const BitArray d = [0,1,1]; 987 988 c = (a ~ d); 989 assert( c.length == 5 ); 990 assert( c[0] == 1 ); 991 assert( c[1] == 0 ); 992 assert( c[2] == 0 ); 993 assert( c[3] == 1 ); 994 assert( c[4] == 1 ); 995 996 auto e = immutable(BitArray)([1,0,1]); 997 998 c = (a ~ e); 999 assert( c.length == 5 ); 1000 assert( c[0] == 1 ); 1001 assert( c[1] == 0 ); 1002 assert( c[2] == 1 ); 1003 assert( c[3] == 0 ); 1004 assert( c[4] == 1 ); 1005 1006 } 1007 } 1008 1009 1010 /** 1011 * Support for index operations, much like the behavior of built-in arrays. 1012 * 1013 * Params: 1014 * b = The new bit value to set. 1015 * pos = The desired index position. 1016 * 1017 * In: 1018 * pos must be less than the length of this array. 1019 * 1020 * Returns: 1021 * The new value of the bit at pos. 1022 */ 1023 bool opIndexAssign( bool b, size_t pos ) pure 1024 in 1025 { 1026 assert( pos < len ); 1027 } 1028 body 1029 { 1030 if( b ) 1031 bts( ptr, pos ); 1032 else 1033 btr( ptr, pos ); 1034 return b; 1035 } 1036 1037 1038 /** 1039 * Updates the contents of this array with the result of a bitwise and 1040 * operation between this array and the supplied array. 1041 * 1042 * Params: 1043 * rhs = The array with which to perform the bitwise and operation. 1044 * 1045 * In: 1046 * rhs.length must equal the length of this array. 1047 * 1048 * Returns: 1049 * A shallow copy of this array. 1050 */ 1051 BitArray opAndAssign( const(BitArray) rhs ) 1052 in 1053 { 1054 assert( len == rhs.length ); 1055 } 1056 body 1057 { 1058 auto dim = this.dim(); 1059 1060 for( size_t i = 0; i < dim; ++i ) 1061 ptr[i] &= rhs.ptr[i]; 1062 return this; 1063 } 1064 1065 1066 debug( UnitTest ) 1067 { 1068 unittest 1069 { 1070 BitArray a = [1,0,1,0,1]; 1071 BitArray b = [1,0,1,1,0]; 1072 1073 a &= b; 1074 assert( a[0] == 1 ); 1075 assert( a[1] == 0 ); 1076 assert( a[2] == 1 ); 1077 assert( a[3] == 0 ); 1078 assert( a[4] == 0 ); 1079 1080 const BitArray d = [1,0,0,1,0]; 1081 1082 a &= d; 1083 assert( a[0] == 1 ); 1084 assert( a[1] == 0 ); 1085 assert( a[2] == 0 ); 1086 assert( a[3] == 0 ); 1087 assert( a[4] == 0 ); 1088 1089 } 1090 } 1091 1092 1093 /** 1094 * Updates the contents of this array with the result of a bitwise or 1095 * operation between this array and the supplied array. 1096 * 1097 * Params: 1098 * rhs = The array with which to perform the bitwise or operation. 1099 * 1100 * In: 1101 * rhs.length must equal the length of this array. 1102 * 1103 * Returns: 1104 * A shallow copy of this array. 1105 */ 1106 BitArray opOrAssign( const(BitArray) rhs ) 1107 in 1108 { 1109 assert( len == rhs.length ); 1110 } 1111 body 1112 { 1113 auto dim = this.dim(); 1114 1115 for( size_t i = 0; i < dim; ++i ) 1116 ptr[i] |= rhs.ptr[i]; 1117 return this; 1118 } 1119 1120 1121 debug( UnitTest ) 1122 { 1123 unittest 1124 { 1125 BitArray a = [1,0,1,0,1]; 1126 BitArray b = [1,0,1,1,0]; 1127 1128 a |= b; 1129 assert( a[0] == 1 ); 1130 assert( a[1] == 0 ); 1131 assert( a[2] == 1 ); 1132 assert( a[3] == 1 ); 1133 assert( a[4] == 1 ); 1134 1135 const BitArray e = [1,0,1,0,0]; 1136 1137 a=[1,0,1,0,1]; 1138 a |= e; 1139 assert( a[0] == 1 ); 1140 assert( a[1] == 0 ); 1141 assert( a[2] == 1 ); 1142 assert( a[3] == 0 ); 1143 assert( a[4] == 1 ); 1144 } 1145 } 1146 1147 1148 /** 1149 * Updates the contents of this array with the result of a bitwise xor 1150 * operation between this array and the supplied array. 1151 * 1152 * Params: 1153 * rhs = The array with which to perform the bitwise xor operation. 1154 * 1155 * In: 1156 * rhs.length must equal the length of this array. 1157 * 1158 * Returns: 1159 * A shallow copy of this array. 1160 */ 1161 BitArray opXorAssign( const(BitArray) rhs ) 1162 in 1163 { 1164 assert( len == rhs.length ); 1165 } 1166 body 1167 { 1168 auto dim = this.dim(); 1169 1170 for( size_t i = 0; i < dim; ++i ) 1171 ptr[i] ^= rhs.ptr[i]; 1172 return this; 1173 } 1174 1175 1176 debug( UnitTest ) 1177 { 1178 unittest 1179 { 1180 BitArray a = [1,0,1,0,1]; 1181 BitArray b = [1,0,1,1,0]; 1182 1183 a ^= b; 1184 assert( a[0] == 0 ); 1185 assert( a[1] == 0 ); 1186 assert( a[2] == 0 ); 1187 assert( a[3] == 1 ); 1188 assert( a[4] == 1 ); 1189 1190 const BitArray e = [1,0,1,0,0]; 1191 1192 a = [1,0,1,0,1]; 1193 a ^= e; 1194 assert( a[0] == 0 ); 1195 assert( a[1] == 0 ); 1196 assert( a[2] == 0 ); 1197 assert( a[3] == 0 ); 1198 assert( a[4] == 1 ); 1199 } 1200 } 1201 1202 1203 /** 1204 * Updates the contents of this array with the result of this array minus 1205 * the supplied array. $(I a - b) for BitArrays means the same thing as 1206 * $(I a & ~b). 1207 * 1208 * Params: 1209 * rhs = The array with which to perform the subtraction operation. 1210 * 1211 * In: 1212 * rhs.length must equal the length of this array. 1213 * 1214 * Returns: 1215 * A shallow copy of this array. 1216 */ 1217 BitArray opSubAssign( const(BitArray) rhs ) 1218 in 1219 { 1220 assert( len == rhs.length ); 1221 } 1222 body 1223 { 1224 auto dim = this.dim(); 1225 1226 for( size_t i = 0; i < dim; ++i ) 1227 ptr[i] &= ~rhs.ptr[i]; 1228 return this; 1229 } 1230 1231 1232 debug( UnitTest ) 1233 { 1234 unittest 1235 { 1236 BitArray a = [1,0,1,0,1]; 1237 BitArray b = [1,0,1,1,0]; 1238 1239 a -= b; 1240 assert( a[0] == 0 ); 1241 assert( a[1] == 0 ); 1242 assert( a[2] == 0 ); 1243 assert( a[3] == 0 ); 1244 assert( a[4] == 1 ); 1245 } 1246 } 1247 1248 1249 /** 1250 * Updates the contents of this array with the result of this array 1251 * concatenated with the supplied array. 1252 * 1253 * Params: 1254 * rhs = The array with which to perform the concatenation operation. 1255 * 1256 * Returns: 1257 * A shallow copy of this array. 1258 */ 1259 BitArray opCatAssign( bool b ) 1260 { 1261 length = len + 1; 1262 (this)[len - 1] = b; 1263 return this; 1264 } 1265 1266 1267 debug( UnitTest ) 1268 { 1269 unittest 1270 { 1271 BitArray a = [1,0,1,0,1]; 1272 BitArray b; 1273 1274 b = (a ~= true); 1275 assert( a[0] == 1 ); 1276 assert( a[1] == 0 ); 1277 assert( a[2] == 1 ); 1278 assert( a[3] == 0 ); 1279 assert( a[4] == 1 ); 1280 assert( a[5] == 1 ); 1281 1282 assert( b == a ); 1283 } 1284 } 1285 1286 1287 /** ditto */ 1288 BitArray opCatAssign( const(BitArray) rhs ) 1289 { 1290 auto istart = len; 1291 length = len + rhs.length; 1292 for( auto i = istart; i < len; ++i ) 1293 (this)[i] = rhs[i - istart]; 1294 return this; 1295 } 1296 1297 1298 debug( UnitTest ) 1299 { 1300 unittest 1301 { 1302 BitArray a = [1,0]; 1303 BitArray b = [0,1,0]; 1304 BitArray c; 1305 1306 c = (a ~= b); 1307 assert( a.length == 5 ); 1308 assert( a[0] == 1 ); 1309 assert( a[1] == 0 ); 1310 assert( a[2] == 0 ); 1311 assert( a[3] == 1 ); 1312 assert( a[4] == 0 ); 1313 1314 assert( c == a ); 1315 } 1316 } 1317 }