/** * Creates the new instance that merges this and the given one via logical AND. * * @param that the other instance * @return this merged instance */ public Bitmask and(Bitmask that) { Bitmask copy = new Bitmask(this, that.bits.length << WORD_ADDRESS_BITS); return copy.andInPlace(that); }
/** * Creates the new instance that merges this and the given one via logical AND NOT. * * @param that the other instance * @return this merged instance */ public Bitmask andNot(Bitmask that) { Bitmask copy = new Bitmask(this, that.bits.length << WORD_ADDRESS_BITS); return copy.andNotInPlace(that); }
private String toIndexString() { StringBuilder sb = new StringBuilder(2 + this.cardinality() * 8); sb.append("{"); String separator = ""; int nextIndex = this.nextSetBit(0); while (nextIndex != -1) { sb.append(separator).append(nextIndex); separator = ", "; nextIndex = this.nextSetBit(nextIndex + 1); } sb.append("}"); return sb.toString(); }
final Bitmask excludedExistingIndices = this.existingDestinationChannelIndices.andNot( this.reachableExistingDestinationChannelIndices.getOrDefault(channelDescriptor, Bitmask.EMPTY_BITMASK) ); final Bitmask newSettledIndices = this.kernelDestChannelDescriptorsToIndices .getOrDefault(channelDescriptor, Bitmask.EMPTY_BITMASK) .andNot(settledDestinationIndices) .andNotInPlace(excludedExistingIndices) .andNotInPlace(excludedAbsentIndices); if (!newSettledIndices.isEmpty()) { if (channelDescriptor.isReusable() || newSettledIndices.cardinality() == 1) { for (int index = newSettledIndices.nextSetBit(0); index != -1; index = newSettledIndices.nextSetBit(index + 1)) { Bitmask newSettledIndicesSubset = new Bitmask(index + 1); newSettledIndicesSubset.set(index); newSolution = Tree.singleton(channelDescriptor, newSettledIndicesSubset); newSolutions.put(newSolution.settledDestinationIndices, newSolution); if (newSettledIndices.cardinality() == this.destChannelDescriptorSets.size() - excludedExistingIndices.cardinality() && (!this.isRequestBreakpoint || isVisitedBreakpointChannel)) { return newSolutions; settledDestinationIndices.orInPlace(newSettledIndices); settledDestinationIndices.andNotInPlace(newSettledIndices); for (Collection<Tree> trees : childSolutionSets) { for (Tree tree : trees) {
/** * Sets the bit at the given index. * * @param index where the bit should be set * @return whether this instance was changed */ public boolean set(int index) { if (!this.ensureCapacity(index) && this.get(index)) { return false; } final int longPos = getLongPos(index); final int offset = getOffset(index); this.bits[longPos] = this.bits[longPos] | (1L << offset); if (this.cardinalityCache != -1) this.cardinalityCache++; return true; }
/** * Flips all bits in the given range * * @param fromIndex inclusive start index of the range * @param toIndex exclusive end index of the range * @return this instance */ public Bitmask flip(int fromIndex, int toIndex) { if (fromIndex < toIndex) { this.ensureCapacity(toIndex - 1); int fromLongPos = getLongPos(fromIndex); int untilLongPos = getLongPos(toIndex - 1); for (int longPos = fromLongPos; longPos <= untilLongPos; longPos++) { int fromOffset = (longPos == fromLongPos) ? getOffset(fromIndex) : 0; int untilOffset = (longPos == untilLongPos) ? getOffset(toIndex - 1) + 1 : BITS_PER_WORD; long flipMask = createAllSetBits(untilOffset) ^ createAllSetBits(fromOffset); this.bits[longPos] ^= flipMask; } this.cardinalityCache = -1; } return this; }
for (Set<ChannelDescriptor> destChannelDescriptorSet : this.destChannelDescriptorSets) { final Bitmask indices = this.kernelDestChannelDescriptorSetsToIndices.computeIfAbsent( destChannelDescriptorSet, key -> new Bitmask(this.destChannelDescriptorSets.size()) ); this.allDestinationChannelIndices.set(index); indices.set(index++); final Bitmask indices = entry.getValue(); if (indices.cardinality() < 2) continue; this.kernelDestChannelDescriptorSetsToIndices.computeIfAbsent( channelsToIndicesChange.getField0(), key -> new Bitmask(this.destChannelDescriptorSets.size()) ).orInPlace(channelsToIndicesChange.getField1()); this.kernelDestChannelDescriptorsToIndices.merge(channelDescriptor, new Bitmask(indices), Bitmask::or);
this.existingDestinationChannelIndices = new Bitmask(); this.existingChannels = Collections.emptyMap(); this.existingDestinationChannels = Collections.emptyMap(); this.existingDestinationChannelIndices = new Bitmask(); this.openChannelDescriptors = Collections.emptySet(); final Bitmask channelIndices = this.kernelDestChannelDescriptorsToIndices .get(existingDestinationChannel.getDescriptor()) .and(this.existingDestinationChannelIndices); while (true) { this.reachableExistingDestinationChannelIndices.compute( existingDestinationChannel.getDescriptor(), (k, v) -> v == null ? new Bitmask(channelIndices) : v.orInPlace(channelIndices) ); if (existingDestinationChannel.getDescriptor().equals(this.sourceChannelDescriptor)) break; .andNot(this.existingDestinationChannelIndices);
/** * Finds the next set bit, starting from a given index. * * @param from index from that the search starts * @return the index of the set next bit or {@code -1} if there is no next set bit */ public int nextSetBit(int from) { int longPos = getLongPos(from); int offset = getOffset(from); while (longPos < this.bits.length) { long bits = this.bits[longPos]; int nextOffset = Long.numberOfTrailingZeros(bits & ~createAllSetBits(offset)); if (nextOffset < BITS_PER_WORD) { return longPos << WORD_ADDRESS_BITS | nextOffset; } longPos++; offset = 0; } return -1; }
Bitmask combinationSettledIndices = new Bitmask(firstTree.settledDestinationIndices); int maxSettledIndices = combinationSettledIndices.cardinality(); final HashSet<ChannelDescriptor> employedChannelDescriptors = new HashSet<>(firstTree.employedChannelDescriptors); int maxVisitedChannelDescriptors = employedChannelDescriptors.size(); final Tree ithTree = iterator.next(); combinationSettledIndices.orInPlace(ithTree.settledDestinationIndices); maxSettledIndices += ithTree.settledDestinationIndices.cardinality(); if (maxSettledIndices > combinationSettledIndices.cardinality()) { return null;
/** * Starts the actual search. */ private Tree searchTree() { // Prepare the recursive traversal. final HashSet<ChannelDescriptor> visitedChannelDescriptors = new HashSet<>(16); visitedChannelDescriptors.add(this.sourceChannelDescriptor); // Perform the traversal. final Map<Bitmask, Tree> solutions = this.enumerate( visitedChannelDescriptors, this.sourceChannelDescriptor, Bitmask.EMPTY_BITMASK, this.sourceChannelDescriptor.isSuitableForBreakpoint() ); // Get hold of a comprehensive solution (if it exists). Bitmask requestedIndices = new Bitmask(this.destChannelDescriptorSets.size()); requestedIndices.flip(0, this.destChannelDescriptorSets.size()); return solutions.get(requestedIndices); }
for (int index = vertex.settledIndices.nextSetBit(0); index >= 0; index = vertex.settledIndices.nextSetBit(index + 1)) { if (!this.existingDestinationChannelIndices.get(index) && this.openChannelDescriptors.contains(baseChannel.getDescriptor())) { if (baseChannelCopy == null) baseChannelCopy = baseChannel.copy(); junction.setTargetChannel(index, baseChannelCopy);
/** * Accumulates the given instance to this one via logical AND NOT. * * @param that that should be accumulated * @return this instance */ public Bitmask andNotInPlace(Bitmask that) { this.ensureCapacity(that.bits.length << WORD_ADDRESS_BITS); for (int i = 0; i < that.bits.length; i++) { this.bits[i] &= ~that.bits[i]; } this.cardinalityCache = -1; return this; }
/** * Tells whether this instance is empty. * * @return whether this instance is empty */ public boolean isEmpty() { return this.cardinality() == 0; }
/** * Creates a new instance with a single {@link TreeVertex}. * * @param channelDescriptor represented by the {@link TreeVertex} * @param settledIndices indices to destinations settled by the {@code channelDescriptor} * @return the new instance */ static Tree singleton(ChannelDescriptor channelDescriptor, Bitmask settledIndices) { return new Tree(new TreeVertex(channelDescriptor, settledIndices), new Bitmask(settledIndices)); }
/** * Accumulates the given instance to this one via logical OR. * * @param that that should be accumulated * @return this instance */ public Bitmask orInPlace(Bitmask that) { this.ensureCapacity(that.bits.length << WORD_ADDRESS_BITS); for (int i = 0; i < that.bits.length; i++) { this.bits[i] |= that.bits[i]; } this.cardinalityCache = -1; return this; }
/** * Accumulates the given instance to this one via logical AND. * * @param that that should be accumulated * @return this instance */ public Bitmask andInPlace(Bitmask that) { this.ensureCapacity(that.bits.length << WORD_ADDRESS_BITS); for (int i = 0; i < that.bits.length; i++) { this.bits[i] &= that.bits[i]; } for (int i = that.bits.length; i < this.bits.length; i++) { this.bits[i] = 0; } this.cardinalityCache = -1; return this; }