// // Copyright (C) 2010 United States Government as represented by the // Administrator of the National Aeronautics and Space Administration // (NASA). All Rights Reserved. // // This software is distributed under the NASA Open Source Agreement // (NOSA), version 1.3. The NOSA has been approved by the Open Source // Initiative. See the file NOSA-1.3-JPF at the top of the distribution // directory tree for the complete NOSA document. // // THE SUBJECT SOFTWARE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY OF ANY // KIND, EITHER EXPRESSED, IMPLIED, OR STATUTORY, INCLUDING, BUT NOT // LIMITED TO, ANY WARRANTY THAT THE SUBJECT SOFTWARE WILL CONFORM TO // SPECIFICATIONS, ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR // A PARTICULAR PURPOSE, OR FREEDOM FROM INFRINGEMENT, ANY WARRANTY THAT // THE SUBJECT SOFTWARE WILL BE ERROR FREE, OR ANY WARRANTY THAT // DOCUMENTATION, IF PROVIDED, WILL CONFORM TO THE SUBJECT SOFTWARE. // package gov.nasa.jpf.util; import java.util.NoSuchElementException; import gov.nasa.jpf.JPFException; /** * */ public class BitSet64 implements FixedBitSet, Cloneable, IntSet { static final int INDEX_MASK = 0xffffffc0; // ( i>=0 && i<64) long l0; int cardinality; public BitSet64 (){ // nothing in here } public BitSet64 (int i){ set(i); } public BitSet64 (int... idx){ for (int i : idx){ set(i); } } public int longSize(){ return 1; } public long getLong(int i){ if (i==0) { return l0; } else { throw new IndexOutOfBoundsException("BitSet64 has no long index " + i); } } public BitSet64 clone() { try { return (BitSet64) super.clone(); } catch (CloneNotSupportedException ex) { throw new JPFException("BitSet64 clone failed"); } } private final int computeCardinality (){ return Long.bitCount(l0); } //--- public interface (much like java.util.BitSet) public void set (int i){ if ((i & INDEX_MASK) == 0){ long bitPattern = (1L << i); if ((l0 & bitPattern) == 0L) { cardinality++; l0 |= bitPattern; } } else { throw new IndexOutOfBoundsException("BitSet64 index out of range: " + i); } } public void clear (int i){ if ((i & INDEX_MASK) == 0){ long bitPattern = (1L << i); if ((l0 & bitPattern) != 0L) { // bit is set cardinality--; l0 &= ~bitPattern; } } else { throw new IndexOutOfBoundsException("BitSet64 index out of range: " + i); } } public void set (int i, boolean val){ if (val) { set(i); } else { clear(i); } } public boolean get (int i){ if ((i & INDEX_MASK) == 0){ long bitPattern = (1L << i); return ((l0 & bitPattern) != 0); } else { throw new IndexOutOfBoundsException("BitSet64 index out of range: " + i); } } public int cardinality() { return cardinality; } public int capacity(){ return 64; } /** * number of bits we can store */ public int size() { return cardinality; } /** * index of highest set bit + 1 */ public int length() { return 64 - Long.numberOfLeadingZeros(l0); } public boolean isEmpty() { return (cardinality == 0); } public void clear() { l0 = 0L; cardinality = 0; } public int nextSetBit (int fromIdx){ if ((fromIdx & INDEX_MASK) == 0){ //int n = Long.numberOfTrailingZeros(l0 & (0xffffffffffffffffL << fromIdx)); int n = Long.numberOfTrailingZeros(l0 >> fromIdx) + fromIdx; if (n < 64) { return n; } else { return -1; } } else { //throw new IndexOutOfBoundsException("BitSet64 index out of range: " + fromIdx); return -1; } } public int nextClearBit (int fromIdx){ if ((fromIdx & INDEX_MASK) == 0){ //int n = Long.numberOfTrailingZeros(~l0 & (0xffffffffffffffffL << fromIdx)); int n = Long.numberOfTrailingZeros(~l0 >> fromIdx) + fromIdx; if (n < 64) { return n; } else { return -1; } } else { //throw new IndexOutOfBoundsException("BitSet64 index out of range: " + fromIdx); return -1; } } public void and (BitSet64 other){ l0 &= other.l0; cardinality = computeCardinality(); } public void andNot (BitSet64 other){ l0 &= ~other.l0; cardinality = computeCardinality(); } public void or (BitSet64 other){ l0 |= other.l0; cardinality = computeCardinality(); } public boolean equals (Object o){ if (o instanceof BitSet64){ BitSet64 other = (BitSet64)o; if (l0 != other.l0) return false; return true; } else { // <2do> we could compare to a normal java.util.BitSet here return false; } } public void hash(HashData hd){ hd.add(hashCode()); } /** * answer the same hashCodes as java.util.BitSet */ public int hashCode() { long hc = 1234; hc ^= l0; return (int) ((hc >>32) ^ hc); } public String toString() { StringBuilder sb = new StringBuilder(); sb.append('{'); boolean first = true; for (int i=nextSetBit(0); i>= 0; i = nextSetBit(i+1)){ if (!first){ sb.append(','); } else { first = false; } sb.append(i); } sb.append('}'); return sb.toString(); } //--- IntSet interface class SetBitIterator implements IntIterator { int cur = 0; int nBits; @Override public void remove() { if (cur >0){ clear(cur-1); } } @Override public boolean hasNext() { return nBits < cardinality; } @Override public int next() { if (nBits < cardinality){ int idx = nextSetBit(cur); if (idx >= 0){ nBits++; cur = idx+1; } return idx; } else { throw new NoSuchElementException(); } } } @Override public boolean add(int i) { if (get(i)) { return false; } else { set(i); return true; } } @Override public boolean remove(int i) { if (get(i)) { clear(i); return true; } else { return false; } } @Override public boolean contains(int i) { return get(i); } @Override public IntIterator intIterator() { return new SetBitIterator(); } }