mirror of
https://github.com/marcin-szczepanski/jFuzzyLogic.git
synced 2024-08-16 18:06:57 +02:00
575 lines
16 KiB
Java
575 lines
16 KiB
Java
![]() |
/*
|
||
|
[The "BSD licence"]
|
||
|
Copyright (c) 2005-2006 Terence Parr
|
||
|
All rights reserved.
|
||
|
|
||
|
Redistribution and use in source and binary forms, with or without
|
||
|
modification, are permitted provided that the following conditions
|
||
|
are met:
|
||
|
1. Redistributions of source code must retain the above copyright
|
||
|
notice, this list of conditions and the following disclaimer.
|
||
|
2. Redistributions in binary form must reproduce the above copyright
|
||
|
notice, this list of conditions and the following disclaimer in the
|
||
|
documentation and/or other materials provided with the distribution.
|
||
|
3. The name of the author may not be used to endorse or promote products
|
||
|
derived from this software without specific prior written permission.
|
||
|
|
||
|
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||
|
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||
|
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||
|
IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||
|
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||
|
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||
|
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||
|
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||
|
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||
|
*/
|
||
|
package org.antlr.misc;
|
||
|
|
||
|
import org.antlr.analysis.Label;
|
||
|
import org.antlr.tool.Grammar;
|
||
|
|
||
|
import java.util.Collection;
|
||
|
import java.util.Iterator;
|
||
|
import java.util.List;
|
||
|
import java.util.Map;
|
||
|
|
||
|
/**A BitSet to replace java.util.BitSet.
|
||
|
*
|
||
|
* Primary differences are that most set operators return new sets
|
||
|
* as opposed to oring and anding "in place". Further, a number of
|
||
|
* operations were added. I cannot contain a BitSet because there
|
||
|
* is no way to access the internal bits (which I need for speed)
|
||
|
* and, because it is final, I cannot subclass to add functionality.
|
||
|
* Consider defining set degree. Without access to the bits, I must
|
||
|
* call a method n times to test the ith bit...ack!
|
||
|
*
|
||
|
* Also seems like or() from util is wrong when size of incoming set is bigger
|
||
|
* than this.bits.length.
|
||
|
*
|
||
|
* @author Terence Parr
|
||
|
*/
|
||
|
public class BitSet implements IntSet, Cloneable {
|
||
|
protected final static int BITS = 64; // number of bits / long
|
||
|
protected final static int LOG_BITS = 6; // 2^6 == 64
|
||
|
|
||
|
/* We will often need to do a mod operator (i mod nbits). Its
|
||
|
* turns out that, for powers of two, this mod operation is
|
||
|
* same as (i & (nbits-1)). Since mod is slow, we use a
|
||
|
* precomputed mod mask to do the mod instead.
|
||
|
*/
|
||
|
protected final static int MOD_MASK = BITS - 1;
|
||
|
|
||
|
/** The actual data bits */
|
||
|
protected long bits[];
|
||
|
|
||
|
/** Construct a bitset of size one word (64 bits) */
|
||
|
public BitSet() {
|
||
|
this(BITS);
|
||
|
}
|
||
|
|
||
|
/** Construction from a static array of longs */
|
||
|
public BitSet(long[] bits_) {
|
||
|
bits = bits_;
|
||
|
}
|
||
|
|
||
|
/** Construct a bitset given the size
|
||
|
* @param nbits The size of the bitset in bits
|
||
|
*/
|
||
|
public BitSet(int nbits) {
|
||
|
bits = new long[((nbits - 1) >> LOG_BITS) + 1];
|
||
|
}
|
||
|
|
||
|
/** or this element into this set (grow as necessary to accommodate) */
|
||
|
public void add(int el) {
|
||
|
//System.out.println("add("+el+")");
|
||
|
int n = wordNumber(el);
|
||
|
//System.out.println("word number is "+n);
|
||
|
//System.out.println("bits.length "+bits.length);
|
||
|
if (n >= bits.length) {
|
||
|
growToInclude(el);
|
||
|
}
|
||
|
bits[n] |= bitMask(el);
|
||
|
}
|
||
|
|
||
|
public void addAll(IntSet set) {
|
||
|
if ( set instanceof BitSet ) {
|
||
|
this.orInPlace((BitSet)set);
|
||
|
}
|
||
|
else if ( set instanceof IntervalSet ) {
|
||
|
IntervalSet other = (IntervalSet)set;
|
||
|
// walk set and add each interval
|
||
|
for (Iterator iter = other.intervals.iterator(); iter.hasNext();) {
|
||
|
Interval I = (Interval) iter.next();
|
||
|
this.orInPlace(BitSet.range(I.a,I.b));
|
||
|
}
|
||
|
}
|
||
|
else {
|
||
|
throw new IllegalArgumentException("can't add "+
|
||
|
set.getClass().getName()+
|
||
|
" to BitSet");
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public void addAll(int[] elements) {
|
||
|
if ( elements==null ) {
|
||
|
return;
|
||
|
}
|
||
|
for (int i = 0; i < elements.length; i++) {
|
||
|
int e = elements[i];
|
||
|
add(e);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public void addAll(Iterable elements) {
|
||
|
if ( elements==null ) {
|
||
|
return;
|
||
|
}
|
||
|
Iterator it = elements.iterator();
|
||
|
while (it.hasNext()) {
|
||
|
Object o = (Object) it.next();
|
||
|
if ( !(o instanceof Integer) ) {
|
||
|
throw new IllegalArgumentException();
|
||
|
}
|
||
|
Integer eI = (Integer)o;
|
||
|
add(eI.intValue());
|
||
|
}
|
||
|
/*
|
||
|
int n = elements.size();
|
||
|
for (int i = 0; i < n; i++) {
|
||
|
Object o = elements.get(i);
|
||
|
if ( !(o instanceof Integer) ) {
|
||
|
throw new IllegalArgumentException();
|
||
|
}
|
||
|
Integer eI = (Integer)o;
|
||
|
add(eI.intValue());
|
||
|
}
|
||
|
*/
|
||
|
}
|
||
|
|
||
|
public IntSet and(IntSet a) {
|
||
|
BitSet s = (BitSet)this.clone();
|
||
|
s.andInPlace((BitSet)a);
|
||
|
return s;
|
||
|
}
|
||
|
|
||
|
public void andInPlace(BitSet a) {
|
||
|
int min = Math.min(bits.length, a.bits.length);
|
||
|
for (int i = min - 1; i >= 0; i--) {
|
||
|
bits[i] &= a.bits[i];
|
||
|
}
|
||
|
// clear all bits in this not present in a (if this bigger than a).
|
||
|
for (int i = min; i < bits.length; i++) {
|
||
|
bits[i] = 0;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
private final static long bitMask(int bitNumber) {
|
||
|
int bitPosition = bitNumber & MOD_MASK; // bitNumber mod BITS
|
||
|
return 1L << bitPosition;
|
||
|
}
|
||
|
|
||
|
public void clear() {
|
||
|
for (int i = bits.length - 1; i >= 0; i--) {
|
||
|
bits[i] = 0;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public void clear(int el) {
|
||
|
int n = wordNumber(el);
|
||
|
if (n >= bits.length) { // grow as necessary to accommodate
|
||
|
growToInclude(el);
|
||
|
}
|
||
|
bits[n] &= ~bitMask(el);
|
||
|
}
|
||
|
|
||
|
public Object clone() {
|
||
|
BitSet s;
|
||
|
try {
|
||
|
s = (BitSet)super.clone();
|
||
|
s.bits = new long[bits.length];
|
||
|
System.arraycopy(bits, 0, s.bits, 0, bits.length);
|
||
|
}
|
||
|
catch (CloneNotSupportedException e) {
|
||
|
throw new InternalError();
|
||
|
}
|
||
|
return s;
|
||
|
}
|
||
|
|
||
|
public int size() {
|
||
|
int deg = 0;
|
||
|
for (int i = bits.length - 1; i >= 0; i--) {
|
||
|
long word = bits[i];
|
||
|
if (word != 0L) {
|
||
|
for (int bit = BITS - 1; bit >= 0; bit--) {
|
||
|
if ((word & (1L << bit)) != 0) {
|
||
|
deg++;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
return deg;
|
||
|
}
|
||
|
|
||
|
public boolean equals(Object other) {
|
||
|
if ( other == null || !(other instanceof BitSet) ) {
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
BitSet otherSet = (BitSet)other;
|
||
|
|
||
|
int n = Math.min(this.bits.length, otherSet.bits.length);
|
||
|
|
||
|
// for any bits in common, compare
|
||
|
for (int i=0; i<n; i++) {
|
||
|
if (this.bits[i] != otherSet.bits[i]) {
|
||
|
return false;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// make sure any extra bits are off
|
||
|
|
||
|
if (this.bits.length > n) {
|
||
|
for (int i = n+1; i<this.bits.length; i++) {
|
||
|
if (this.bits[i] != 0) {
|
||
|
return false;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
else if (otherSet.bits.length > n) {
|
||
|
for (int i = n+1; i<otherSet.bits.length; i++) {
|
||
|
if (otherSet.bits[i] != 0) {
|
||
|
return false;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Grows the set to a larger number of bits.
|
||
|
* @param bit element that must fit in set
|
||
|
*/
|
||
|
public void growToInclude(int bit) {
|
||
|
int newSize = Math.max(bits.length << 1, numWordsToHold(bit));
|
||
|
long newbits[] = new long[newSize];
|
||
|
System.arraycopy(bits, 0, newbits, 0, bits.length);
|
||
|
bits = newbits;
|
||
|
}
|
||
|
|
||
|
public boolean member(int el) {
|
||
|
int n = wordNumber(el);
|
||
|
if (n >= bits.length) return false;
|
||
|
return (bits[n] & bitMask(el)) != 0;
|
||
|
}
|
||
|
|
||
|
/** Get the first element you find and return it. Return Label.INVALID
|
||
|
* otherwise.
|
||
|
*/
|
||
|
public int getSingleElement() {
|
||
|
for (int i = 0; i < (bits.length << LOG_BITS); i++) {
|
||
|
if (member(i)) {
|
||
|
return i;
|
||
|
}
|
||
|
}
|
||
|
return Label.INVALID;
|
||
|
}
|
||
|
|
||
|
public boolean isNil() {
|
||
|
for (int i = bits.length - 1; i >= 0; i--) {
|
||
|
if (bits[i] != 0) return false;
|
||
|
}
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
public IntSet complement() {
|
||
|
BitSet s = (BitSet)this.clone();
|
||
|
s.notInPlace();
|
||
|
return s;
|
||
|
}
|
||
|
|
||
|
public IntSet complement(IntSet set) {
|
||
|
if ( set==null ) {
|
||
|
return this.complement();
|
||
|
}
|
||
|
return set.subtract(this);
|
||
|
}
|
||
|
|
||
|
public void notInPlace() {
|
||
|
for (int i = bits.length - 1; i >= 0; i--) {
|
||
|
bits[i] = ~bits[i];
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/** complement bits in the range 0..maxBit. */
|
||
|
public void notInPlace(int maxBit) {
|
||
|
notInPlace(0, maxBit);
|
||
|
}
|
||
|
|
||
|
/** complement bits in the range minBit..maxBit.*/
|
||
|
public void notInPlace(int minBit, int maxBit) {
|
||
|
// make sure that we have room for maxBit
|
||
|
growToInclude(maxBit);
|
||
|
for (int i = minBit; i <= maxBit; i++) {
|
||
|
int n = wordNumber(i);
|
||
|
bits[n] ^= bitMask(i);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
private final int numWordsToHold(int el) {
|
||
|
return (el >> LOG_BITS) + 1;
|
||
|
}
|
||
|
|
||
|
public static BitSet of(int el) {
|
||
|
BitSet s = new BitSet(el + 1);
|
||
|
s.add(el);
|
||
|
return s;
|
||
|
}
|
||
|
|
||
|
public static BitSet of(Collection elements) {
|
||
|
BitSet s = new BitSet();
|
||
|
Iterator iter = elements.iterator();
|
||
|
while (iter.hasNext()) {
|
||
|
Integer el = (Integer) iter.next();
|
||
|
s.add(el.intValue());
|
||
|
}
|
||
|
return s;
|
||
|
}
|
||
|
|
||
|
public static BitSet of(IntSet set) {
|
||
|
if ( set==null ) {
|
||
|
return null;
|
||
|
}
|
||
|
|
||
|
if ( set instanceof BitSet ) {
|
||
|
return (BitSet)set;
|
||
|
}
|
||
|
if ( set instanceof IntervalSet ) {
|
||
|
BitSet s = new BitSet();
|
||
|
s.addAll(set);
|
||
|
return s;
|
||
|
}
|
||
|
throw new IllegalArgumentException("can't create BitSet from "+set.getClass().getName());
|
||
|
}
|
||
|
|
||
|
public static BitSet of(Map elements) {
|
||
|
return BitSet.of(elements.keySet());
|
||
|
}
|
||
|
|
||
|
public static BitSet range(int a, int b) {
|
||
|
BitSet s = new BitSet(b + 1);
|
||
|
for (int i = a; i <= b; i++) {
|
||
|
int n = wordNumber(i);
|
||
|
s.bits[n] |= bitMask(i);
|
||
|
}
|
||
|
return s;
|
||
|
}
|
||
|
|
||
|
/** return this | a in a new set */
|
||
|
public IntSet or(IntSet a) {
|
||
|
if ( a==null ) {
|
||
|
return this;
|
||
|
}
|
||
|
BitSet s = (BitSet)this.clone();
|
||
|
s.orInPlace((BitSet)a);
|
||
|
return s;
|
||
|
}
|
||
|
|
||
|
public void orInPlace(BitSet a) {
|
||
|
if ( a==null ) {
|
||
|
return;
|
||
|
}
|
||
|
// If this is smaller than a, grow this first
|
||
|
if (a.bits.length > bits.length) {
|
||
|
setSize(a.bits.length);
|
||
|
}
|
||
|
int min = Math.min(bits.length, a.bits.length);
|
||
|
for (int i = min - 1; i >= 0; i--) {
|
||
|
bits[i] |= a.bits[i];
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// remove this element from this set
|
||
|
public void remove(int el) {
|
||
|
int n = wordNumber(el);
|
||
|
if (n >= bits.length) {
|
||
|
growToInclude(el);
|
||
|
}
|
||
|
bits[n] &= ~bitMask(el);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Sets the size of a set.
|
||
|
* @param nwords how many words the new set should be
|
||
|
*/
|
||
|
private void setSize(int nwords) {
|
||
|
long newbits[] = new long[nwords];
|
||
|
int n = Math.min(nwords, bits.length);
|
||
|
System.arraycopy(bits, 0, newbits, 0, n);
|
||
|
bits = newbits;
|
||
|
}
|
||
|
|
||
|
public int numBits() {
|
||
|
return bits.length << LOG_BITS; // num words * bits per word
|
||
|
}
|
||
|
|
||
|
/** return how much space is being used by the bits array not
|
||
|
* how many actually have member bits on.
|
||
|
*/
|
||
|
public int lengthInLongWords() {
|
||
|
return bits.length;
|
||
|
}
|
||
|
|
||
|
/**Is this contained within a? */
|
||
|
public boolean subset(BitSet a) {
|
||
|
if (a == null) return false;
|
||
|
return this.and(a).equals(this);
|
||
|
}
|
||
|
|
||
|
/**Subtract the elements of 'a' from 'this' in-place.
|
||
|
* Basically, just turn off all bits of 'this' that are in 'a'.
|
||
|
*/
|
||
|
public void subtractInPlace(BitSet a) {
|
||
|
if (a == null) return;
|
||
|
// for all words of 'a', turn off corresponding bits of 'this'
|
||
|
for (int i = 0; i < bits.length && i < a.bits.length; i++) {
|
||
|
bits[i] &= ~a.bits[i];
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public IntSet subtract(IntSet a) {
|
||
|
if (a == null || !(a instanceof BitSet)) return null;
|
||
|
|
||
|
BitSet s = (BitSet)this.clone();
|
||
|
s.subtractInPlace((BitSet)a);
|
||
|
return s;
|
||
|
}
|
||
|
|
||
|
public List toList() {
|
||
|
throw new NoSuchMethodError("BitSet.toList() unimplemented");
|
||
|
}
|
||
|
|
||
|
public int[] toArray() {
|
||
|
int[] elems = new int[size()];
|
||
|
int en = 0;
|
||
|
for (int i = 0; i < (bits.length << LOG_BITS); i++) {
|
||
|
if (member(i)) {
|
||
|
elems[en++] = i;
|
||
|
}
|
||
|
}
|
||
|
return elems;
|
||
|
}
|
||
|
|
||
|
public long[] toPackedArray() {
|
||
|
return bits;
|
||
|
}
|
||
|
|
||
|
public String toString() {
|
||
|
return toString(null);
|
||
|
}
|
||
|
|
||
|
/** Transform a bit set into a string by formatting each element as an integer
|
||
|
* separator The string to put in between elements
|
||
|
* @return A commma-separated list of values
|
||
|
*/
|
||
|
public String toString(Grammar g) {
|
||
|
StringBuffer buf = new StringBuffer();
|
||
|
String separator = ",";
|
||
|
boolean havePrintedAnElement = false;
|
||
|
buf.append('{');
|
||
|
|
||
|
for (int i = 0; i < (bits.length << LOG_BITS); i++) {
|
||
|
if (member(i)) {
|
||
|
if (i > 0 && havePrintedAnElement ) {
|
||
|
buf.append(separator);
|
||
|
}
|
||
|
if ( g!=null ) {
|
||
|
buf.append(g.getTokenDisplayName(i));
|
||
|
}
|
||
|
else {
|
||
|
buf.append(i);
|
||
|
}
|
||
|
havePrintedAnElement = true;
|
||
|
}
|
||
|
}
|
||
|
buf.append('}');
|
||
|
return buf.toString();
|
||
|
}
|
||
|
|
||
|
/**Create a string representation where instead of integer elements, the
|
||
|
* ith element of vocabulary is displayed instead. Vocabulary is a Vector
|
||
|
* of Strings.
|
||
|
* separator The string to put in between elements
|
||
|
* @return A commma-separated list of character constants.
|
||
|
*/
|
||
|
public String toString(String separator, List vocabulary) {
|
||
|
if (vocabulary == null) {
|
||
|
return toString(null);
|
||
|
}
|
||
|
String str = "";
|
||
|
for (int i = 0; i < (bits.length << LOG_BITS); i++) {
|
||
|
if (member(i)) {
|
||
|
if (str.length() > 0) {
|
||
|
str += separator;
|
||
|
}
|
||
|
if (i >= vocabulary.size()) {
|
||
|
str += "'" + (char)i + "'";
|
||
|
}
|
||
|
else if (vocabulary.get(i) == null) {
|
||
|
str += "'" + (char)i + "'";
|
||
|
}
|
||
|
else {
|
||
|
str += (String)vocabulary.get(i);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
return str;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Dump a comma-separated list of the words making up the bit set.
|
||
|
* Split each 64 bit number into two more manageable 32 bit numbers.
|
||
|
* This generates a comma-separated list of C++-like unsigned long constants.
|
||
|
*/
|
||
|
public String toStringOfHalfWords() {
|
||
|
StringBuffer s = new StringBuffer();
|
||
|
for (int i = 0; i < bits.length; i++) {
|
||
|
if (i != 0) s.append(", ");
|
||
|
long tmp = bits[i];
|
||
|
tmp &= 0xFFFFFFFFL;
|
||
|
s.append(tmp);
|
||
|
s.append("UL");
|
||
|
s.append(", ");
|
||
|
tmp = bits[i] >>> 32;
|
||
|
tmp &= 0xFFFFFFFFL;
|
||
|
s.append(tmp);
|
||
|
s.append("UL");
|
||
|
}
|
||
|
return s.toString();
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Dump a comma-separated list of the words making up the bit set.
|
||
|
* This generates a comma-separated list of Java-like long int constants.
|
||
|
*/
|
||
|
public String toStringOfWords() {
|
||
|
StringBuffer s = new StringBuffer();
|
||
|
for (int i = 0; i < bits.length; i++) {
|
||
|
if (i != 0) s.append(", ");
|
||
|
s.append(bits[i]);
|
||
|
s.append("L");
|
||
|
}
|
||
|
return s.toString();
|
||
|
}
|
||
|
|
||
|
public String toStringWithRanges() {
|
||
|
return toString();
|
||
|
}
|
||
|
|
||
|
private final static int wordNumber(int bit) {
|
||
|
return bit >> LOG_BITS; // bit / BITS
|
||
|
}
|
||
|
}
|