-
Notifications
You must be signed in to change notification settings - Fork 73
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
7 changed files
with
277 additions
and
855 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,240 @@ | ||
/* | ||
* Copyright (c) 1995, 2020, Oracle and/or its affiliates. All rights reserved. | ||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. | ||
* | ||
* This code is free software; you can redistribute it and/or modify it | ||
* under the terms of the GNU General Public License version 2 only, as | ||
* published by the Free Software Foundation. Oracle designates this | ||
* particular file as subject to the "Classpath" exception as provided | ||
* by Oracle in the LICENSE file that accompanied this code. | ||
* | ||
* This code is distributed in the hope that it will be useful, but WITHOUT | ||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | ||
* version 2 for more details (a copy is included in the LICENSE file that | ||
* accompanied this code). | ||
* | ||
* You should have received a copy of the GNU General Public License version | ||
* 2 along with this work; if not, write to the Free Software Foundation, | ||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. | ||
* | ||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA | ||
* or visit www.oracle.com if you need additional information or have any | ||
* questions. | ||
*/ | ||
|
||
package dr.app.tools.treeannotator; | ||
|
||
import java.io.*; | ||
import java.util.Arrays; | ||
|
||
/** | ||
* This class implements a vector of bits that grows as needed. Each | ||
* component of the bit set has a {@code boolean} value. The | ||
* bits of a {@code BitSet} are indexed by nonnegative integers. | ||
* Individual indexed bits can be examined, set, or cleared. One | ||
* {@code BitSet} may be used to modify the contents of another | ||
* {@code BitSet} through logical AND, logical inclusive OR, and | ||
* logical exclusive OR operations. | ||
* | ||
* <p>By default, all bits in the set initially have the value | ||
* {@code false}. | ||
* | ||
* <p>Every bit set has a current size, which is the number of bits | ||
* of space currently in use by the bit set. Note that the size is | ||
* related to the implementation of a bit set, so it may change with | ||
* implementation. The length of a bit set relates to logical length | ||
* of a bit set and is defined independently of implementation. | ||
* | ||
* <p>Unless otherwise noted, passing a null parameter to any of the | ||
* methods in a {@code BitSet} will result in a | ||
* {@code NullPointerException}. | ||
* | ||
* <p>A {@code BitSet} is not safe for multithreaded use without | ||
* external synchronization. | ||
* | ||
* @author Arthur van Hoff | ||
* @author Michael McCloskey | ||
* @author Martin Buchholz | ||
* @since 1.0 | ||
*/ | ||
public class CladeKey { | ||
/* | ||
* BitSets are packed into arrays of "words." Currently a word is | ||
* a long, which consists of 64 bits, requiring 6 address bits. | ||
* The choice of word size is determined purely by performance concerns. | ||
*/ | ||
private static final int ADDRESS_BITS_PER_WORD = 6; | ||
private static final int BITS_PER_WORD = 1 << ADDRESS_BITS_PER_WORD; | ||
/* Used to shift left or right for a partial word mask */ | ||
private static final long WORD_MASK = 0xffffffffffffffffL; | ||
|
||
/** | ||
* The internal field corresponding to the serialField "bits". | ||
*/ | ||
private long[] words; | ||
|
||
/** | ||
* The number of words in the logical size of this BitSet. | ||
*/ | ||
private transient int wordsInUse = 0; | ||
|
||
/** | ||
* Given a bit index, return word index containing it. | ||
*/ | ||
private static int wordIndex(int bitIndex) { | ||
return bitIndex >> ADDRESS_BITS_PER_WORD; | ||
} | ||
|
||
/** | ||
* Creates a new bit set. All bits are initially {@code false}. | ||
*/ | ||
public CladeKey() { | ||
words = new long[wordIndex(CladeKey.BITS_PER_WORD -1) + 1]; | ||
} | ||
|
||
public CladeKey(int bitIndex) { | ||
words = new long[wordIndex(CladeKey.BITS_PER_WORD -1) + 1]; | ||
set(bitIndex); | ||
} | ||
|
||
public long[] toLongArray() { | ||
return Arrays.copyOf(words, wordsInUse); | ||
} | ||
|
||
|
||
public void clear() { | ||
while (wordsInUse > 0) | ||
words[--wordsInUse] = 0; | ||
} | ||
|
||
public boolean get(int bitIndex) { | ||
int wordIndex = wordIndex(bitIndex); | ||
return (wordIndex < wordsInUse) | ||
&& ((words[wordIndex] & (1L << bitIndex)) != 0); | ||
} | ||
|
||
public void set(int bitIndex) { | ||
int wordIndex = wordIndex(bitIndex); | ||
int wordsRequired = wordIndex+1; | ||
if (wordsInUse < wordsRequired) { | ||
if (words.length < wordsRequired) { | ||
// Allocate larger of doubled size or required size | ||
int request = Math.max(2 * words.length, wordsRequired); | ||
words = Arrays.copyOf(words, request); | ||
} | ||
wordsInUse = wordsRequired; | ||
} | ||
|
||
words[wordIndex] |= (1L << bitIndex); // Restores invariants | ||
} | ||
|
||
public void set(CladeKey set) { | ||
words = Arrays.copyOf(set.words, set.wordsInUse); | ||
wordsInUse = set.wordsInUse; | ||
} | ||
|
||
|
||
public boolean isEmpty() { | ||
return wordsInUse == 0; | ||
} | ||
|
||
public int cardinality() { | ||
int sum = 0; | ||
for (int i = 0; i < wordsInUse; i++) | ||
sum += Long.bitCount(words[i]); | ||
return sum; | ||
} | ||
|
||
public void or(CladeKey key1, CladeKey key2) { | ||
|
||
if (key1.wordsInUse >= key2.wordsInUse) { | ||
wordsInUse = key1.wordsInUse; | ||
words = Arrays.copyOf(key1.words, wordsInUse); | ||
for (int i = 0; i < wordsInUse; i++) { | ||
words[i] |= key2.words[i]; | ||
} | ||
} else { | ||
wordsInUse = key2.wordsInUse; | ||
words = Arrays.copyOf(key2.words, wordsInUse); | ||
for (int i = 0; i < wordsInUse; i++) { | ||
words[i] |= key1.words[i]; | ||
} | ||
} | ||
} | ||
|
||
|
||
/** | ||
* Returns the hash code value for this bit set. The hash code depends | ||
* only on which bits are set within this {@code BitSet}. | ||
* | ||
* <p>The hash code is defined to be the result of the following | ||
* calculation: | ||
* <pre> {@code | ||
* public int hashCode() { | ||
* long h = 1234; | ||
* long[] words = toLongArray(); | ||
* for (int i = words.length; --i >= 0; ) | ||
* h ^= words[i] * (i + 1); | ||
* return (int)((h >> 32) ^ h); | ||
* }}</pre> | ||
* Note that the hash code changes if the set of bits is altered. | ||
* | ||
* @return the hash code value for this bit set | ||
*/ | ||
public int hashCode() { | ||
long h = 1234; | ||
for (int i = wordsInUse; --i >= 0; ) | ||
h ^= words[i] * (i + 1); | ||
|
||
return (int)((h >> 32) ^ h); | ||
} | ||
|
||
|
||
public boolean equals(Object obj) { | ||
if (!(obj instanceof CladeKey set)) | ||
return false; | ||
if (this == obj) | ||
return true; | ||
|
||
if (wordsInUse != set.wordsInUse) | ||
return false; | ||
|
||
// Check words in use by both BitSets | ||
for (int i = 0; i < wordsInUse; i++) | ||
if (words[i] != set.words[i]) | ||
return false; | ||
|
||
return true; | ||
} | ||
|
||
/** | ||
* Returns the index of the first bit that is set to {@code true} | ||
* that occurs on or after the specified starting index and up to and | ||
* including the specified word index | ||
* If no such bit exists then {@code -1} is returned. | ||
* | ||
* @param fromIndex the index to start checking from (inclusive) | ||
* @param toWordIndex the last word index to check (inclusive) | ||
* @return the index of the next set bit, or {@code -1} if there | ||
* is no such bit | ||
*/ | ||
private int nextSetBit(int fromIndex, int toWordIndex) { | ||
int u = wordIndex(fromIndex); | ||
// Check if out of bounds | ||
if (u > toWordIndex) | ||
return -1; | ||
|
||
long word = words[u] & (WORD_MASK << fromIndex); | ||
|
||
while (true) { | ||
if (word != 0) | ||
return (u * BITS_PER_WORD) + Long.numberOfTrailingZeros(word); | ||
// Check if out of bounds | ||
if (++u > toWordIndex) | ||
return -1; | ||
word = words[u]; | ||
} | ||
} | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.