Fixed a bug in Am2900; created dlatch8/80; relayouted some components
[Mograsim.git] / net.mograsim.logic.core / src / net / mograsim / logic / core / types / BitVector.java
index e8a4098..1346694 100644 (file)
@@ -57,37 +57,17 @@ public final class BitVector implements StrictLogicType<BitVector>, Iterable<Bit
                return new BitVector(bit.makeArray(length));
        }
 
-       public BigInteger getUnsignedValue()
+       public static BitVector from(long value, int bits)
        {
-               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++)
-               {
-                       if (Bit.ONE.equals(bits[i]))
-                       {
-                               bytes[(i / 8) + 1] |= 1 << (i % 8);
-                       }
-               }
-               return new BigInteger(bytes);
+               return from(BigInteger.valueOf(value), bits);
        }
 
-       public static BitVector from(BigInteger b, int length)
+       public static BitVector from(BigInteger value, int bits)
        {
-               int bitLength = b.bitLength();
-               int actualLength = Integer.min(bitLength, length);
-               Bit[] bits = new Bit[length];
-               for (int i = 0; i < actualLength; i++)
-                       bits[i] = b.testBit(i) ? Bit.ONE : Bit.ZERO;
-               if (b.signum() < 0)
-                       for (int i = actualLength; i < length; i++)
-                               bits[i] = Bit.ONE;
-               else
-                       for (int i = actualLength; i < length; i++)
-                               bits[i] = Bit.ZERO;
-               return BitVector.of(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()
@@ -116,6 +96,11 @@ public final class BitVector implements StrictLogicType<BitVector>, Iterable<Bit
                return bits.clone();
        }
 
+       /**
+        * Checks if all bits are {@link Bit#isBinary() binary}.
+        * 
+        * @see Bit#isBinary()
+        */
        public boolean isBinary()
        {
                for (int i = 0; i < bits.length; i++)
@@ -249,12 +234,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 +307,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 +317,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 +327,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 +337,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;
                }
 
@@ -377,7 +383,7 @@ public final class BitVector implements StrictLogicType<BitVector>, Iterable<Bit
 
        /**
         * Does test for equality of values/content, shifting the other BitVector by <code>offset</code> to the right.<br>
-        * Therefore <code>offset + other.length() <= this.length()</code> needs to be true.
+        * Therefore <code>offset + other.length() <= this.wdith()</code> needs to be true.
         * 
         * @throws ArrayIndexOutOfBoundsException if <code>offset + other.length() > this.length()</code>
         * 
@@ -404,6 +410,58 @@ public final class BitVector implements StrictLogicType<BitVector>, Iterable<Bit
                return sb.toString();
        }
 
+       /**
+        * Returns the value of the BitVector as BigInteger.
+        * 
+        * @throws NumberFormatException if the BitVector is not {@link #isBinary() binary}.
+        */
+       public BigInteger getUnsignedValue()
+       {
+               if (!isBinary())
+                       throw new NumberFormatException(this + " is not binary");
+               byte[] bytes = new byte[(bits.length / 8 + (bits.length % 8 == 0 ? 0 : 1)) + 1];
+               for (int i = bits.length - 1; i >= 0; i--)
+               {
+                       if (Bit.ONE == bits[bits.length - i - 1])
+                       {
+                               try
+                               {
+                                       bytes[bytes.length - (i / 8) - 1] |= 1 << (i % 8);
+                               }
+                               catch (IndexOutOfBoundsException e)
+                               {
+                                       e.printStackTrace();
+                               }
+                       }
+               }
+               return new BigInteger(bytes);
+       }
+
+       public long getUnsignedValueLong()
+       {
+               return getUnsignedValue().longValue();
+       }
+
+       /**
+        * Returns the value of the BitVector as BigInteger interpreted as a two's complement number.
+        * 
+        * @throws NumberFormatException if the BitVector is not {@link #isBinary() binary}.
+        * 
+        * @author Daniel Kirschten
+        */
+       public BigInteger getSignedValue()
+       {
+               BigInteger unsignedValue = getUnsignedValue();
+               if (bits[bits.length - 1] == Bit.ZERO)
+                       return unsignedValue;
+               return unsignedValue.subtract(BitVector.of(Bit.ONE, bits.length).getUnsignedValue()).subtract(BigInteger.ONE);// TODO speed this up!
+       }
+
+       public long getSignedValueLong()
+       {
+               return getSignedValue().longValue();
+       }
+
        /**
         * Parses a String containing solely {@link Bit} symbols (MSB first)
         * 
@@ -419,19 +477,18 @@ 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)
+       /**
+        * Changes a single Bit using the given operation. This can be used to set, clear or flip bits.
+        * 
+        * @param msbIndex           index of the MSB to be changed
+        * @param singleBitOperation the operation to perform on that Bit
+        * @return the resulting, new BitVektor
+        */
+       public BitVector withBitChanged(int msbIndex, UnaryOperator<Bit> singleBitOperation)
        {
-               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);
+               Bit[] newBits = bits.clone();
+               newBits[msbIndex] = singleBitOperation.apply(newBits[msbIndex]);
+               return new BitVector(newBits);
        }
 
        /**
@@ -459,4 +516,15 @@ public final class BitVector implements StrictLogicType<BitVector>, Iterable<Bit
                        }
                };
        }
+
+       public BitVector reverse()
+       {
+               int length = length();
+               Bit[] other = new Bit[length];
+               for (int i = 0, j = length - 1; i < length; i++, j--)
+               {
+                       other[i] = bits[j];
+               }
+               return new BitVector(other);
+       }
 }