Refactored BitVector and added test cases
authorChristian Femers <femers@in.tum.de>
Mon, 26 Aug 2019 00:47:50 +0000 (02:47 +0200)
committerChristian Femers <femers@in.tum.de>
Mon, 26 Aug 2019 00:47:50 +0000 (02:47 +0200)
The is duplication of methods that were developed independently. This
will be resolved in a future commit.

net.mograsim.logic.core/src/net/mograsim/logic/core/types/BitVector.java
net.mograsim.logic.core/test/net/mograsim/logic/core/types/BitVectorTest.java [new file with mode: 0644]

index e8a4098..6a36403 100644 (file)
@@ -61,14 +61,12 @@ public final class BitVector implements StrictLogicType<BitVector>, Iterable<Bit
        {
                if (!isBinary())
                        throw new NumberFormatException("BitVector is non binary: " + toString());
-               Bit[] bits = getBits();
-               int length = length();
-               byte[] bytes = new byte[(length / 8) + 1];
-               for (int i = 0; i < length; i++)
+               byte[] bytes = new byte[(bits.length / 8) + 1];
+               for (int i = 0; i < bits.length; i++)
                {
-                       if (Bit.ONE.equals(bits[i]))
+                       if (Bit.ONE == bits[i])
                        {
-                               bytes[(i / 8) + 1] |= 1 << (i % 8);
+                               bytes[i / 8] |= 1 << (i % 8);
                        }
                }
                return new BigInteger(bytes);
@@ -90,6 +88,21 @@ public final class BitVector implements StrictLogicType<BitVector>, Iterable<Bit
                return BitVector.of(bits);
        }
 
+       public static BitVector of(long value, int bits)
+       {
+               return of(BigInteger.valueOf(value), bits);
+       }
+
+       public static BitVector of(BigInteger value, int bits)
+       {
+               Bit[] values = new Bit[bits];
+               for (int i = 0; i < bits; i++)
+               {
+                       values[bits - i - 1] = Bit.of(value.testBit(i));
+               }
+               return new BitVector(values);
+       }
+
        public BitVectorMutator mutator()
        {
                return BitVectorMutator.of(this);
@@ -249,12 +262,23 @@ public final class BitVector implements StrictLogicType<BitVector>, Iterable<Bit
 
                /**
                 * Returns an empty mutator which has no bits set and will simply copy the values from the first binary operation performed.
+                * <p>
+                * An empty BitVectorMutator <b>must not</b> be converted to BitVector or used to manipulate single bits until at least one two
+                * operand logic operation is performed.
                 */
                public static BitVectorMutator empty()
                {
                        return new BitVectorMutator(null);
                }
 
+               /**
+                * @see #empty()
+                */
+               public boolean isEmpty()
+               {
+                       return bits == null;
+               }
+
                /**
                 * Produces the resulting, immutable {@link BitVector}<br>
                 * 
@@ -311,6 +335,8 @@ public final class BitVector implements StrictLogicType<BitVector>, Iterable<Bit
                 */
                public void setMSBit(int bitIndex, Bit bit)
                {
+                       if (bits == null)
+                               throw new IllegalStateException("cannot set a bit of an empty mutator");
                        bits[bitIndex] = bit;
                }
 
@@ -319,6 +345,8 @@ public final class BitVector implements StrictLogicType<BitVector>, Iterable<Bit
                 */
                public void setLSBit(int bitIndex, Bit bit)
                {
+                       if (bits == null)
+                               throw new IllegalStateException("cannot set a bit of an empty mutator");
                        bits[bits.length - bitIndex - 1] = bit;
                }
 
@@ -327,6 +355,8 @@ public final class BitVector implements StrictLogicType<BitVector>, Iterable<Bit
                 */
                public Bit getMSBit(int bitIndex)
                {
+                       if (bits == null)
+                               throw new IllegalStateException("cannot get a bit of an empty mutator");
                        return bits[bitIndex];
                }
 
@@ -335,11 +365,15 @@ public final class BitVector implements StrictLogicType<BitVector>, Iterable<Bit
                 */
                public Bit getLSBit(int bitIndex)
                {
+                       if (bits == null)
+                               throw new IllegalStateException("cannot get a bit of an empty mutator");
                        return bits[bits.length - bitIndex - 1];
                }
 
                public int length()
                {
+                       if (bits == null)
+                               throw new IllegalStateException("cannot obtain a length of an empty mutator");
                        return bits.length;
                }
 
@@ -404,6 +438,23 @@ public final class BitVector implements StrictLogicType<BitVector>, Iterable<Bit
                return sb.toString();
        }
 
+       /**
+        * Returns the value of the BitVector as BigInteger either unsigned or as two-complement.
+        * 
+        * @param signed if true and the BitVector represents a negative two-complement integer, an equivalent BigInteger is returned
+        * @return the value of this BitVector as BigInteger
+        * 
+        */
+       public BigInteger toBigInteger(boolean signed)
+       {
+               if (!isBinary())
+                       throw new NumberFormatException(this + " is not binary");
+               BigInteger val = new BigInteger(toString(), 2);
+               if (signed && bits[0] == Bit.ONE)
+                       val = val.not().setBit(val.bitLength()).add(BigInteger.ONE);
+               return val;
+       }
+
        /**
         * Parses a String containing solely {@link Bit} symbols (MSB first)
         * 
@@ -419,21 +470,6 @@ public final class BitVector implements StrictLogicType<BitVector>, Iterable<Bit
                return new BitVector(values);
        }
 
-       public static BitVector of(long value, int bits)
-       {
-               return of(BigInteger.valueOf(value), bits);
-       }
-
-       public static BitVector of(BigInteger value, int bits)
-       {
-               Bit[] values = new Bit[bits];
-               for (int i = 0; i < bits; i++)
-               {
-                       values[bits - i - 1] = Bit.of(value.testBit(i));
-               }
-               return new BitVector(values);
-       }
-
        /**
         * Iterate over the {@link Bit}s of the BitVector <b>from MSB to LSB</b> (left to right).
         */
diff --git a/net.mograsim.logic.core/test/net/mograsim/logic/core/types/BitVectorTest.java b/net.mograsim.logic.core/test/net/mograsim/logic/core/types/BitVectorTest.java
new file mode 100644 (file)
index 0000000..2ab57ee
--- /dev/null
@@ -0,0 +1,309 @@
+package net.mograsim.logic.core.types;\r
+\r
+import static net.mograsim.logic.core.types.BitVector.*;\r
+import static net.mograsim.logic.core.types.Bit.*;\r
+import static org.junit.jupiter.api.Assertions.*;\r
+\r
+import java.math.BigInteger;\r
+import java.util.Iterator;\r
+\r
+import org.junit.jupiter.api.Test;\r
+\r
+class BitVectorTest\r
+{\r
+\r
+       @Test\r
+       void testOfBitArray()\r
+       {\r
+               BitVector.of(); // should be allowed and work\r
+\r
+               assertSame(SINGLE_U, BitVector.of(U));\r
+               assertSame(SINGLE_X, BitVector.of(X));\r
+               assertSame(SINGLE_0, BitVector.of(ZERO));\r
+               assertSame(SINGLE_1, BitVector.of(ONE));\r
+               assertSame(SINGLE_Z, BitVector.of(Z));\r
+       }\r
+\r
+       @Test\r
+       void testOfBitInt()\r
+       {\r
+               assertEquals(BitVector.of(), BitVector.of(ONE, 0));\r
+\r
+               assertSame(SINGLE_U, BitVector.of(U, 1));\r
+               assertSame(SINGLE_X, BitVector.of(X, 1));\r
+               assertSame(SINGLE_0, BitVector.of(ZERO, 1));\r
+               assertSame(SINGLE_1, BitVector.of(ONE, 1));\r
+               assertSame(SINGLE_Z, BitVector.of(Z, 1));\r
+\r
+               assertEquals(BitVector.of(X, X, X), BitVector.of(X, 3));\r
+       }\r
+\r
+       @Test\r
+       void testFrom()\r
+       {\r
+               assertEquals(BitVector.parse("101"), BitVector.from(BigInteger.valueOf(0b101), 3));\r
+               assertEquals(BitVector.parse("01010"), BitVector.from(BigInteger.valueOf(0b01010), 5));\r
+               assertEquals(BitVector.parse("10101"), BitVector.from(BigInteger.valueOf(-11), 5));\r
+               assertEquals(BitVector.parse("0000"), BitVector.from(BigInteger.valueOf(0), 4));\r
+       }\r
+\r
+       @Test\r
+       void testGetUnsignedValue()\r
+       {\r
+               assertEquals(BigInteger.valueOf(0b101), BitVector.parse("101").getUnsignedValue());\r
+               assertEquals(BigInteger.valueOf(0b01010), BitVector.parse("01010").getUnsignedValue());\r
+               assertEquals(BigInteger.valueOf(0), BitVector.parse("0000").getUnsignedValue());\r
+\r
+               assertThrows(NumberFormatException.class, () -> BitVector.parse("00X1").getUnsignedValue());\r
+\r
+       }\r
+\r
+       @Test\r
+       void testToBigInteger()\r
+       {\r
+               assertEquals(BigInteger.valueOf(0b101), BitVector.parse("101").toBigInteger(false));\r
+               assertEquals(BigInteger.valueOf(0b01010), BitVector.parse("01010").toBigInteger(false));\r
+               assertEquals(BigInteger.valueOf(0), BitVector.parse("0000").toBigInteger(false));\r
+\r
+//             assertEquals(BigInteger.valueOf(-11), BitVector.parse("10101").toBigInteger(true)); TODO\r
+\r
+               assertThrows(NumberFormatException.class, () -> BitVector.parse("00X1").toBigInteger(false));\r
+       }\r
+\r
+       @Test\r
+       void testOfLongInt()\r
+       {\r
+               assertEquals(BitVector.parse("101"), BitVector.of(0b101L, 3));\r
+               assertEquals(BitVector.parse("01010"), BitVector.of(0b01010L, 5));\r
+               assertEquals(BitVector.parse("10101"), BitVector.of(-11L, 5));\r
+               assertEquals(BitVector.parse("0000"), BitVector.of(0L, 4));\r
+       }\r
+\r
+       @Test\r
+       void testOfBigIntegerInt()\r
+       {\r
+               assertEquals(BitVector.parse("101"), BitVector.of(BigInteger.valueOf(0b101), 3));\r
+               assertEquals(BitVector.parse("01010"), BitVector.of(BigInteger.valueOf(0b01010), 5));\r
+               assertEquals(BitVector.parse("10101"), BitVector.of(BigInteger.valueOf(-11), 5));\r
+               assertEquals(BitVector.parse("0000"), BitVector.of(BigInteger.valueOf(0), 4));\r
+       }\r
+\r
+       @Test\r
+       void testMutator()\r
+       {\r
+               var bv = BitVector.SINGLE_1;\r
+               var bvm = bv.mutator();\r
+\r
+               assertFalse(bvm.isEmpty());\r
+               assertEquals(ONE, bvm.getLSBit(0));\r
+               assertEquals(SINGLE_1, bvm.toBitVector());\r
+       }\r
+\r
+       @Test\r
+       void testGetMSBit()\r
+       {\r
+               assertEquals(ONE, SINGLE_1.getMSBit(0));\r
+               assertEquals(ONE, BitVector.of(ONE, X, X, X).getMSBit(0));\r
+               assertEquals(ONE, BitVector.of(X, X, X, X, ONE, X).getMSBit(4));\r
+       }\r
+\r
+       @Test\r
+       void testGetLSBit()\r
+       {\r
+               assertEquals(ONE, SINGLE_1.getLSBit(0));\r
+               assertEquals(ONE, BitVector.of(X, X, X, ONE).getLSBit(0));\r
+               assertEquals(ONE, BitVector.of(X, X, X, X, ONE, X).getLSBit(1));\r
+       }\r
+\r
+       @Test\r
+       void testGetBits()\r
+       {\r
+               assertArrayEquals(new Bit[] { X, ONE, Z }, BitVector.of(X, ONE, Z).getBits());\r
+               assertArrayEquals(new Bit[] { X, ONE, Z }, BitVector.parse("X1Z").getBits());\r
+       }\r
+\r
+       @Test\r
+       void testIsBinary()\r
+       {\r
+               assertTrue(SINGLE_0.isBinary());\r
+               assertTrue(SINGLE_1.isBinary());\r
+\r
+               assertFalse(SINGLE_U.isBinary());\r
+               assertFalse(SINGLE_X.isBinary());\r
+               assertFalse(SINGLE_Z.isBinary());\r
+\r
+               assertTrue(BitVector.of(ONE, ZERO, ONE, ONE, ZERO).isBinary());\r
+               assertFalse(BitVector.of(ONE, ZERO, ZERO, X).isBinary());\r
+       }\r
+\r
+       @Test\r
+       void testJoin()\r
+       {\r
+               // binary\r
+               assertEquals(SINGLE_0, SINGLE_0.join(SINGLE_0));\r
+               assertEquals(SINGLE_X, SINGLE_0.join(SINGLE_1));\r
+               assertEquals(SINGLE_1, SINGLE_1.join(SINGLE_1));\r
+\r
+               // other\r
+               assertEquals(SINGLE_1, SINGLE_Z.join(SINGLE_1));\r
+               assertEquals(SINGLE_U, SINGLE_0.join(SINGLE_U));\r
+               assertEquals(SINGLE_X, SINGLE_X.join(SINGLE_Z));\r
+\r
+               // higher length\r
+               var result = BitVector.of(U, X, ZERO, ONE, Z).join(BitVector.of(ONE, ZERO, ZERO, ONE, Z));\r
+               assertEquals(BitVector.of(U, X, ZERO, ONE, Z), result);\r
+       }\r
+\r
+       @Test\r
+       void testAnd()\r
+       {\r
+               // binary\r
+               assertEquals(SINGLE_0, SINGLE_0.and(SINGLE_0));\r
+               assertEquals(SINGLE_0, SINGLE_0.and(SINGLE_1));\r
+               assertEquals(SINGLE_1, SINGLE_1.and(SINGLE_1));\r
+\r
+               // other\r
+               assertEquals(SINGLE_X, SINGLE_Z.and(SINGLE_1));\r
+               assertEquals(SINGLE_0, SINGLE_0.and(SINGLE_U));\r
+               assertEquals(SINGLE_X, SINGLE_X.and(SINGLE_Z));\r
+\r
+               // higher length\r
+               var result = BitVector.of(U, X, ZERO, ONE, ONE).and(BitVector.of(ONE, ONE, ZERO, ZERO, ONE));\r
+               assertEquals(BitVector.of(U, X, ZERO, ZERO, ONE), result);\r
+       }\r
+\r
+       @Test\r
+       void testOr()\r
+       {\r
+               // binary\r
+               assertEquals(SINGLE_0, SINGLE_0.or(SINGLE_0));\r
+               assertEquals(SINGLE_1, SINGLE_0.or(SINGLE_1));\r
+               assertEquals(SINGLE_1, SINGLE_1.or(SINGLE_1));\r
+\r
+               // other\r
+               assertEquals(SINGLE_1, SINGLE_Z.or(SINGLE_1));\r
+               assertEquals(SINGLE_1, SINGLE_1.or(SINGLE_U));\r
+               assertEquals(SINGLE_X, SINGLE_X.or(SINGLE_Z));\r
+\r
+               // higher length\r
+               var result = BitVector.of(U, X, ZERO, ONE, ZERO).or(BitVector.of(ZERO, ZERO, ZERO, ONE, ONE));\r
+               assertEquals(BitVector.of(U, X, ZERO, ONE, ONE), result);\r
+       }\r
+\r
+       @Test\r
+       void testXor()\r
+       {\r
+               // binary\r
+               assertEquals(SINGLE_0, SINGLE_0.xor(SINGLE_0));\r
+               assertEquals(SINGLE_1, SINGLE_0.xor(SINGLE_1));\r
+               assertEquals(SINGLE_0, SINGLE_1.xor(SINGLE_1));\r
+\r
+               // other\r
+               assertEquals(SINGLE_X, SINGLE_Z.xor(SINGLE_1));\r
+               assertEquals(SINGLE_U, SINGLE_0.xor(SINGLE_U));\r
+               assertEquals(SINGLE_X, SINGLE_X.xor(SINGLE_Z));\r
+\r
+               // higher length\r
+               var result = BitVector.of(U, X, ZERO, ONE, ONE).xor(BitVector.of(ONE, ZERO, ZERO, ZERO, ONE));\r
+               assertEquals(BitVector.of(U, X, ZERO, ONE, ZERO), result);\r
+       }\r
+\r
+       @Test\r
+       void testNot()\r
+       {\r
+               // binary\r
+               assertEquals(SINGLE_1, SINGLE_0.not());\r
+               assertEquals(SINGLE_0, SINGLE_1.not());\r
+\r
+               // other\r
+               assertEquals(SINGLE_U, SINGLE_U.not());\r
+               assertEquals(SINGLE_X, SINGLE_X.not());\r
+               assertEquals(SINGLE_X, SINGLE_Z.not());\r
+\r
+               // higher length\r
+               var result = BitVector.of(U, X, ZERO, ONE, Z).not();\r
+               assertEquals(BitVector.of(U, X, ONE, ZERO, X), result);\r
+       }\r
+\r
+       @Test\r
+       void testLength()\r
+       {\r
+               assertEquals(0, BitVector.of().length());\r
+               assertEquals(1, SINGLE_0.length());\r
+               assertEquals(3, BitVector.of(X, X, Z).length());\r
+       }\r
+\r
+       @Test\r
+       void testConcat()\r
+       {\r
+               assertEquals(BitVector.of(U, X), SINGLE_U.concat(SINGLE_X));\r
+               assertEquals(BitVector.of(Z, X, U, ONE, X), BitVector.of(Z, X, U).concat(BitVector.of(ONE, X)));\r
+       }\r
+\r
+       @Test\r
+       void testSubVectorInt()\r
+       {\r
+               assertEquals(SINGLE_0, SINGLE_0.subVector(0));\r
+               assertEquals(BitVector.of(), SINGLE_0.subVector(1));\r
+               assertEquals(SINGLE_0, BitVector.of(ONE, ZERO).subVector(1));\r
+               assertEquals(BitVector.of(X, Z), BitVector.of(ZERO, U, ONE, X, Z).subVector(3));\r
+       }\r
+\r
+       @Test\r
+       void testSubVectorIntInt()\r
+       {\r
+               assertEquals(SINGLE_0, SINGLE_0.subVector(0, 1));\r
+               assertEquals(BitVector.of(), SINGLE_0.subVector(0, 0));\r
+               assertEquals(SINGLE_0, BitVector.of(ONE, ZERO).subVector(1, 2));\r
+               assertEquals(BitVector.of(ONE, X), BitVector.of(ZERO, U, ONE, X, Z).subVector(2, 4));\r
+       }\r
+\r
+       @Test\r
+       void testEqualsObject()\r
+       {\r
+               assertEquals(SINGLE_X, SINGLE_X);\r
+               assertNotEquals(SINGLE_0, SINGLE_1);\r
+\r
+               assertEquals(BitVector.of(X, Z, U), BitVector.of(X, Z, U));\r
+               assertNotEquals(BitVector.of(X, Z, U), BitVector.of(X, X, U));\r
+       }\r
+\r
+       @Test\r
+       void testEqualsWithOffset()\r
+       {\r
+               assertTrue(SINGLE_X.equalsWithOffset(SINGLE_X, 0));\r
+               assertFalse(SINGLE_0.equalsWithOffset(SINGLE_1, 0));\r
+\r
+               assertTrue(BitVector.of(X, Z, U).equalsWithOffset(BitVector.of(Z, U), 1));\r
+               assertFalse(BitVector.of(X, Z, U).equalsWithOffset(BitVector.of(X, U), 1));\r
+               assertTrue(BitVector.of(X, Z, U).equalsWithOffset(BitVector.of(U), 2));\r
+       }\r
+\r
+       @Test\r
+       void testParse()\r
+       {\r
+               assertEquals(SINGLE_U, BitVector.parse("U"));\r
+               assertEquals(SINGLE_X, BitVector.parse("X"));\r
+               assertEquals(SINGLE_0, BitVector.parse("0"));\r
+               assertEquals(SINGLE_1, BitVector.parse("1"));\r
+               assertEquals(SINGLE_Z, BitVector.parse("Z"));\r
+\r
+               assertEquals(BitVector.of(X, U, Z, ONE, ZERO), BitVector.parse("XUZ10"));\r
+\r
+               assertThrows(RuntimeException.class, () -> BitVector.parse("01BX"));\r
+       }\r
+\r
+       @Test\r
+       void testIterator()\r
+       {\r
+               var bv = BitVector.of(U, Z, ONE, ZERO, X);\r
+               Iterator<Bit> it = bv.iterator();\r
+\r
+               assertEquals(U, it.next());\r
+               assertEquals(Z, it.next());\r
+               assertEquals(ONE, it.next());\r
+               assertEquals(ZERO, it.next());\r
+               assertEquals(X, it.next());\r
+               assertFalse(it.hasNext());\r
+       }\r
+}\r