All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.chocosolver.memory.structure.OneWordS64BitSet Maven / Gradle / Ivy

There is a newer version: 4.10.16
Show newest version
/**
 * Copyright (c) 2016, Ecole des Mines de Nantes
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 * 3. All advertising materials mentioning features or use of this software
 *    must display the following acknowledgement:
 *    This product includes software developed by the .
 * 4. Neither the name of the  nor the
 *    names of its contributors may be used to endorse or promote products
 *    derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY  ''AS IS'' AND ANY
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL  BE LIABLE FOR ANY
 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
package org.chocosolver.memory.structure;

import org.chocosolver.memory.IEnvironment;
import org.chocosolver.memory.IStateBitSet;
import org.chocosolver.memory.IStateLong;

import java.lang.reflect.Array;
import java.util.BitSet;


public class OneWordS64BitSet implements IStateBitSet {

    /*
    * BitSets are packed into arrays of "word."  Currently a word is
    * a long, which consists of 64 bits, requiring 6 address bits.
    * The choice of word size is determined purely by performance concerns.
    */
    private final static int ADDRESS_BITS_PER_WORD = 6;
    private final static int BITS_PER_WORD = 1 << ADDRESS_BITS_PER_WORD;

    /* Used to shift left or right for a partial word mask */
    private static final long WORD_MASK = 0xffffffffffffffffL;

    /**
     * The current environment.
     */
    private final IEnvironment environment;

    /**
     * The internal field corresponding to the serialField "bits".
     */
    private IStateLong word;

    /**
     * Creates a new bit set. All bits are initially false.
     *
     * @param environment bactrackable environment
     */
    public OneWordS64BitSet(IEnvironment environment) {
        this.environment = environment;
        word = this.environment.makeLong(0);
    }

    /**
     * Creates a bit set whose initial size is large enough to explicitly
     * represent bits with indices in the range 0 through
     * nbits-1. All bits are initially false.
     *
     * @param environment backtrackable environment
     * @param nbits       the initial size of the bit set.
     * @throws NegativeArraySizeException if the specified initial size
     *                                    is negative.
     */
    public OneWordS64BitSet(IEnvironment environment, int nbits) {
        this.environment = environment;
        // nbits can't be negative; size 0 is OK
        if (nbits < 0)
            throw new NegativeArraySizeException("nbits < 0: " + nbits);
        if (nbits > 64)
            throw new ArrayIndexOutOfBoundsException("nbits > 64: " + nbits);

        word = this.environment.makeLong(0);
    }

    @SuppressWarnings({"unchecked"})
    public static  T[] copyOf(T[] original, int newLength) {
        return (T[]) copyOf(original, newLength, original.getClass());
    }

    @SuppressWarnings({"unchecked", "SuspiciousSystemArraycopy", "RedundantCast"})
    public static  T[] copyOf(U[] original, int newLength, Class newType) {
        T[] copy = ((Object) newType == (Object) Object[].class)
                ? (T[]) new Object[newLength]
                : (T[]) Array.newInstance(newType.getComponentType(), newLength);
        System.arraycopy(original, 0, copy, 0,
                Math.min(original.length, newLength));
        return copy;
    }

    public BitSet copyToBitSet() {
        BitSet view = new BitSet(this.size());
        for (int i = this.nextSetBit(0); i >= 0; i = this.nextSetBit(i + 1)) view.set(i, true);
        return view;
    }

    /**
     * Checks that fromIndex ... toIndex is a valid range of bit indices.
     *
     * @param fromIndex starting index
     * @param toIndex   ending index
     */
    private static void checkRange(int fromIndex, int toIndex) {
        if (fromIndex < 0)
            throw new IndexOutOfBoundsException("fromIndex < 0: " + fromIndex);
        if (toIndex < 0)
            throw new IndexOutOfBoundsException("toIndex < 0: " + toIndex);
        if (fromIndex > toIndex)
            throw new IndexOutOfBoundsException("fromIndex: " + fromIndex + " > toIndex: " + toIndex);
    }

    /**
     * Sets the bit at the specified index to the complement of its
     * current value.
     *
     * @param bitIndex the index of the bit to flip.
     * @throws IndexOutOfBoundsException if the specified index is negative.
     * @since 1.4
     */
    public void flip(int bitIndex) {
        if (bitIndex < 0)
            throw new IndexOutOfBoundsException("bitIndex < 0: " + bitIndex);

        long tmp = word.get();
        tmp ^= (1L << bitIndex);
        word.set(tmp);
    }

    /**
     * Sets each bit from the specified fromIndex (inclusive) to the
     * specified toIndex (exclusive) to the complement of its current
     * value.
     *
     * @param fromIndex index of the first bit to flip.
     * @param toIndex   index after the last bit to flip.
     * @throws IndexOutOfBoundsException if fromIndex is negative,
     *                                   or toIndex is negative, or fromIndex is
     *                                   larger than toIndex.
     * @since 1.4
     */
    public void flip(int fromIndex, int toIndex) {
        checkRange(fromIndex, toIndex);

        if (fromIndex == toIndex)
            return;
        long firstWordMask = WORD_MASK << fromIndex;
        long lastWordMask = WORD_MASK >>> -toIndex;
        long tmp = word.get();
        tmp ^= (firstWordMask & lastWordMask);
        word.set(tmp);
    }

    /**
     * Sets the bit at the specified index to true.
     *
     * @param bitIndex a bit index.
     * @throws IndexOutOfBoundsException if the specified index is negative.
     * @since JDK1.0
     */
    public void set(int bitIndex) {
        if (bitIndex < 0)
            throw new IndexOutOfBoundsException("bitIndex < 0: " + bitIndex);

        word.set(word.get() | (1L << bitIndex)); // Restores invariants
        //checkInvariants();
    }

    /**
     * Sets the bit at the specified index to the specified value.
     *
     * @param bitIndex a bit index.
     * @param value    a boolean value to set.
     * @throws IndexOutOfBoundsException if the specified index is negative.
     * @since 1.4
     */
    public void set(int bitIndex, boolean value) {
        if (value)
            set(bitIndex);
        else
            clear(bitIndex);
    }

    /**
     * Sets the bits from the specified fromIndex (inclusive) to the
     * specified toIndex (exclusive) to true.
     *
     * @param fromIndex index of the first bit to be set.
     * @param toIndex   index after the last bit to be set.
     * @throws IndexOutOfBoundsException if fromIndex is negative,
     *                                   or toIndex is negative, or fromIndex is
     *                                   larger than toIndex.
     * @since 1.4
     */
    public void set(int fromIndex, int toIndex) {
        checkRange(fromIndex, toIndex);

        if (fromIndex == toIndex)
            return;

        long firstWordMask = WORD_MASK << fromIndex;
        long lastWordMask = WORD_MASK >>> -toIndex;
        word.set(word.get() | (firstWordMask & lastWordMask));
        //checkInvariants();
    }

    /**
     * Sets the bits from the specified fromIndex (inclusive) to the
     * specified toIndex (exclusive) to the specified value.
     *
     * @param fromIndex index of the first bit to be set.
     * @param toIndex   index after the last bit to be set
     * @param value     value to set the selected bits to
     * @throws IndexOutOfBoundsException if fromIndex is negative,
     *                                   or toIndex is negative, or fromIndex is
     *                                   larger than toIndex.
     * @since 1.4
     */
    public void set(int fromIndex, int toIndex, boolean value) {
        if (value)
            set(fromIndex, toIndex);
        else
            clear(fromIndex, toIndex);
    }

    /**
     * Sets the bit specified by the index to false.
     *
     * @param bitIndex the index of the bit to be cleared.
     * @throws IndexOutOfBoundsException if the specified index is negative.
     * @since JDK1.0
     */
    public void clear(int bitIndex) {
        if (bitIndex < 0)
            throw new IndexOutOfBoundsException("bitIndex < 0: " + bitIndex);

        word.set(word.get() & ~(1L << bitIndex));
        //checkInvariants();
    }

    /**
     * Sets the bits from the specified fromIndex (inclusive) to the
     * specified toIndex (exclusive) to false.
     *
     * @param fromIndex index of the first bit to be cleared.
     * @param toIndex   index after the last bit to be cleared.
     * @throws IndexOutOfBoundsException if fromIndex is negative,
     *                                   or toIndex is negative, or fromIndex is
     *                                   larger than toIndex.
     * @since 1.4
     */
    public void clear(int fromIndex, int toIndex) {
        checkRange(fromIndex, toIndex);

        if (fromIndex == toIndex)
            return;

        long firstWordMask = WORD_MASK << fromIndex;
        long lastWordMask = WORD_MASK >>> -toIndex;
        word.set(word.get() & ~(firstWordMask & lastWordMask));
        //checkInvariants();
    }

    /**
     * Sets all of the bits in this BitSet to false.
     *
     * @since 1.4
     */
    public void clear() {
        word.set(0);
    }

    /**
     * Returns the value of the bit with the specified index. The value
     * is true if the bit with the index bitIndex
     * is currently set in this BitSet; otherwise, the result
     * is false.
     *
     * @param bitIndex the bit index.
     * @return the value of the bit with the specified index.
     * @throws IndexOutOfBoundsException if the specified index is negative.
     */
    final public boolean get(final int bitIndex) {
        //if (bitIndex < 0)
        //    throw new IndexOutOfBoundsException("bitIndex < 0: " + bitIndex);

        //checkInvariants();
        return bitIndex < 64 && ((word.get() & (1L << bitIndex)) != 0);
    }

    /**
     * Returns a new BitSet composed of bits from this BitSet
     * from fromIndex (inclusive) to toIndex (exclusive).
     *
     * @param fromIndex index of the first bit to include.
     * @param toIndex   index after the last bit to include.
     * @return a new BitSet from a range of this BitSet.
     * @throws IndexOutOfBoundsException if fromIndex is negative,
     *                                   or toIndex is negative, or fromIndex is
     *                                   larger than toIndex.
     * @since 1.4
     */
    @SuppressWarnings("UnusedParameters")
    public OneWordS64BitSet get(int fromIndex, int toIndex) {
        throw new UnsupportedOperationException();
    }

    /**
     * Returns the index of the first bit that is set to {@code true}
     * that occurs on or after the specified starting index. If no such
     * bit exists then {@code -1} is returned.
     * 

*

To iterate over the {@code true} bits in a {@code BitSet}, * use the following loop: *

*

 {@code
     * for (int i = bs.nextSetBit(0); i >= 0; i = bs.nextSetBit(i+1)) {
     *     // operate on index i here
     * }}
* * @param fromIndex the index to start checking from (inclusive) * @return the index of the next set bit, or {@code -1} if there * is no such bit * @throws IndexOutOfBoundsException if the specified index is negative * @since 1.4 */ public int nextSetBit(int fromIndex) { if (fromIndex < 0) { fromIndex = 0; } if (fromIndex >= 64) return -1; long word = this.word.get() & (WORD_MASK << fromIndex); if (word != 0) return Long.numberOfTrailingZeros(word); else return -1; } /** * Returns the index of the first bit that is set to {@code false} * that occurs on or after the specified starting index. * * @param fromIndex the index to start checking from (inclusive) * @return the index of the next clear bit * @throws IndexOutOfBoundsException if the specified index is negative * @since 1.4 */ public int nextClearBit(int fromIndex) { // Neither spec nor implementation handle bitsets of maximal length. // See 4816253. if (fromIndex < 0) { fromIndex = 0; } if (fromIndex >= 64) return fromIndex; long word = ~this.word.get() & (WORD_MASK << fromIndex); if (word != 0) return Long.numberOfTrailingZeros(word); else return 0; } /** * Returns the index of the nearest bit that is set to {@code true} * that occurs on or before the specified starting index. * If no such bit exists, or if {@code -1} is given as the * starting index, then {@code -1} is returned. *

*

To iterate over the {@code true} bits in a {@code BitSet}, * use the following loop: *

*

 {@code
     * for (int i = bs.length(); (i = bs.previousSetBit(i-1)) >= 0; ) {
     *     // operate on index i here
     * }}
* * @param fromIndex the index to start checking from (inclusive) * @return the index of the previous set bit, or {@code -1} if there * is no such bit * @throws IndexOutOfBoundsException if the specified index is less * than {@code -1} * @since 1.7 */ public int prevSetBit(int fromIndex) { if (fromIndex < 0) { return -1; } if (fromIndex >= 64) return length() - 1; long word = this.word.get() & (WORD_MASK >>> -(fromIndex + 1)); if (word != 0) return BITS_PER_WORD - 1 - Long.numberOfLeadingZeros(word); else return -1; } /** * Returns the index of the nearest bit that is set to {@code false} * that occurs on or before the specified starting index. * If no such bit exists, or if {@code -1} is given as the * starting index, then {@code -1} is returned. * * @param fromIndex the index to start checking from (inclusive) * @return the index of the previous clear bit, or {@code -1} if there * is no such bit * @throws IndexOutOfBoundsException if the specified index is less * than {@code -1} * @since 1.7 */ public int prevClearBit(int fromIndex) { if (fromIndex < 0) { return -1; } if (fromIndex >= 64) return fromIndex; long word = ~this.word.get() & (WORD_MASK >>> -(fromIndex + 1)); if (word != 0) return BITS_PER_WORD - 1 - Long.numberOfLeadingZeros(word); else return -1; } public int capacity() { return BITS_PER_WORD; } /** * Returns the "logical size" of this BitSet: the index of * the highest set bit in the BitSet plus one. Returns zero * if the BitSet contains no set bits. * * @return the logical size of this BitSet. * @since 1.2 */ public int length() { return (BITS_PER_WORD - Long.numberOfLeadingZeros(word.get())); } /** * Returns true if this BitSet contains no bits that are set * to true. * * @return boolean indicating whether this BitSet is empty. * @since 1.4 */ public boolean isEmpty() { return word.get() == 0; } /** * Returns the number of bits set to true in this * BitSet. * * @return the number of bits set to true in this * BitSet. * @since 1.4 */ public int cardinality() { return Long.bitCount(word.get()); } /** * Performs a logical AND of this target bit set with the * argument bit set. This bit set is modified so that each bit in it * has the value true if and only if it both initially * had the value true and the corresponding bit in the * bit set argument also had the value true. * * @param setI a bit set. */ public void and(IStateBitSet setI) { throw new UnsupportedOperationException(); } /** * Performs a logical OR of this bit set with the bit set * argument. This bit set is modified so that a bit in it has the * value true if and only if it either already had the * value true or the corresponding bit in the bit set * argument has the value true. * * @param setI a bit set. */ public void or(IStateBitSet setI) { throw new UnsupportedOperationException(); } /** * Performs a logical XOR of this bit set with the bit set * argument. This bit set is modified so that a bit in it has the * value true if and only if one of the following * statements holds: *
    *
  • The bit initially has the value true, and the * corresponding bit in the argument has the value false. *
  • The bit initially has the value false, and the * corresponding bit in the argument has the value true. *
* * @param setI a bit set. */ public void xor(IStateBitSet setI) { throw new UnsupportedOperationException(); } /** * Clears all of the bits in this BitSet whose corresponding * bit is set in the specified BitSet. * * @param setI the BitSet with which to mask this * BitSet. * @since 1.2 */ public void andNot(IStateBitSet setI) { throw new UnsupportedOperationException(); } /** * Returns true if the specified BitSet has any bits set to * true that are also set to true in this * BitSet. * * @param setI BitSet to intersect with * @return boolean indicating whether this BitSet intersects * the specified BitSet. * @since 1.4 */ public boolean intersects(IStateBitSet setI) { throw new UnsupportedOperationException(); } public int hashCode() { long h = 1234; h ^= word.get(); return (int) ((h >> 32) ^ h); } /** * Returns the number of bits of space actually in use by this * BitSet to represent bit values. * The maximum element in the set is the size - 1st element. * * @return the number of bits currently in this bit set. */ public int size() { return BITS_PER_WORD; } public boolean equals(Object obj) { if (!(obj instanceof OneWordS64BitSet)) return false; if (this == obj) return true; OneWordS64BitSet set = (OneWordS64BitSet) obj; //checkInvariants(); //set.checkInvariants(); // Check word in use by both BitSets return word == set.word; } public IStateBitSet copy() { //if (!sizeIsSticky.get()) trimToSize(); OneWordS64BitSet result = new OneWordS64BitSet(environment, this.size()); //result.sizeIsSticky.set(sizeIsSticky.get()); result.word.set(word.get()); //result.checkInvariants(); return result; } public String toString() { //checkInvariants(); int numBits = BITS_PER_WORD; StringBuilder b = new StringBuilder(6 * numBits + 2); b.append('{'); int i = nextSetBit(0); if (i != -1) { b.append(i); for (i = nextSetBit(i + 1); i >= 0; i = nextSetBit(i + 1)) { int endOfRun = nextClearBit(i); do { b.append(", ").append(i); } while (++i < endOfRun); } } b.append('}'); return b.toString(); } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy