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 @SuppressWarnings("synthetic-access")
144 public static final class BitVectorMutator implements LogicType<BitVectorMutator, BitVector>
148 private BitVectorMutator(Bit[] bits)
153 static BitVectorMutator of(BitVector bv)
155 return new BitVectorMutator(bv.getBits());
159 * Returns an empty mutator which has no bits set and will simply copy the values from the first binary operation performed.
162 public static BitVectorMutator empty()
164 return new BitVectorMutator(null);
168 * Produces the resulting, immutable {@link BitVector}<br>
170 * @throws IllegalStateException if the mutator is (still) empty
172 public BitVector get()
175 throw new IllegalStateException("cannot create a BitVector from an empty mutator");
176 return new BitVector(bits);
180 public BitVectorMutator join(BitVector t)
182 checkCompatibility(t);
183 bits = binOp(bits, t.bits, Bit::join);
188 public BitVectorMutator and(BitVector t)
190 checkCompatibility(t);
191 bits = binOp(bits, t.bits, Bit::and);
196 public BitVectorMutator or(BitVector t)
198 checkCompatibility(t);
199 bits = binOp(bits, t.bits, Bit::or);
204 public BitVectorMutator xor(BitVector t)
206 checkCompatibility(t);
207 bits = binOp(bits, t.bits, Bit::xor);
212 public BitVectorMutator not()
214 unOp(bits, Bit::not);
218 private void checkCompatibility(BitVector bv)
220 if (bits != null && bits.length != bv.length())
221 throw new IllegalArgumentException(format("BitVector length does not match: %d and %d", bits.length, bv.length()));
226 * @see Arrays#hashCode(Object[])
229 public int hashCode()
231 return Arrays.hashCode(bits);
235 * Does test for equality of values/content
237 * @see Object#equals(Object)
240 public boolean equals(Object obj)
244 if (!(obj instanceof BitVector))
246 BitVector other = (BitVector) obj;
247 return Arrays.equals(bits, other.bits);
251 * Does test for equality of values/content, shifting the other BitVector by <code>offset</code> to the right.<br>
252 * Therefore <code>offset + other.length() <= this.length()</code> needs to be true.
254 * @throws ArrayIndexOutOfBoundsException if <code>offset + other.length() > this.length()</code>
256 * @see Object#equals(Object)
258 public boolean equalsWithOffset(BitVector other, int offset)
262 return Arrays.equals(bits, offset, offset + other.length(), other.bits, 0, other.length());
266 * All {@link Bit}s symbols concatenated together
268 * @see #parse(String)
271 public String toString()
273 StringBuilder sb = new StringBuilder(bits.length);
276 return sb.toString();
280 * Parses a String containing solely {@link Bit} symbols
284 public static BitVector parse(String s)
286 Bit[] values = new Bit[s.length()];
287 for (int i = 0; i < s.length(); i++)
289 values[i] = Bit.parse(s, i);
291 return new BitVector(values);
295 public Iterator<Bit> iterator()
297 return new Iterator<>()
305 throw new NoSuchElementException();
306 return getBit(pos++);
310 public boolean hasNext()
312 return pos != length();