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);// do this first to "catch" bits==null before the foreach loop
29 throw new NullPointerException();
32 public static BitVector of(Bit... bits)
34 return new BitVector(bits.clone());
37 public static BitVector of(Bit bit, int length)
39 return new BitVector(bit.makeArray(length));
42 public BitVectorMutator mutator()
44 return BitVectorMutator.of(this);
47 public Bit getBit(int bitIndex)
49 return bits[bitIndex];
52 public Bit[] getBits()
58 public BitVector join(BitVector t)
60 checkCompatibility(t);
61 return new BitVector(binOp(bits.clone(), t.bits, Bit::join));
65 public BitVector and(BitVector t)
67 checkCompatibility(t);
68 return new BitVector(binOp(bits.clone(), t.bits, Bit::and));
72 public BitVector or(BitVector t)
74 checkCompatibility(t);
75 return new BitVector(binOp(bits.clone(), t.bits, Bit::or));
79 public BitVector xor(BitVector t)
81 checkCompatibility(t);
82 return new BitVector(binOp(bits.clone(), t.bits, Bit::xor));
86 public BitVector not()
88 return new BitVector(unOp(bits.clone(), Bit::not));
96 public BitVector concat(BitVector other)
98 Bit[] newBits = Arrays.copyOf(bits, length() + other.length());
99 System.arraycopy(other.bits, 0, newBits, length(), other.length());
100 return new BitVector(newBits);
103 public BitVector subVector(int start)
105 return new BitVector(Arrays.copyOfRange(bits, start, length()));
108 public BitVector subVector(int start, int end)
110 return new BitVector(Arrays.copyOfRange(bits, start, end));
113 private void checkCompatibility(BitVector bv)
115 if (length() != bv.length())
116 throw new IllegalArgumentException(format("BitVector length does not match: %d and %d", length(), bv.length()));
119 static Bit[] binOp(Bit[] dest, Bit[] second, BinaryOperator<Bit> op)
122 return second.clone();
123 for (int i = 0; i < dest.length; i++)
125 dest[i] = op.apply(dest[i], second[i]);
130 static Bit[] unOp(Bit[] dest, UnaryOperator<Bit> op)
134 for (int i = 0; i < dest.length; i++)
136 dest[i] = op.apply(dest[i]);
142 * Class for comfortable and efficient manipulation of {@link BitVector}s, similar to {@link StringBuilder}
144 * @author Christian Femers
146 public static final class BitVectorMutator implements LogicType<BitVectorMutator, BitVector>
150 private BitVectorMutator(Bit[] bits)
155 static BitVectorMutator of(BitVector bv)
157 return new BitVectorMutator(bv.getBits());
161 * Returns a new mutator of the specified length, <b>with all bits set to <code>null</code></b>. Use with care!
163 public static BitVectorMutator ofLength(int length)
165 return new BitVectorMutator(new Bit[length]);
169 * Returns an empty mutator which has no bits set and will simply copy the values from the first binary operation performed.
171 public static BitVectorMutator empty()
173 return new BitVectorMutator(null);
177 * Produces the resulting, immutable {@link BitVector}<br>
179 * @throws IllegalStateException if the mutator is (still) empty
181 public BitVector toBitVector()
184 throw new IllegalStateException("cannot create a BitVector from an empty mutator");
185 return new BitVector(bits);
189 public BitVectorMutator join(BitVector t)
191 checkCompatibility(t);
192 bits = binOp(bits, t.bits, Bit::join);
197 public BitVectorMutator and(BitVector t)
199 checkCompatibility(t);
200 bits = binOp(bits, t.bits, Bit::and);
205 public BitVectorMutator or(BitVector t)
207 checkCompatibility(t);
208 bits = binOp(bits, t.bits, Bit::or);
213 public BitVectorMutator xor(BitVector t)
215 checkCompatibility(t);
216 bits = binOp(bits, t.bits, Bit::xor);
221 public BitVectorMutator not()
223 unOp(bits, Bit::not);
227 public void setBit(int bitIndex, Bit bit)
229 bits[bitIndex] = bit;
232 public Bit getBit(int bitIndex)
234 return bits[bitIndex];
242 private void checkCompatibility(BitVector bv)
244 if (bits != null && bits.length != bv.length())
245 throw new IllegalArgumentException(format("BitVector length does not match: %d and %d", bits.length, bv.length()));
250 * @see Arrays#hashCode(Object[])
253 public int hashCode()
255 return Arrays.hashCode(bits);
259 * Does test for equality of values/content
261 * @see Object#equals(Object)
264 public boolean equals(Object obj)
268 if (!(obj instanceof BitVector))
270 BitVector other = (BitVector) obj;
271 return Arrays.equals(bits, other.bits);
275 * Does test for equality of values/content, shifting the other BitVector by <code>offset</code> to the right.<br>
276 * Therefore <code>offset + other.length() <= this.length()</code> needs to be true.
278 * @throws ArrayIndexOutOfBoundsException if <code>offset + other.length() > this.length()</code>
280 * @see Object#equals(Object)
282 public boolean equalsWithOffset(BitVector other, int offset)
286 return Arrays.equals(bits, offset, offset + other.length(), other.bits, 0, other.length());
290 * All {@link Bit}s symbols concatenated together
292 * @see #parse(String)
295 public String toString()
297 StringBuilder sb = new StringBuilder(bits.length);
300 return sb.toString();
304 * Parses a String containing solely {@link Bit} symbols
308 public static BitVector parse(String s)
310 Bit[] values = new Bit[s.length()];
311 for (int i = 0; i < s.length(); i++)
313 values[i] = Bit.parse(s, i);
315 return new BitVector(values);
319 public Iterator<Bit> iterator()
321 return new Iterator<>()
329 throw new NoSuchElementException();
330 return getBit(pos++);
334 public boolean hasNext()
336 return pos != length();