1 package net.mograsim.logic.core.types;
3 import static java.lang.String.format;
5 import java.util.Arrays;
6 import java.util.Iterator;
7 import java.util.NoSuchElementException;
8 import java.util.Objects;
9 import java.util.RandomAccess;
10 import java.util.function.BinaryOperator;
11 import java.util.function.UnaryOperator;
14 * Immutable class representing a {@link Bit}Vector
17 * @author Christian Femers
20 public final class BitVector implements StrictLogicType<BitVector>, Iterable<Bit>, RandomAccess
22 private final Bit[] bits;
24 private BitVector(Bit[] bits)
26 this.bits = Objects.requireNonNull(bits);
29 public static BitVector of(Bit... bits)
31 return new BitVector(bits.clone());
34 public static BitVector of(Bit bit, int length)
36 return new BitVector(bit.makeArray(length));
39 public BitVectorMutator mutator()
41 return BitVectorMutator.of(this);
44 public Bit getBit(int bitIndex)
46 return bits[bitIndex];
49 public Bit[] getBits()
55 public BitVector join(BitVector t)
57 checkCompatibility(t);
58 return new BitVector(binOp(bits.clone(), t.bits, Bit::join));
62 public BitVector and(BitVector t)
64 checkCompatibility(t);
65 return new BitVector(binOp(bits.clone(), t.bits, Bit::and));
69 public BitVector or(BitVector t)
71 checkCompatibility(t);
72 return new BitVector(binOp(bits.clone(), t.bits, Bit::or));
76 public BitVector xor(BitVector t)
78 checkCompatibility(t);
79 return new BitVector(binOp(bits.clone(), t.bits, Bit::xor));
83 public BitVector not()
85 return new BitVector(unOp(bits.clone(), Bit::not));
93 public BitVector concat(BitVector other)
95 Bit[] newBits = Arrays.copyOf(bits, length() + other.length());
96 System.arraycopy(other.bits, 0, newBits, length(), other.length());
97 return new BitVector(newBits);
100 public BitVector subVector(int start)
102 return new BitVector(Arrays.copyOfRange(bits, start, length()));
105 public BitVector subVector(int start, int end)
107 return new BitVector(Arrays.copyOfRange(bits, start, end));
110 private void checkCompatibility(BitVector bv)
112 if (length() != bv.length())
113 throw new IllegalArgumentException(format("BitVector length does not match: %d and %d", length(), bv.length()));
116 static Bit[] binOp(Bit[] dest, Bit[] second, BinaryOperator<Bit> op)
119 return second.clone();
120 for (int i = 0; i < dest.length; i++)
122 dest[i] = op.apply(dest[i], second[i]);
127 static Bit[] unOp(Bit[] dest, UnaryOperator<Bit> op)
131 for (int i = 0; i < dest.length; i++)
133 dest[i] = op.apply(dest[i]);
139 * Class for comfortable and efficient manipulation of {@link BitVector}s, similar to {@link StringBuilder}
141 * @author Christian Femers
143 public static final class BitVectorMutator implements LogicType<BitVectorMutator, BitVector>
147 private BitVectorMutator(Bit[] bits)
152 static BitVectorMutator of(BitVector bv)
154 return new BitVectorMutator(bv.getBits());
158 * Returns a new mutator of the specified length, <b>with all bits set to <code>null</code></b>. Use with care!
160 public static BitVectorMutator ofLength(int length)
162 return new BitVectorMutator(new Bit[length]);
166 * Returns an empty mutator which has no bits set and will simply copy the values from the first binary operation performed.
168 public static BitVectorMutator empty()
170 return new BitVectorMutator(null);
174 * Produces the resulting, immutable {@link BitVector}<br>
176 * @throws IllegalStateException if the mutator is (still) empty
178 public BitVector toBitVector()
181 throw new IllegalStateException("cannot create a BitVector from an empty mutator");
182 return new BitVector(bits);
186 public BitVectorMutator join(BitVector t)
188 checkCompatibility(t);
189 bits = binOp(bits, t.bits, Bit::join);
194 public BitVectorMutator and(BitVector t)
196 checkCompatibility(t);
197 bits = binOp(bits, t.bits, Bit::and);
202 public BitVectorMutator or(BitVector t)
204 checkCompatibility(t);
205 bits = binOp(bits, t.bits, Bit::or);
210 public BitVectorMutator xor(BitVector t)
212 checkCompatibility(t);
213 bits = binOp(bits, t.bits, Bit::xor);
218 public BitVectorMutator not()
220 unOp(bits, Bit::not);
224 public void setBit(int bitIndex, Bit bit)
226 bits[bitIndex] = bit;
229 public Bit getBit(int bitIndex)
231 return bits[bitIndex];
239 private void checkCompatibility(BitVector bv)
241 if (bits != null && bits.length != bv.length())
242 throw new IllegalArgumentException(format("BitVector length does not match: %d and %d", bits.length, bv.length()));
247 * @see Arrays#hashCode(Object[])
250 public int hashCode()
252 return Arrays.hashCode(bits);
256 * Does test for equality of values/content
258 * @see Object#equals(Object)
261 public boolean equals(Object obj)
265 if (!(obj instanceof BitVector))
267 BitVector other = (BitVector) obj;
268 return Arrays.equals(bits, other.bits);
272 * Does test for equality of values/content, shifting the other BitVector by <code>offset</code> to the right.<br>
273 * Therefore <code>offset + other.length() <= this.length()</code> needs to be true.
275 * @throws ArrayIndexOutOfBoundsException if <code>offset + other.length() > this.length()</code>
277 * @see Object#equals(Object)
279 public boolean equalsWithOffset(BitVector other, int offset)
283 return Arrays.equals(bits, offset, offset + other.length(), other.bits, 0, other.length());
287 * All {@link Bit}s symbols concatenated together
289 * @see #parse(String)
292 public String toString()
294 StringBuilder sb = new StringBuilder(bits.length);
297 return sb.toString();
301 * Parses a String containing solely {@link Bit} symbols
305 public static BitVector parse(String s)
307 Bit[] values = new Bit[s.length()];
308 for (int i = 0; i < s.length(); i++)
310 values[i] = Bit.parse(s, i);
312 return new BitVector(values);
316 public Iterator<Bit> iterator()
318 return new Iterator<>()
326 throw new NoSuchElementException();
327 return getBit(pos++);
331 public boolean hasNext()
333 return pos != length();