mirror of
https://github.com/2003scape/deep-c-rsc.git
synced 2024-03-22 05:49:51 -04:00
607 lines
14 KiB
Java
607 lines
14 KiB
Java
![]() |
/*
|
||
|
* @(#) $(JCGO)/goclsp/clsp_fix/java/util/BitSet.java --
|
||
|
* Int-based implementation of the standard BitSet class.
|
||
|
**
|
||
|
* Project: JCGO (http://www.ivmaisoft.com/jcgo/)
|
||
|
* Copyright (C) 2001-2007 Ivan Maidanski <ivmai@ivmaisoft.com>
|
||
|
* All rights reserved.
|
||
|
**
|
||
|
* Class specification origin: GNU Classpath v0.93
|
||
|
*/
|
||
|
|
||
|
/*
|
||
|
* This is free software; you can redistribute it and/or modify
|
||
|
* it under the terms of the GNU General Public License as published by
|
||
|
* the Free Software Foundation; either version 2, or (at your option)
|
||
|
* any later version.
|
||
|
**
|
||
|
* This software 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 (GPL) for more details.
|
||
|
**
|
||
|
* Linking this library statically or dynamically with other modules is
|
||
|
* making a combined work based on this library. Thus, the terms and
|
||
|
* conditions of the GNU General Public License cover the whole
|
||
|
* combination.
|
||
|
**
|
||
|
* As a special exception, the copyright holders of this library give you
|
||
|
* permission to link this library with independent modules to produce an
|
||
|
* executable, regardless of the license terms of these independent
|
||
|
* modules, and to copy and distribute the resulting executable under
|
||
|
* terms of your choice, provided that you also meet, for each linked
|
||
|
* independent module, the terms and conditions of the license of that
|
||
|
* module. An independent module is a module which is not derived from
|
||
|
* or based on this library. If you modify this library, you may extend
|
||
|
* this exception to your version of the library, but you are not
|
||
|
* obligated to do so. If you do not wish to do so, delete this
|
||
|
* exception statement from your version.
|
||
|
*/
|
||
|
|
||
|
package java.util;
|
||
|
|
||
|
import java.io.IOException;
|
||
|
import java.io.ObjectInputStream;
|
||
|
import java.io.ObjectOutputStream;
|
||
|
import java.io.Serializable;
|
||
|
|
||
|
public class BitSet
|
||
|
implements Cloneable, Serializable
|
||
|
{
|
||
|
|
||
|
private static final long serialVersionUID = 7997698588986878753L;
|
||
|
|
||
|
private static final int INDEX_SHIFT = 5;
|
||
|
|
||
|
private long[] bits;
|
||
|
|
||
|
private transient int unitsInUse;
|
||
|
|
||
|
private transient int[] intBits;
|
||
|
|
||
|
public BitSet()
|
||
|
{
|
||
|
this(64);
|
||
|
}
|
||
|
|
||
|
public BitSet(int nbits)
|
||
|
{
|
||
|
if (nbits < 0)
|
||
|
throw new NegativeArraySizeException("" + nbits);
|
||
|
intBits = new int[(((nbits - 1) >> INDEX_SHIFT) + 2) & ~1];
|
||
|
}
|
||
|
|
||
|
public int length()
|
||
|
{
|
||
|
recalculateUnitsInUse();
|
||
|
int i = unitsInUse;
|
||
|
return i > 0 ? (i << INDEX_SHIFT) -
|
||
|
numberOfLeadingZeros(intBits[i - 1]) : 0;
|
||
|
}
|
||
|
|
||
|
public boolean isEmpty()
|
||
|
{
|
||
|
recalculateUnitsInUse();
|
||
|
return unitsInUse == 0;
|
||
|
}
|
||
|
|
||
|
public void set(int bitIndex)
|
||
|
{
|
||
|
if (bitIndex < 0)
|
||
|
throw new IndexOutOfBoundsException("" + bitIndex);
|
||
|
int i = bitIndex >> INDEX_SHIFT;
|
||
|
if (unitsInUse <= i)
|
||
|
ensureCapacity(i + 1);
|
||
|
intBits[i] |= 1 << bitIndex;
|
||
|
}
|
||
|
|
||
|
public void set(int fromIndex, int toIndex)
|
||
|
{
|
||
|
if (fromIndex < 0 || toIndex < fromIndex)
|
||
|
throw new IndexOutOfBoundsException("" + fromIndex + ", " + toIndex);
|
||
|
if (fromIndex < toIndex)
|
||
|
{
|
||
|
int i = fromIndex >> INDEX_SHIFT;
|
||
|
int j = (toIndex - 1) >> INDEX_SHIFT;
|
||
|
if (unitsInUse <= j)
|
||
|
ensureCapacity(j + 1);
|
||
|
int[] intBits = this.intBits;
|
||
|
if (i < j)
|
||
|
{
|
||
|
intBits[i] |= -1 << fromIndex;
|
||
|
intBits[j] |= (2 << (toIndex - 1)) - 1;
|
||
|
while (++i < j)
|
||
|
intBits[i] = -1;
|
||
|
}
|
||
|
else intBits[i] |= (-1 << fromIndex) & ((2 << (toIndex - 1)) - 1);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public void set(int bitIndex, boolean value)
|
||
|
{
|
||
|
if (value)
|
||
|
set(bitIndex);
|
||
|
else clear(bitIndex);
|
||
|
}
|
||
|
|
||
|
public void set(int fromIndex, int toIndex, boolean value)
|
||
|
{
|
||
|
if (value)
|
||
|
set(fromIndex, toIndex);
|
||
|
else clear(fromIndex, toIndex);
|
||
|
}
|
||
|
|
||
|
public void clear()
|
||
|
{
|
||
|
int i = unitsInUse;
|
||
|
if (i > 0)
|
||
|
{
|
||
|
int[] intBits = this.intBits;
|
||
|
unitsInUse = 0;
|
||
|
do
|
||
|
{
|
||
|
intBits[--i] = 0;
|
||
|
} while (i > 0);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public void clear(int bitIndex)
|
||
|
{
|
||
|
if (bitIndex < 0)
|
||
|
throw new IndexOutOfBoundsException("" + bitIndex);
|
||
|
int i = bitIndex >> INDEX_SHIFT;
|
||
|
if (unitsInUse > i)
|
||
|
intBits[i] &= ~(1 << bitIndex);
|
||
|
}
|
||
|
|
||
|
public void clear(int fromIndex, int toIndex)
|
||
|
{
|
||
|
if (fromIndex < 0 || toIndex < fromIndex)
|
||
|
throw new IndexOutOfBoundsException("" + fromIndex + ", " + toIndex);
|
||
|
if (fromIndex < toIndex)
|
||
|
{
|
||
|
int i = fromIndex >> INDEX_SHIFT;
|
||
|
int j = unitsInUse - 1;
|
||
|
if (i <= j)
|
||
|
{
|
||
|
int[] intBits = this.intBits;
|
||
|
int k = (toIndex - 1) >> INDEX_SHIFT;
|
||
|
if (j >= k)
|
||
|
j = k;
|
||
|
if (i < j)
|
||
|
{
|
||
|
intBits[i] &= (1 << fromIndex) - 1;
|
||
|
intBits[j] &= -2 << (toIndex - 1);
|
||
|
while (++i < j)
|
||
|
intBits[i] = 0;
|
||
|
}
|
||
|
else intBits[i] &= ((1 << fromIndex) - 1) | (-2 << (toIndex - 1));
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public boolean get(int bitIndex)
|
||
|
{
|
||
|
if (bitIndex < 0)
|
||
|
throw new IndexOutOfBoundsException("" + bitIndex);
|
||
|
int i = bitIndex >> INDEX_SHIFT;
|
||
|
return unitsInUse > i && (intBits[i] & (1 << bitIndex)) != 0;
|
||
|
}
|
||
|
|
||
|
public BitSet get(int fromIndex, int toIndex)
|
||
|
{
|
||
|
if (fromIndex < 0 || toIndex < fromIndex)
|
||
|
throw new IndexOutOfBoundsException("" + fromIndex + ", " + toIndex);
|
||
|
BitSet set = new BitSet(toIndex - fromIndex);
|
||
|
if (fromIndex < toIndex)
|
||
|
{
|
||
|
int i = fromIndex >> INDEX_SHIFT;
|
||
|
int j = unitsInUse;
|
||
|
if (i < j)
|
||
|
{
|
||
|
int[] intBits = this.intBits;
|
||
|
int[] intBits2 = set.intBits;
|
||
|
int k = (toIndex - 1) >> INDEX_SHIFT;
|
||
|
if (j >= k)
|
||
|
j = k;
|
||
|
k = j - i;
|
||
|
set.unitsInUse = k + 1;
|
||
|
if ((fromIndex & ((1 << INDEX_SHIFT) - 1)) != 0)
|
||
|
{
|
||
|
int v = intBits[i];
|
||
|
if (k > 0)
|
||
|
{
|
||
|
int revShift = -fromIndex;
|
||
|
k = 0;
|
||
|
do
|
||
|
{
|
||
|
int w = intBits[++i];
|
||
|
intBits2[k++] = (v >>> fromIndex) | (w << revShift);
|
||
|
v = w;
|
||
|
} while (i < j);
|
||
|
}
|
||
|
intBits2[k] = (((2 << (toIndex - 1)) - 1) & v) >>> fromIndex;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
if (k > 0)
|
||
|
System.arraycopy(intBits, i, intBits2, 0, k);
|
||
|
intBits2[k] = intBits[j] & ((2 << (toIndex - 1)) - 1);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
return set;
|
||
|
}
|
||
|
|
||
|
public void flip(int bitIndex)
|
||
|
{
|
||
|
if (bitIndex < 0)
|
||
|
throw new IndexOutOfBoundsException("" + bitIndex);
|
||
|
int i = bitIndex >> INDEX_SHIFT;
|
||
|
if (unitsInUse <= i)
|
||
|
ensureCapacity(i + 1);
|
||
|
intBits[i] ^= 1 << bitIndex;
|
||
|
}
|
||
|
|
||
|
public void flip(int fromIndex, int toIndex)
|
||
|
{
|
||
|
if (fromIndex < 0 || toIndex < fromIndex)
|
||
|
throw new IndexOutOfBoundsException("" + fromIndex + ", " + toIndex);
|
||
|
if (fromIndex < toIndex)
|
||
|
{
|
||
|
int i = fromIndex >> INDEX_SHIFT;
|
||
|
int j = (toIndex - 1) >> INDEX_SHIFT;
|
||
|
if (unitsInUse <= j)
|
||
|
ensureCapacity(j + 1);
|
||
|
int[] intBits = this.intBits;
|
||
|
if (i < j)
|
||
|
{
|
||
|
intBits[i] ^= -1 << fromIndex;
|
||
|
intBits[j] ^= (2 << (toIndex - 1)) - 1;
|
||
|
while (++i < j)
|
||
|
intBits[i] ^= -1;
|
||
|
}
|
||
|
else intBits[i] ^= (-1 << fromIndex) & ((2 << (toIndex - 1)) - 1);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public void and(BitSet set)
|
||
|
{
|
||
|
if (set != this)
|
||
|
{
|
||
|
set.recalculateUnitsInUse();
|
||
|
recalculateUnitsInUse();
|
||
|
int i = unitsInUse;
|
||
|
int j = set.unitsInUse;
|
||
|
int[] intBits = this.intBits;
|
||
|
int[] intBits2 = set.intBits;
|
||
|
if (i > j)
|
||
|
{
|
||
|
unitsInUse = j;
|
||
|
do
|
||
|
{
|
||
|
intBits[--i] = 0;
|
||
|
} while (i > j);
|
||
|
}
|
||
|
while (i-- > 0)
|
||
|
intBits[i] &= intBits2[i];
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public void andNot(BitSet set)
|
||
|
{
|
||
|
if (set != this)
|
||
|
{
|
||
|
set.recalculateUnitsInUse();
|
||
|
recalculateUnitsInUse();
|
||
|
int i = unitsInUse;
|
||
|
int[] intBits = this.intBits;
|
||
|
int[] intBits2 = set.intBits;
|
||
|
int j = set.unitsInUse;
|
||
|
if (i >= j)
|
||
|
i = j;
|
||
|
while (i-- > 0)
|
||
|
intBits[i] &= ~intBits2[i];
|
||
|
}
|
||
|
else clear();
|
||
|
}
|
||
|
|
||
|
public void or(BitSet set)
|
||
|
{
|
||
|
if (set != this)
|
||
|
{
|
||
|
set.recalculateUnitsInUse();
|
||
|
recalculateUnitsInUse();
|
||
|
int i = unitsInUse;
|
||
|
int j = set.unitsInUse;
|
||
|
if (i < j)
|
||
|
ensureCapacity(j);
|
||
|
int[] intBits = this.intBits;
|
||
|
int[] intBits2 = set.intBits;
|
||
|
while (i < j)
|
||
|
{
|
||
|
j--;
|
||
|
intBits[j] = intBits2[j];
|
||
|
}
|
||
|
while (j-- > 0)
|
||
|
intBits[j] |= intBits2[j];
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public void xor(BitSet set)
|
||
|
{
|
||
|
if (set != this)
|
||
|
{
|
||
|
set.recalculateUnitsInUse();
|
||
|
recalculateUnitsInUse();
|
||
|
int i = unitsInUse;
|
||
|
int j = set.unitsInUse;
|
||
|
if (i < j)
|
||
|
ensureCapacity(j);
|
||
|
int[] intBits = this.intBits;
|
||
|
int[] intBits2 = set.intBits;
|
||
|
while (i < j)
|
||
|
{
|
||
|
j--;
|
||
|
intBits[j] = intBits2[j];
|
||
|
}
|
||
|
while (j-- > 0)
|
||
|
intBits[j] ^= intBits2[j];
|
||
|
}
|
||
|
else clear();
|
||
|
}
|
||
|
|
||
|
public boolean intersects(BitSet set)
|
||
|
{
|
||
|
if (set == this)
|
||
|
return true;
|
||
|
set.recalculateUnitsInUse();
|
||
|
recalculateUnitsInUse();
|
||
|
int i = unitsInUse;
|
||
|
int[] intBits = this.intBits;
|
||
|
int[] intBits2 = set.intBits;
|
||
|
int j = set.unitsInUse;
|
||
|
if (i >= j)
|
||
|
i = j;
|
||
|
while (i-- > 0)
|
||
|
if ((bits[i] & intBits2[i]) != 0)
|
||
|
return true;
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
public int nextClearBit(int bitIndex)
|
||
|
{
|
||
|
if (bitIndex < 0)
|
||
|
throw new IndexOutOfBoundsException("" + bitIndex);
|
||
|
int i = bitIndex >> INDEX_SHIFT;
|
||
|
int j = unitsInUse;
|
||
|
if (i < j)
|
||
|
{
|
||
|
int[] intBits = this.intBits;
|
||
|
int v = intBits[i] | ((1 << bitIndex) - 1);
|
||
|
while (++i < j && v == -1)
|
||
|
v = intBits[i];
|
||
|
bitIndex = numberOfTrailingZeros(~v) + ((i - 1) << INDEX_SHIFT);
|
||
|
}
|
||
|
return bitIndex;
|
||
|
}
|
||
|
|
||
|
public int nextSetBit(int bitIndex)
|
||
|
{
|
||
|
if (bitIndex < 0)
|
||
|
throw new IndexOutOfBoundsException("" + bitIndex);
|
||
|
int i = bitIndex >> INDEX_SHIFT;
|
||
|
int j = unitsInUse;
|
||
|
if (i < j)
|
||
|
{
|
||
|
int[] intBits = this.intBits;
|
||
|
int v = intBits[i] & (-1 << bitIndex);
|
||
|
while (v == 0 && ++i < j)
|
||
|
v = intBits[i];
|
||
|
if (i < j)
|
||
|
return numberOfTrailingZeros(v) + (i << INDEX_SHIFT);
|
||
|
}
|
||
|
return -1;
|
||
|
}
|
||
|
|
||
|
public int size()
|
||
|
{
|
||
|
return intBits.length << INDEX_SHIFT;
|
||
|
}
|
||
|
|
||
|
public int cardinality()
|
||
|
{
|
||
|
recalculateUnitsInUse();
|
||
|
int i = unitsInUse;
|
||
|
int count = 0;
|
||
|
int[] intBits = this.intBits;
|
||
|
while (i-- > 0)
|
||
|
count += bitCount(intBits[i]);
|
||
|
return count;
|
||
|
}
|
||
|
|
||
|
public int hashCode()
|
||
|
{
|
||
|
recalculateUnitsInUse();
|
||
|
int h = 1234;
|
||
|
int[] intBits = this.intBits;
|
||
|
for (int i = (unitsInUse + 1) >> 1; i > 0; i--)
|
||
|
{
|
||
|
int v = intBits[(i - 1) << 1];
|
||
|
h ^= (mulHigh(v, i) + intBits[(i << 1) - 1] * i) ^ (v * i);
|
||
|
}
|
||
|
return h;
|
||
|
}
|
||
|
|
||
|
public boolean equals(Object obj)
|
||
|
{
|
||
|
if (obj != this)
|
||
|
{
|
||
|
if (!(obj instanceof BitSet))
|
||
|
return false;
|
||
|
BitSet set = (BitSet) obj;
|
||
|
recalculateUnitsInUse();
|
||
|
set.recalculateUnitsInUse();
|
||
|
int i = unitsInUse;
|
||
|
if (set.unitsInUse != i)
|
||
|
return false;
|
||
|
int[] intBits = this.intBits;
|
||
|
int[] intBits2 = set.intBits;
|
||
|
while (i-- > 0)
|
||
|
if (intBits[i] != intBits2[i])
|
||
|
return false;
|
||
|
}
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
public Object clone()
|
||
|
{
|
||
|
BitSet result;
|
||
|
try
|
||
|
{
|
||
|
result = (BitSet) super.clone();
|
||
|
}
|
||
|
catch (CloneNotSupportedException e)
|
||
|
{
|
||
|
throw new InternalError();
|
||
|
}
|
||
|
int[] intBits = this.intBits;
|
||
|
System.arraycopy(intBits, 0, result.intBits = new int[intBits.length], 0,
|
||
|
unitsInUse);
|
||
|
return result;
|
||
|
}
|
||
|
|
||
|
private void writeObject(ObjectOutputStream output)
|
||
|
throws IOException
|
||
|
{
|
||
|
int[] intBits = this.intBits;
|
||
|
long[] bits = new long[intBits.length >> 1];
|
||
|
int i = (unitsInUse + 1) >> 1;
|
||
|
while (i-- > 0)
|
||
|
bits[i] = ((long) intBits[(i << 1) + 1] << 32) |
|
||
|
(long) intBits[i << 1] & 0xffffffffL;
|
||
|
this.bits = bits;
|
||
|
output.defaultWriteObject();
|
||
|
this.bits = null;
|
||
|
}
|
||
|
|
||
|
private void readObject(ObjectInputStream input)
|
||
|
throws IOException, ClassNotFoundException
|
||
|
{
|
||
|
input.defaultReadObject();
|
||
|
long[] bits = this.bits;
|
||
|
int i = bits.length;
|
||
|
this.bits = null;
|
||
|
int[] intBits = new int[i << 1];
|
||
|
unitsInUse = i << 1;
|
||
|
while (i-- > 0)
|
||
|
{
|
||
|
long v = bits[i];
|
||
|
intBits[i << 1] = (int) v;
|
||
|
intBits[(i << 1) + 1] = (int) (v >>> 32);
|
||
|
}
|
||
|
this.intBits = intBits;
|
||
|
recalculateUnitsInUse();
|
||
|
}
|
||
|
|
||
|
public String toString()
|
||
|
{
|
||
|
StringBuilder buffer = new StringBuilder();
|
||
|
buffer.append('{');
|
||
|
int[] intBits = this.intBits;
|
||
|
int len = unitsInUse;
|
||
|
boolean next = false;
|
||
|
for (int i = 0; i < len; i++)
|
||
|
{
|
||
|
int v = intBits[i];
|
||
|
for (int j = 0; v != 0; j++)
|
||
|
{
|
||
|
if ((v & 1) != 0)
|
||
|
{
|
||
|
if (next)
|
||
|
buffer.append(',').append(' ');
|
||
|
buffer.append((i << INDEX_SHIFT) | j);
|
||
|
next = true;
|
||
|
}
|
||
|
v >>>= 1;
|
||
|
}
|
||
|
}
|
||
|
return buffer.append('}').toString();
|
||
|
}
|
||
|
|
||
|
private void ensureCapacity(int unitsRequired)
|
||
|
{
|
||
|
int[] intBits = this.intBits;
|
||
|
if (intBits.length < unitsRequired)
|
||
|
{
|
||
|
int newLen = intBits.length << 1;
|
||
|
if (newLen < 0)
|
||
|
newLen = -1 >>> 1;
|
||
|
if (unitsRequired + 1 > newLen)
|
||
|
newLen = (unitsRequired + 1) & ~1;
|
||
|
int[] newBits = new int[newLen];
|
||
|
System.arraycopy(intBits, 0, newBits, 0, unitsInUse);
|
||
|
this.intBits = newBits;
|
||
|
}
|
||
|
unitsInUse = unitsRequired;
|
||
|
}
|
||
|
|
||
|
private void recalculateUnitsInUse()
|
||
|
{
|
||
|
int i = unitsInUse - 1;
|
||
|
if (i >= 0)
|
||
|
{
|
||
|
int[] intBits = this.intBits;
|
||
|
if (intBits[i] == 0)
|
||
|
{
|
||
|
while (i-- > 0)
|
||
|
if (intBits[i] != 0)
|
||
|
break;
|
||
|
unitsInUse = i + 1;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
private static int numberOfLeadingZeros(int value)
|
||
|
{
|
||
|
value |= value >>> 1;
|
||
|
value |= value >>> 2;
|
||
|
value |= value >>> 4;
|
||
|
value |= value >>> 8;
|
||
|
return bitCount(~((value >>> 16) | value));
|
||
|
}
|
||
|
|
||
|
private static int numberOfTrailingZeros(int value)
|
||
|
{
|
||
|
return bitCount((-value & value) - 1);
|
||
|
}
|
||
|
|
||
|
private static int bitCount(int value)
|
||
|
{
|
||
|
if (((value + 1) >> 1) == 0)
|
||
|
return value != 0 ? 32 : 0;
|
||
|
value = ((value >> 1) & 0x55555555) + (value & 0x55555555);
|
||
|
value = ((value >> 2) & 0x33333333) + (value & 0x33333333);
|
||
|
value = ((value >> 4) & 0xf0f0f0f) + (value & 0xf0f0f0f);
|
||
|
value = ((value >> 8) & 0xff00ff) + (value & 0xff00ff);
|
||
|
return ((value >> 16) & 0xffff) + (value & 0xffff);
|
||
|
}
|
||
|
|
||
|
private static int mulHigh(int valueA, int valueB)
|
||
|
{
|
||
|
int highA = valueA >>> 16;
|
||
|
int highB = valueB >>> 16;
|
||
|
valueA &= 0xffff;
|
||
|
int lowB = valueB & 0xffff;
|
||
|
valueA = ((valueA * lowB) >>> 16) + valueA * highB;
|
||
|
lowB *= highA;
|
||
|
valueA += lowB;
|
||
|
highA = highA * highB + (valueA >>> 16);
|
||
|
if ((valueA ^ lowB) >= 0)
|
||
|
lowB = valueA - lowB;
|
||
|
if (lowB < 0)
|
||
|
highA += 0x10000;
|
||
|
return highA;
|
||
|
}
|
||
|
}
|