001 /* 002 // $Id: //open/mondrian/src/main/mondrian/rolap/BitKey.java#15 $ 003 // This software is subject to the terms of the Common Public License 004 // Agreement, available at the following URL: 005 // http://www.opensource.org/licenses/cpl.html. 006 // Copyright (C) 2001-2002 Kana Software, Inc. 007 // Copyright (C) 2001-2008 Julian Hyde and others 008 // All Rights Reserved. 009 // You must accept the terms of that agreement to use this software. 010 // 011 // jhyde, 30 August, 2001 012 */ 013 014 package mondrian.rolap; 015 016 import java.util.BitSet; 017 import java.util.Iterator; 018 019 /** 020 * Represents a set of bits. 021 * 022 * <p>Unlike {@link java.util.BitSet}, the number of bits cannot be changed 023 * after the BitKey is created. This allows us to optimize. 024 * 025 * <p>If you have a collection of immutable objects, each of which has a unique 026 * positive number and you wish to do comparisons between subsets of those 027 * objects testing for equality, then encoding the subsets as BitKeys is very 028 * efficient. 029 * 030 * <p>There are two implementations that target groups of objects with maximum 031 * number less than 64 and less than 128; and there is one implements that is 032 * general for any positive number. 033 * 034 * <p>One caution: if the maximum number assigned to one of the 035 * objects is large, then this representation might be sparse and therefore 036 * not efficient. 037 * 038 * @author Richard M. Emberson 039 * @version $Id: //open/mondrian/src/main/mondrian/rolap/BitKey.java#15 $ 040 */ 041 public interface BitKey extends Comparable<BitKey>, Iterable<Integer> { 042 043 /** 044 * Sets the bit at the specified index to the specified value. 045 */ 046 void set(int bitIndex, boolean value); 047 048 /** 049 * Sets the bit at the specified index to <code>true</code>. 050 */ 051 void set(int bitIndex); 052 053 /** 054 * Returns the value of the bit with the specified index. The value 055 * is <code>true</code> if the bit with the index <code>bitIndex</code> 056 * is currently set in this <code>BitKey</code>; otherwise, the result 057 * is <code>false</code>. 058 */ 059 boolean get(int bitIndex); 060 061 /** 062 * Sets the bit specified by the index to <code>false</code>. 063 */ 064 void clear(int bitIndex); 065 066 /** 067 * Sets all of the bits in this BitKey to <code>false</code>. 068 */ 069 void clear(); 070 071 /** 072 * Is every bit set in the parameter <code>bitKey</code> also set in 073 * <code>this</code>. 074 * If one switches <code>this</code> with the parameter <code>bitKey</code> 075 * one gets the equivalent of isSubSetOf. 076 * 077 * @param bitKey 078 */ 079 boolean isSuperSetOf(BitKey bitKey); 080 081 /** 082 * Or the parameter <code>BitKey</code> with <code>this</code>. 083 * 084 * @param bitKey 085 */ 086 BitKey or(BitKey bitKey); 087 088 /** 089 * Returns the boolean AND of this bitkey and the given bitkey. 090 */ 091 BitKey and(BitKey bitKey); 092 093 /** 094 * Returns a <code>BitKey</code> containing all of the bits in this 095 * <code>BitSet</code> whose corresponding 096 * bit is NOT set in the specified <code>BitSet</code>. 097 */ 098 BitKey andNot(BitKey bitKey); 099 100 /** 101 * Returns a copy of this BitKey. 102 * 103 * @return copy of BitKey 104 */ 105 BitKey copy(); 106 107 /** 108 * Returns an empty BitKey of the same type. This is the same 109 * as calling {@link #copy} followed by {@link #clear()}. 110 * 111 * @return BitKey of same type 112 */ 113 BitKey emptyCopy(); 114 115 /** 116 * Returns true if this <code>BitKey</code> contains no bits that are set 117 * to <code>true</code>. 118 */ 119 boolean isEmpty(); 120 121 /** 122 * Returns whether this BitKey has any bits in common with a given BitKey. 123 */ 124 boolean intersects(BitKey bitKey); 125 126 /** 127 * Returns a {@link BitSet} with the same contents as this BitKey. 128 */ 129 BitSet toBitSet(); 130 131 /** 132 * An Iterator over the bit positions. 133 * For example, if the BitKey had positions 3 and 4 set, then 134 * the Iterator would return the values 3 and then 4. The bit 135 * positions returned by the iterator are in the order, from 136 * smallest to largest, as they are set in the BitKey. 137 */ 138 Iterator<Integer> iterator(); 139 140 public abstract class Factory { 141 142 /** 143 * Creates a {@link BitKey} with a capacity for a given number of bits. 144 * @param size Number of bits in key 145 */ 146 public static BitKey makeBitKey(int size) { 147 if (size < 0) { 148 String msg = "Negative size \"" + size + "\" not allowed"; 149 throw new IllegalArgumentException(msg); 150 } 151 if (size < 64) { 152 return new BitKey.Small(); 153 } else if (size < 128) { 154 return new BitKey.Mid128(); 155 } else { 156 return new BitKey.Big(size); 157 } 158 /* 159 switch (AbstractBitKey.chunkCount(size)) { 160 case 0: 161 case 1: 162 return new BitKey.Small(); 163 case 2: 164 return new BitKey.Mid128(); 165 default: 166 return new BitKey.Big(size); 167 } 168 */ 169 } 170 171 /** 172 * Creates a {@link BitKey} with the same contents as a {@link BitSet}. 173 */ 174 public static BitKey makeBitKey(BitSet bitSet) { 175 BitKey bitKey = makeBitKey(bitSet.length()); 176 for (int i = bitSet.nextSetBit(0); i >= 0; i = bitSet.nextSetBit(i + 1)) { 177 bitKey.set(i); 178 } 179 return bitKey; 180 } 181 } 182 183 /** 184 * Abstract implementation of {@link BitKey}. 185 */ 186 abstract class AbstractBitKey implements BitKey { 187 protected AbstractBitKey() { 188 } 189 190 // chunk is a long, which has 64 bits 191 protected static final int ChunkBitCount = 6; 192 protected static final int Mask = 63; 193 194 /** 195 * Creates a chunk containing a single bit. 196 */ 197 protected static long bit(int pos) { 198 return (1L << (pos & Mask)); 199 } 200 201 /** 202 * Returns which chunk a given bit falls into. 203 * Bits 0 to 63 fall in chunk 0, bits 64 to 127 fall into chunk 1. 204 */ 205 protected static int chunkPos(int size) { 206 return (size >> ChunkBitCount); 207 } 208 209 /** 210 * Returns the number of chunks required for a given number of bits. 211 * 212 * <p>0 bits requires 0 chunks; 1 - 64 bits requires 1 chunk; etc. 213 */ 214 protected static int chunkCount(int size) { 215 return (size + 63) >> ChunkBitCount; 216 } 217 218 public final void set(int pos, boolean value) { 219 if (value) { 220 set(pos); 221 } else { 222 clear(pos); 223 } 224 } 225 226 protected static void copyFromByte(BitSet bitSet, int pos, byte x) 227 { 228 if (x == 0) { 229 return; 230 } 231 if ((x & 0x01) != 0) { 232 bitSet.set(pos, true); 233 } 234 ++pos; 235 if ((x & 0x02) != 0) { 236 bitSet.set(pos, true); 237 } 238 ++pos; 239 if ((x & 0x04) != 0) { 240 bitSet.set(pos, true); 241 } 242 ++pos; 243 if ((x & 0x08) != 0) { 244 bitSet.set(pos, true); 245 } 246 ++pos; 247 if ((x & 0x10) != 0) { 248 bitSet.set(pos, true); 249 } 250 ++pos; 251 if ((x & 0x20) != 0) { 252 bitSet.set(pos, true); 253 } 254 ++pos; 255 if ((x & 0x40) != 0) { 256 bitSet.set(pos, true); 257 } 258 ++pos; 259 if ((x & 0x80) != 0) { 260 bitSet.set(pos, true); 261 } 262 } 263 264 protected static void copyFromLong( 265 final BitSet bitSet, 266 int pos, 267 long x) { 268 while (x != 0) { 269 copyFromByte(bitSet, pos, (byte) (x & 0xff)); 270 x >>>= 8; 271 pos += 8; 272 } 273 } 274 275 protected IllegalArgumentException createException(BitKey bitKey) { 276 final String msg = (bitKey == null) 277 ? "Null BitKey" 278 : "Bad BitKey type: " + bitKey.getClass().getName(); 279 return new IllegalArgumentException(msg); 280 } 281 } 282 283 /** 284 * Implementation of {@link BitKey} for bit counts less than 64. 285 */ 286 public class Small extends AbstractBitKey { 287 private long bits; 288 289 private Small() { 290 } 291 private Small(long bits) { 292 this.bits = bits; 293 } 294 public void set(int pos) { 295 if (pos < 64) { 296 bits |= bit(pos); 297 } else { 298 throw new IllegalArgumentException("pos " + pos + " exceeds capacity 64"); 299 } 300 } 301 public boolean get(int pos) { 302 return pos < 64 && ((bits & bit(pos)) != 0); 303 } 304 public void clear(int pos) { 305 bits &= ~bit(pos); 306 } 307 public void clear() { 308 bits = 0; 309 } 310 private void or(long bits) { 311 this.bits |= bits; 312 } 313 314 private void and(long bits) { 315 this.bits &= bits; 316 } 317 318 public BitKey or(BitKey bitKey) { 319 if (bitKey instanceof BitKey.Small) { 320 final BitKey.Small other = (BitKey.Small) bitKey; 321 final BitKey.Small bk = (BitKey.Small) copy(); 322 bk.or(other.bits); 323 return bk; 324 325 } else if (bitKey instanceof BitKey.Mid128) { 326 final BitKey.Mid128 other = (BitKey.Mid128) bitKey; 327 final BitKey.Mid128 bk = (BitKey.Mid128) other.copy(); 328 bk.or(this.bits, 0); 329 return bk; 330 331 } else if (bitKey instanceof BitKey.Big) { 332 final BitKey.Big other = (BitKey.Big) bitKey; 333 final BitKey.Big bk = (BitKey.Big) other.copy(); 334 bk.or(this.bits); 335 return bk; 336 } 337 338 throw createException(bitKey); 339 } 340 341 public BitKey and(BitKey bitKey) { 342 if (bitKey instanceof BitKey.Small) { 343 final BitKey.Small other = (BitKey.Small) bitKey; 344 final BitKey.Small bk = (BitKey.Small) copy(); 345 bk.and(other.bits); 346 return bk; 347 348 } else if (bitKey instanceof BitKey.Mid128) { 349 final BitKey.Mid128 other = (BitKey.Mid128) bitKey; 350 final BitKey.Small bk = (BitKey.Small) copy(); 351 bk.and(other.bits0); 352 return bk; 353 354 } else if (bitKey instanceof BitKey.Big) { 355 final BitKey.Big other = (BitKey.Big) bitKey; 356 final BitKey.Small bk = (BitKey.Small) copy(); 357 bk.and(other.bits[0]); 358 return bk; 359 } 360 361 throw createException(bitKey); 362 } 363 364 public BitKey andNot(BitKey bitKey) { 365 if (bitKey instanceof BitKey.Small) { 366 final BitKey.Small other = (BitKey.Small) bitKey; 367 final BitKey.Small bk = (BitKey.Small) copy(); 368 bk.andNot(other.bits); 369 return bk; 370 371 } else if (bitKey instanceof BitKey.Mid128) { 372 final BitKey.Mid128 other = (BitKey.Mid128) bitKey; 373 final BitKey.Small bk = (BitKey.Small) copy(); 374 bk.andNot(other.bits0); 375 return bk; 376 377 } else if (bitKey instanceof BitKey.Big) { 378 final BitKey.Big other = (BitKey.Big) bitKey; 379 final BitKey.Small bk = (BitKey.Small) copy(); 380 bk.andNot(other.bits[0]); 381 return bk; 382 } 383 384 throw createException(bitKey); 385 } 386 387 private void andNot(long bits) { 388 this.bits &= ~bits; 389 } 390 391 public boolean isSuperSetOf(BitKey bitKey) { 392 if (bitKey instanceof BitKey.Small) { 393 BitKey.Small other = (BitKey.Small) bitKey; 394 return ((this.bits | other.bits) == this.bits); 395 396 } else if (bitKey instanceof BitKey.Mid128) { 397 BitKey.Mid128 other = (BitKey.Mid128) bitKey; 398 return ((this.bits | other.bits0) == this.bits) && 399 (other.bits1 == 0); 400 401 } else if (bitKey instanceof BitKey.Big) { 402 BitKey.Big other = (BitKey.Big) bitKey; 403 if ((this.bits | other.bits[0]) != this.bits) { 404 return false; 405 } else { 406 for (int i = 1; i < other.bits.length; i++) { 407 if (other.bits[i] != 0) { 408 return false; 409 } 410 } 411 return true; 412 } 413 } 414 return false; 415 } 416 417 public boolean intersects(BitKey bitKey) { 418 if (bitKey instanceof BitKey.Small) { 419 BitKey.Small other = (BitKey.Small) bitKey; 420 return (this.bits & other.bits) != 0; 421 422 } else if (bitKey instanceof BitKey.Mid128) { 423 BitKey.Mid128 other = (BitKey.Mid128) bitKey; 424 return (this.bits & other.bits0) != 0; 425 426 } else if (bitKey instanceof BitKey.Big) { 427 BitKey.Big other = (BitKey.Big) bitKey; 428 return (this.bits & other.bits[0]) != 0; 429 } 430 return false; 431 } 432 433 public BitSet toBitSet() { 434 final BitSet bitSet = new BitSet(64); 435 long x = bits; 436 int pos = 0; 437 while (x != 0) { 438 copyFromByte(bitSet, pos, (byte) (x & 0xff)); 439 x >>>= 8; 440 pos += 8; 441 } 442 return bitSet; 443 } 444 445 /** 446 * To say that I am happy about this algorithm (or the variations 447 * of the algorithm used for the Mid128 and Big BitKey implementations) 448 * would be a stretch. It works but there has to be a more 449 * elegant and faster one but this is the best I could come up 450 * with in a couple of hours. 451 * 452 */ 453 public Iterator<Integer> iterator() { 454 return new Iterator<Integer>() { 455 int pos = -1; 456 long bits = Small.this.bits; 457 public boolean hasNext() { 458 if (bits == 0) { 459 return false; 460 } 461 // This is a special case 462 // Long.MIN_VALUE == -9223372036854775808 463 if (bits == Long.MIN_VALUE) { 464 pos = 63; 465 bits = 0; 466 return true; 467 } 468 long b = (bits&-bits); 469 if (b == 0) { 470 // should never happen 471 return false; 472 } 473 int delta = 0; 474 while (b >= 256) { 475 b = (b >> 8); 476 delta += 8; 477 } 478 int p = bitPositionTable[(int) b]; 479 if (p >= 0) { 480 p += delta; 481 } else { 482 p = delta; 483 } 484 if (pos < 0) { 485 // first time 486 pos = p; 487 } else if (p == 0) { 488 pos++; 489 } else { 490 pos += (p + 1); 491 } 492 bits = bits >>> (p + 1); 493 return true; 494 } 495 public Integer next() { 496 return Integer.valueOf(pos); 497 } 498 public void remove() { 499 throw new UnsupportedOperationException("remove"); 500 } 501 }; 502 } 503 504 public boolean equals(Object o) { 505 if (this == o) { 506 return true; 507 } 508 if (o instanceof BitKey.Small) { 509 BitKey.Small other = (BitKey.Small) o; 510 return (this.bits == other.bits); 511 512 } else if (o instanceof BitKey.Mid128) { 513 BitKey.Mid128 other = (BitKey.Mid128) o; 514 return (this.bits == other.bits0) && (other.bits1 == 0); 515 516 } else if (o instanceof BitKey.Big) { 517 BitKey.Big other = (BitKey.Big) o; 518 if (this.bits != other.bits[0]) { 519 return false; 520 } else { 521 for (int i = 1; i < other.bits.length; i++) { 522 if (other.bits[i] != 0) { 523 return false; 524 } 525 } 526 return true; 527 } 528 } 529 return false; 530 } 531 public int hashCode() { 532 return (int)(bits ^ (bits >>> 32)); 533 } 534 535 // implement Comparable (in lazy, expensive fashion) 536 public int compareTo(BitKey bitKey) { 537 return toString().compareTo(bitKey.toString()); 538 } 539 540 public String toString() { 541 StringBuilder buf = new StringBuilder(64); 542 buf.append("0x"); 543 for (int i = 63; i >= 0; i--) { 544 buf.append((get(i)) ? '1' : '0'); 545 } 546 return buf.toString(); 547 } 548 public BitKey copy() { 549 return new Small(this.bits); 550 } 551 public BitKey emptyCopy() { 552 return new Small(); 553 } 554 555 public boolean isEmpty() { 556 return bits == 0; 557 } 558 } 559 560 /** 561 * Implementation of {@link BitKey} good for sizes less than 128. 562 */ 563 public class Mid128 extends AbstractBitKey { 564 private long bits0; 565 private long bits1; 566 567 private Mid128() { 568 } 569 private Mid128(Mid128 mid) { 570 this.bits0 = mid.bits0; 571 this.bits1 = mid.bits1; 572 } 573 574 public void set(int pos) { 575 if (pos < 64) { 576 bits0 |= bit(pos); 577 } else if (pos < 128) { 578 bits1 |= bit(pos); 579 } else { 580 throw new IllegalArgumentException("pos " + pos + " exceeds capacity 128"); 581 } 582 } 583 584 public boolean get(int pos) { 585 if (pos < 64) { 586 return (bits0 & bit(pos)) != 0; 587 } else if (pos < 128) { 588 return (bits1 & bit(pos)) != 0; 589 } else { 590 return false; 591 } 592 } 593 594 public void clear(int pos) { 595 if (pos < 64) { 596 bits0 &= ~bit(pos); 597 } else if (pos < 128) { 598 bits1 &= ~bit(pos); 599 } else { 600 throw new IndexOutOfBoundsException( 601 "pos " + pos + " exceeds size " + 128); 602 } 603 } 604 605 public void clear() { 606 bits0 = 0; 607 bits1 = 0; 608 } 609 610 private void or(long bits0, long bits1) { 611 this.bits0 |= bits0; 612 this.bits1 |= bits1; 613 } 614 615 private void and(long bits0, long bits1) { 616 this.bits0 &= bits0; 617 this.bits1 &= bits1; 618 } 619 620 public BitKey or(BitKey bitKey) { 621 if (bitKey instanceof BitKey.Small) { 622 final BitKey.Small other = (BitKey.Small) bitKey; 623 final BitKey.Mid128 bk = (BitKey.Mid128) copy(); 624 bk.or(other.bits, 0); 625 return bk; 626 627 } else if (bitKey instanceof BitKey.Mid128) { 628 final BitKey.Mid128 other = (BitKey.Mid128) bitKey; 629 final BitKey.Mid128 bk = (BitKey.Mid128) copy(); 630 bk.or(other.bits0, other.bits1); 631 return bk; 632 633 } else if (bitKey instanceof BitKey.Big) { 634 final BitKey.Big other = (BitKey.Big) bitKey; 635 final BitKey.Big bk = (BitKey.Big) other.copy(); 636 bk.or(this.bits0, this.bits1); 637 return bk; 638 } 639 640 throw createException(bitKey); 641 } 642 643 public BitKey and(BitKey bitKey) { 644 if (bitKey instanceof BitKey.Small) { 645 final BitKey.Small other = (BitKey.Small) bitKey; 646 final BitKey.Mid128 bk = (BitKey.Mid128) copy(); 647 bk.and(other.bits, 0); 648 return bk; 649 650 } else if (bitKey instanceof BitKey.Mid128) { 651 final BitKey.Mid128 other = (BitKey.Mid128) bitKey; 652 final BitKey.Mid128 bk = (BitKey.Mid128) copy(); 653 bk.and(other.bits0, other.bits1); 654 return bk; 655 656 } else if (bitKey instanceof BitKey.Big) { 657 final BitKey.Big other = (BitKey.Big) bitKey; 658 final BitKey.Mid128 bk = (BitKey.Mid128) copy(); 659 bk.and(other.bits[0], other.bits[1]); 660 return bk; 661 } 662 663 throw createException(bitKey); 664 } 665 666 public BitKey andNot(BitKey bitKey) { 667 if (bitKey instanceof BitKey.Small) { 668 final BitKey.Small other = (BitKey.Small) bitKey; 669 final BitKey.Mid128 bk = (BitKey.Mid128) copy(); 670 bk.andNot(other.bits, 0); 671 return bk; 672 673 } else if (bitKey instanceof BitKey.Mid128) { 674 final BitKey.Mid128 other = (BitKey.Mid128) bitKey; 675 final BitKey.Mid128 bk = (BitKey.Mid128) copy(); 676 bk.andNot(other.bits0, other.bits1); 677 return bk; 678 679 } else if (bitKey instanceof BitKey.Big) { 680 final BitKey.Big other = (BitKey.Big) bitKey; 681 final BitKey.Mid128 bk = (BitKey.Mid128) copy(); 682 bk.andNot(other.bits[0], other.bits[1]); 683 return bk; 684 } 685 686 throw createException(bitKey); 687 } 688 689 private void andNot(long bits0, long bits1) { 690 this.bits0 &= ~bits0; 691 this.bits1 &= ~bits1; 692 } 693 694 public boolean isSuperSetOf(BitKey bitKey) { 695 if (bitKey instanceof BitKey.Small) { 696 BitKey.Small other = (BitKey.Small) bitKey; 697 return ((this.bits0 | other.bits) == this.bits0); 698 699 } else if (bitKey instanceof BitKey.Mid128) { 700 BitKey.Mid128 other = (BitKey.Mid128) bitKey; 701 return ((this.bits0 | other.bits0) == this.bits0) && 702 ((this.bits1 | other.bits1) == this.bits1); 703 704 } else if (bitKey instanceof BitKey.Big) { 705 BitKey.Big other = (BitKey.Big) bitKey; 706 if ((this.bits0 | other.bits[0]) != this.bits0) { 707 return false; 708 } else if ((this.bits1 | other.bits[1]) != this.bits1) { 709 return false; 710 } else { 711 for (int i = 2; i < other.bits.length; i++) { 712 if (other.bits[i] != 0) { 713 return false; 714 } 715 } 716 return true; 717 } 718 } 719 return false; 720 } 721 722 public boolean intersects(BitKey bitKey) { 723 if (bitKey instanceof BitKey.Small) { 724 BitKey.Small other = (BitKey.Small) bitKey; 725 return (this.bits0 & other.bits) != 0; 726 727 } else if (bitKey instanceof BitKey.Mid128) { 728 BitKey.Mid128 other = (BitKey.Mid128) bitKey; 729 return (this.bits0 & other.bits0) != 0 || 730 (this.bits1 & other.bits1) != 0; 731 732 } else if (bitKey instanceof BitKey.Big) { 733 BitKey.Big other = (BitKey.Big) bitKey; 734 if ((this.bits0 & other.bits[0]) != 0) { 735 return true; 736 } else if ((this.bits1 & other.bits[1]) != 0) { 737 return true; 738 } else { 739 return false; 740 } 741 } 742 return false; 743 } 744 745 public BitSet toBitSet() { 746 final BitSet bitSet = new BitSet(128); 747 copyFromLong(bitSet, 0, bits0); 748 copyFromLong(bitSet, 64, bits1); 749 return bitSet; 750 } 751 public Iterator<Integer> iterator() { 752 return new Iterator<Integer>() { 753 long bits0 = Mid128.this.bits0; 754 long bits1 = Mid128.this.bits1; 755 int pos = -1; 756 public boolean hasNext() { 757 if (bits0 != 0) { 758 if (bits0 == Long.MIN_VALUE) { 759 pos = 63; 760 bits0 = 0; 761 return true; 762 } 763 long b = (bits0&-bits0); 764 int delta = 0; 765 while (b >= 256) { 766 b = (b >> 8); 767 delta += 8; 768 } 769 int p = bitPositionTable[(int) b]; 770 if (p >= 0) { 771 p += delta; 772 } else { 773 p = delta; 774 } 775 if (pos < 0) { 776 pos = p; 777 } else if (p == 0) { 778 pos++; 779 } else { 780 pos += (p + 1); 781 } 782 bits0 = bits0 >>> (p + 1); 783 return true; 784 } else { 785 if (pos < 63) { 786 pos = 63; 787 } 788 if (bits1 == Long.MIN_VALUE) { 789 pos = 127; 790 bits1 = 0; 791 return true; 792 } 793 long b = (bits1&-bits1); 794 if (b == 0) { 795 return false; 796 } 797 int delta = 0; 798 while (b >= 256) { 799 b = (b >> 8); 800 delta += 8; 801 } 802 int p = bitPositionTable[(int) b]; 803 if (p >= 0) { 804 p += delta; 805 } else { 806 p = delta; 807 } 808 if (pos < 0) { 809 pos = p; 810 } else if (p == 63) { 811 pos++; 812 } else { 813 pos += (p + 1); 814 } 815 bits1 = bits1 >>> (p + 1); 816 return true; 817 } 818 } 819 public Integer next() { 820 return Integer.valueOf(pos); 821 } 822 public void remove() { 823 throw new UnsupportedOperationException("remove"); 824 } 825 }; 826 } 827 828 public boolean equals(Object o) { 829 if (this == o) { 830 return true; 831 } 832 if (o instanceof BitKey.Small) { 833 BitKey.Small other = (BitKey.Small) o; 834 return (this.bits0 == other.bits) && (this.bits1 == 0); 835 836 } else if (o instanceof BitKey.Mid128) { 837 BitKey.Mid128 other = (BitKey.Mid128) o; 838 return (this.bits0 == other.bits0) && 839 (this.bits1 == other.bits1); 840 841 } else if (o instanceof BitKey.Big) { 842 BitKey.Big other = (BitKey.Big) o; 843 if (this.bits0 != other.bits[0]) { 844 return false; 845 } else if (this.bits1 != other.bits[1]) { 846 return false; 847 } else { 848 for (int i = 2; i < other.bits.length; i++) { 849 if (other.bits[i] != 0) { 850 return false; 851 } 852 } 853 return true; 854 } 855 } 856 return false; 857 } 858 public int hashCode() { 859 long h = 1234; 860 h ^= bits0; 861 h ^= bits1 * 2; 862 return (int)((h >> 32) ^ h); 863 } 864 public String toString() { 865 StringBuilder buf = new StringBuilder(64); 866 buf.append("0x"); 867 for (int i = 127; i >= 0; i--) { 868 buf.append((get(i)) ? '1' : '0'); 869 } 870 return buf.toString(); 871 } 872 public BitKey copy() { 873 return new Mid128(this); 874 } 875 public BitKey emptyCopy() { 876 return new Mid128(); 877 } 878 879 public boolean isEmpty() { 880 return bits0 == 0 && 881 bits1 == 0; 882 } 883 884 // implement Comparable (in lazy, expensive fashion) 885 public int compareTo(BitKey bitKey) { 886 return toString().compareTo(bitKey.toString()); 887 } 888 } 889 890 /** 891 * Implementation of {@link BitKey} with more than 64 bits. Similar to 892 * {@link java.util.BitSet}, but does not require dynamic resizing. 893 */ 894 public class Big extends AbstractBitKey { 895 private long[] bits; 896 897 private Big(int size) { 898 bits = new long[chunkCount(size + 1)]; 899 } 900 private Big(Big big) { 901 bits = (long[]) big.bits.clone(); 902 } 903 private int size() { 904 return bits.length; 905 } 906 public void set(int pos) { 907 bits[chunkPos(pos)] |= bit(pos); 908 } 909 910 public boolean get(int pos) { 911 return (bits[chunkPos(pos)] & bit(pos)) != 0; 912 } 913 public void clear(int pos) { 914 bits[chunkPos(pos)] &= ~bit(pos); 915 } 916 public void clear() { 917 for (int i = 0; i < bits.length; i++) { 918 bits[i] = 0; 919 } 920 } 921 private void or(long bits0) { 922 this.bits[0] |= bits0; 923 } 924 private void or(long bits0, long bits1) { 925 this.bits[0] |= bits0; 926 this.bits[1] |= bits1; 927 } 928 private void or(long[] bits) { 929 for (int i = 0; i < bits.length; i++) { 930 this.bits[i] |= bits[i]; 931 } 932 } 933 private void and(long[] bits) { 934 int length = Math.min(bits.length, this.bits.length); 935 for (int i = 0; i < length; i++) { 936 this.bits[i] &= bits[i]; 937 } 938 for (int i = bits.length; i < this.bits.length; i++) { 939 this.bits[i] = 0; 940 } 941 } 942 943 public BitKey or(BitKey bitKey) { 944 if (bitKey instanceof BitKey.Small) { 945 final BitKey.Small other = (BitKey.Small) bitKey; 946 final BitKey.Big bk = (BitKey.Big) copy(); 947 bk.or(other.bits); 948 return bk; 949 950 } else if (bitKey instanceof BitKey.Mid128) { 951 final BitKey.Mid128 other = (BitKey.Mid128) bitKey; 952 final BitKey.Big bk = (BitKey.Big) copy(); 953 bk.or(other.bits0, other.bits1); 954 return bk; 955 956 } else if (bitKey instanceof BitKey.Big) { 957 final BitKey.Big other = (BitKey.Big) bitKey; 958 if (other.size() > size()) { 959 final BitKey.Big bk = (BitKey.Big) other.copy(); 960 bk.or(bits); 961 return bk; 962 } else { 963 final BitKey.Big bk = (BitKey.Big) copy(); 964 bk.or(other.bits); 965 return bk; 966 } 967 } 968 969 throw createException(bitKey); 970 } 971 972 public BitKey and(BitKey bitKey) { 973 if (bitKey instanceof BitKey.Small) { 974 final BitKey.Small bk = (BitKey.Small) bitKey.copy(); 975 bk.and(bits[0]); 976 return bk; 977 978 } else if (bitKey instanceof BitKey.Mid128) { 979 final BitKey.Mid128 bk = (BitKey.Mid128) bitKey.copy(); 980 bk.and(bits[0], bits[1]); 981 return bk; 982 983 } else if (bitKey instanceof BitKey.Big) { 984 final BitKey.Big other = (BitKey.Big) bitKey; 985 if (other.size() < size()) { 986 final BitKey.Big bk = (BitKey.Big) other.copy(); 987 bk.and(bits); 988 return bk; 989 } else { 990 final BitKey.Big bk = (BitKey.Big) copy(); 991 bk.and(other.bits); 992 return bk; 993 } 994 } 995 996 throw createException(bitKey); 997 } 998 999 public BitKey andNot(BitKey bitKey) { 1000 if (bitKey instanceof BitKey.Small) { 1001 final BitKey.Small other = (BitKey.Small) bitKey; 1002 final BitKey.Big bk = (BitKey.Big) copy(); 1003 bk.andNot(other.bits); 1004 return bk; 1005 1006 } else if (bitKey instanceof BitKey.Mid128) { 1007 final BitKey.Mid128 other = (Mid128) bitKey; 1008 final BitKey.Big bk = (BitKey.Big) copy(); 1009 bk.andNot(other.bits0, other.bits1); 1010 return bk; 1011 1012 } else if (bitKey instanceof BitKey.Big) { 1013 final BitKey.Big other = (BitKey.Big) bitKey; 1014 final BitKey.Big bk = (BitKey.Big) copy(); 1015 bk.andNot(other.bits); 1016 return bk; 1017 } 1018 1019 throw createException(bitKey); 1020 } 1021 1022 private void andNot(long[] bits) { 1023 for (int i = 0; i < bits.length; i++) { 1024 this.bits[i] &= ~bits[i]; 1025 1026 } 1027 } 1028 1029 private void andNot(long bits0, long bits1) { 1030 this.bits[0] &= ~bits0; 1031 this.bits[1] &= ~bits1; 1032 } 1033 1034 private void andNot(long bits) { 1035 this.bits[0] &= ~bits; 1036 } 1037 1038 public boolean isSuperSetOf(BitKey bitKey) { 1039 if (bitKey instanceof BitKey.Small) { 1040 BitKey.Small other = (BitKey.Small) bitKey; 1041 return ((this.bits[0] | other.bits) == this.bits[0]); 1042 1043 } else if (bitKey instanceof BitKey.Mid128) { 1044 BitKey.Mid128 other = (BitKey.Mid128) bitKey; 1045 return ((this.bits[0] | other.bits0) == this.bits[0]) && 1046 ((this.bits[1] | other.bits1) == this.bits[1]); 1047 1048 } else if (bitKey instanceof BitKey.Big) { 1049 BitKey.Big other = (BitKey.Big) bitKey; 1050 1051 int len = Math.min(bits.length, other.bits.length); 1052 for (int i = 0; i < len; i++) { 1053 if ((this.bits[i] | other.bits[i]) != this.bits[i]) { 1054 return false; 1055 } 1056 } 1057 if (other.bits.length > this.bits.length) { 1058 for (int i = len; i < other.bits.length; i++) { 1059 if (other.bits[i] != 0) { 1060 return false; 1061 } 1062 } 1063 } 1064 return true; 1065 } 1066 return false; 1067 } 1068 1069 public boolean intersects(BitKey bitKey) { 1070 if (bitKey instanceof BitKey.Small) { 1071 BitKey.Small other = (BitKey.Small) bitKey; 1072 return (this.bits[0] & other.bits) != 0; 1073 1074 } else if (bitKey instanceof BitKey.Mid128) { 1075 BitKey.Mid128 other = (BitKey.Mid128) bitKey; 1076 return (this.bits[0] & other.bits0) != 0 || 1077 (this.bits[1] & other.bits1) != 0; 1078 1079 } else if (bitKey instanceof BitKey.Big) { 1080 BitKey.Big other = (BitKey.Big) bitKey; 1081 1082 int len = Math.min(bits.length, other.bits.length); 1083 for (int i = 0; i < len; i++) { 1084 if ((this.bits[i] & other.bits[i]) != 0) { 1085 return true; 1086 } 1087 } 1088 return false; 1089 } 1090 return false; 1091 } 1092 1093 public BitSet toBitSet() { 1094 final BitSet bitSet = new BitSet(64); 1095 int pos = 0; 1096 for (int i = 0; i < bits.length; i++) { 1097 copyFromLong(bitSet, pos, bits[i]); 1098 pos += 64; 1099 } 1100 return bitSet; 1101 } 1102 public Iterator<Integer> iterator() { 1103 return new Iterator<Integer>() { 1104 long[] bits = Big.this.bits.clone(); 1105 int pos = -1; 1106 int index = 0; 1107 public boolean hasNext() { 1108 if (index >= bits.length) { 1109 return false; 1110 } 1111 if (pos < 0) { 1112 while (bits[index] == 0) { 1113 index++; 1114 if (index >= bits.length) { 1115 return false; 1116 } 1117 } 1118 pos = (64 * index) - 1; 1119 } 1120 long bs = bits[index]; 1121 if (bs == 0) { 1122 while (bits[index] == 0) { 1123 index++; 1124 if (index >= bits.length) { 1125 return false; 1126 } 1127 } 1128 pos = (64 * index) - 1; 1129 bs = bits[index]; 1130 } 1131 if (bs != 0) { 1132 if (bs == Long.MIN_VALUE) { 1133 pos = (64 * index) + 63; 1134 bits[index] = 0; 1135 return true; 1136 } 1137 long b = (bs&-bs); 1138 int delta = 0; 1139 while (b >= 256) { 1140 b = (b >> 8); 1141 delta += 8; 1142 } 1143 int p = bitPositionTable[(int) b]; 1144 if (p >= 0) { 1145 p += delta; 1146 } else { 1147 p = delta; 1148 } 1149 if (pos < 0) { 1150 pos = p; 1151 } else if (p == 0) { 1152 pos++; 1153 } else { 1154 pos += (p + 1); 1155 } 1156 bits[index] = bits[index] >>> (p + 1); 1157 return true; 1158 } 1159 return false; 1160 } 1161 public Integer next() { 1162 return Integer.valueOf(pos); 1163 } 1164 public void remove() { 1165 throw new UnsupportedOperationException("remove"); 1166 } 1167 }; 1168 } 1169 public boolean equals(Object o) { 1170 if (this == o) { 1171 return true; 1172 } 1173 if (o instanceof BitKey.Small) { 1174 BitKey.Small other = (BitKey.Small) o; 1175 if (this.bits[0] != other.bits) { 1176 return false; 1177 } else { 1178 for (int i = 1; i < this.bits.length; i++) { 1179 if (this.bits[i] != 0) { 1180 return false; 1181 } 1182 } 1183 return true; 1184 } 1185 1186 } else if (o instanceof BitKey.Mid128) { 1187 BitKey.Mid128 other = (BitKey.Mid128) o; 1188 if (this.bits[0] != other.bits0) { 1189 return false; 1190 } else if (this.bits[1] != other.bits1) { 1191 return false; 1192 } else { 1193 for (int i = 2; i < this.bits.length; i++) { 1194 if (this.bits[i] != 0) { 1195 return false; 1196 } 1197 } 1198 return true; 1199 } 1200 1201 } else if (o instanceof BitKey.Big) { 1202 BitKey.Big other = (BitKey.Big) o; 1203 1204 int len = Math.min(bits.length, other.bits.length); 1205 for (int i = 0; i < len; i++) { 1206 if (this.bits[i] != other.bits[i]) { 1207 return false; 1208 } 1209 } 1210 if (this.bits.length > other.bits.length) { 1211 for (int i = len; i < this.bits.length; i++) { 1212 if (this.bits[i] != 0) { 1213 return false; 1214 } 1215 } 1216 } else if (other.bits.length > this.bits.length) { 1217 for (int i = len; i < other.bits.length; i++) { 1218 if (other.bits[i] != 0) { 1219 return false; 1220 } 1221 } 1222 } 1223 return true; 1224 } 1225 return false; 1226 } 1227 public int hashCode() { 1228 long h = 1234; 1229 for (int i = bits.length; --i >= 0;) { 1230 h ^= bits[i] * (i + 1); 1231 } 1232 return (int)((h >> 32) ^ h); 1233 } 1234 public String toString() { 1235 StringBuilder buf = new StringBuilder(64); 1236 buf.append("0x"); 1237 int start = bits.length * 64 - 1; 1238 for (int i = start; i >= 0; i--) { 1239 buf.append((get(i)) ? '1' : '0'); 1240 } 1241 return buf.toString(); 1242 } 1243 1244 public BitKey copy() { 1245 return new Big(this); 1246 } 1247 1248 public BitKey emptyCopy() { 1249 return new Big(bits.length << ChunkBitCount); 1250 } 1251 1252 public boolean isEmpty() { 1253 for (long bit : bits) { 1254 if (bit != 0) { 1255 return false; 1256 } 1257 } 1258 return true; 1259 } 1260 1261 // implement Comparable (in lazy, expensive fashion) 1262 public int compareTo(BitKey bitKey) { 1263 return toString().compareTo(bitKey.toString()); 1264 } 1265 } 1266 1267 final static byte bitPositionTable[] = { 1268 -1, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 1269 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 1270 5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 1271 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 1272 6, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 1273 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 1274 5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 1275 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 1276 7, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 1277 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 1278 5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 1279 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 1280 6, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 1281 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 1282 5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 1283 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0}; 1284 1285 1286 } 1287 1288 // End BitKey.java