/**
* Immutable class representing a {@link Bit}Vector
*
- *
* @author Christian Femers
*
*/
public final class BitVector implements StrictLogicType<BitVector>, Iterable<Bit>, RandomAccess
{
+ public static final BitVector SINGLE_U = new BitVector(Bit.U);
+ public static final BitVector SINGLE_X = new BitVector(Bit.X);
+ public static final BitVector SINGLE_0 = new BitVector(Bit.ZERO);
+ public static final BitVector SINGLE_1 = new BitVector(Bit.ONE);
+ public static final BitVector SINGLE_Z = new BitVector(Bit.Z);
+
+ private static final BitVector[] SINGLE_BIT_MAPPING = { SINGLE_U, SINGLE_X, SINGLE_0, SINGLE_1, SINGLE_Z };
+
private final Bit[] bits;
+ private BitVector(Bit single)
+ {
+ Objects.requireNonNull(single);
+ bits = new Bit[] { single };
+ }
+
private BitVector(Bit[] bits)
{
- this.bits = Objects.requireNonNull(bits);
+ this.bits = Objects.requireNonNull(bits); // do this first to "catch" bits==null before the foreach loop
+ for (Bit bit : bits)
+ if (bit == null)
+ throw new NullPointerException();
}
public static BitVector of(Bit... bits)
{
+ if (bits.length == 1)
+ return SINGLE_BIT_MAPPING[bits[0].ordinal()];
return new BitVector(bits.clone());
}
public static BitVector of(Bit bit, int length)
{
+ if (length == 1)
+ return SINGLE_BIT_MAPPING[bit.ordinal()];
return new BitVector(bit.makeArray(length));
}
return BitVectorMutator.of(this);
}
- public Bit getBit(int bitIndex)
+ /**
+ * Returns the most significant bit at <code>bitIndex</code>. (leftmost bit of a binary number at the given index)
+ */
+ public Bit getMSBit(int bitIndex)
{
return bits[bitIndex];
}
+ /**
+ * Returns the least significant bit at <code>bitIndex</code>. (rightmost bit of a binary number at the given index)
+ */
+ public Bit getLSBit(int bitIndex)
+ {
+ return bits[bits.length - bitIndex - 1];
+ }
+
public Bit[] getBits()
{
return bits.clone();
public BitVector join(BitVector t)
{
checkCompatibility(t);
+ if (bits.length == 1)
+ return SINGLE_BIT_MAPPING[bits[0].join(t.bits[0]).ordinal()];
return new BitVector(binOp(bits.clone(), t.bits, Bit::join));
}
public BitVector and(BitVector t)
{
checkCompatibility(t);
+ if (bits.length == 1)
+ return SINGLE_BIT_MAPPING[bits[0].and(t.bits[0]).ordinal()];
return new BitVector(binOp(bits.clone(), t.bits, Bit::and));
}
public BitVector or(BitVector t)
{
checkCompatibility(t);
+ if (bits.length == 1)
+ return SINGLE_BIT_MAPPING[bits[0].or(t.bits[0]).ordinal()];
return new BitVector(binOp(bits.clone(), t.bits, Bit::or));
}
public BitVector xor(BitVector t)
{
checkCompatibility(t);
+ if (bits.length == 1)
+ return SINGLE_BIT_MAPPING[bits[0].xor(t.bits[0]).ordinal()];
return new BitVector(binOp(bits.clone(), t.bits, Bit::xor));
}
@Override
public BitVector not()
{
+ if (bits.length == 1)
+ return SINGLE_BIT_MAPPING[bits[0].not().ordinal()];
return new BitVector(unOp(bits.clone(), Bit::not));
}
*
* @author Christian Femers
*/
- @SuppressWarnings("synthetic-access")
public static final class BitVectorMutator implements LogicType<BitVectorMutator, BitVector>
{
private Bit[] bits;
return new BitVectorMutator(bv.getBits());
}
+ /**
+ * Returns a new mutator of the specified length, <b>with all bits set to <code>null</code></b>. Use with care!
+ */
+ public static BitVectorMutator ofLength(int length)
+ {
+ return new BitVectorMutator(new Bit[length]);
+ }
+
/**
* Returns an empty mutator which has no bits set and will simply copy the values from the first binary operation performed.
- *
*/
public static BitVectorMutator empty()
{
*
* @throws IllegalStateException if the mutator is (still) empty
*/
- public BitVector get()
+ public BitVector toBitVector()
{
if (bits == null)
throw new IllegalStateException("cannot create a BitVector from an empty mutator");
return this;
}
+ /**
+ * Set the most significant bit at <code>bitIndex</code>. (leftmost bit of a binary number at the given index)
+ */
+ public void setMSBit(int bitIndex, Bit bit)
+ {
+ bits[bitIndex] = bit;
+ }
+
+ /**
+ * Set the least significant bit at <code>bitIndex</code>. (rightmost bit of a binary number at the given index)
+ */
+ public void setLSBit(int bitIndex, Bit bit)
+ {
+ bits[bits.length - bitIndex - 1] = bit;
+ }
+
+ /**
+ * Returns the most significant bit at <code>bitIndex</code>. (leftmost bit of a binary number at the given index)
+ */
+ public Bit getMSBit(int bitIndex)
+ {
+ return bits[bitIndex];
+ }
+
+ /**
+ * Returns the least significant bit at <code>bitIndex</code>. (rightmost bit of a binary number at the given index)
+ */
+ public Bit getLSBit(int bitIndex)
+ {
+ return bits[bits.length - bitIndex - 1];
+ }
+
+ public int length()
+ {
+ return bits.length;
+ }
+
private void checkCompatibility(BitVector bv)
{
if (bits != null && bits.length != bv.length())
}
/**
- * All {@link Bit}s symbols concatenated together
+ * All {@link Bit}s symbols concatenated together (MSB first)
*
* @see #parse(String)
*/
}
/**
- * Parses a String containing solely {@link Bit} symbols
+ * Parses a String containing solely {@link Bit} symbols (MSB first)
*
* @see #toString()
*/
return new BitVector(values);
}
+ /**
+ * Iterate over the {@link Bit}s of the BitVector <b>from MSB to LSB</b> (left to right).
+ */
@Override
public Iterator<Bit> iterator()
{
{
if (!hasNext())
throw new NoSuchElementException();
- return getBit(pos++);
+ return getMSBit(pos++);
}
@Override