com.yandex.yoctodb.util.mutable.impl.LongArrayBitSet.java Source code

Java tutorial

Introduction

Here is the source code for com.yandex.yoctodb.util.mutable.impl.LongArrayBitSet.java

Source

/*
 * (C) YANDEX LLC, 2014-2016
 *
 * The Source Code called "YoctoDB" available at
 * https://github.com/yandex/yoctodb is subject to the terms of the
 * Mozilla Public License, v. 2.0 (hereinafter referred to as the "License").
 *
 * A copy of the License is also available at http://mozilla.org/MPL/2.0/.
 */

package com.yandex.yoctodb.util.mutable.impl;

import com.google.common.primitives.Longs;
import com.yandex.yoctodb.util.buf.Buffer;
import com.yandex.yoctodb.util.mutable.ArrayBitSet;
import com.yandex.yoctodb.util.mutable.BitSet;
import net.jcip.annotations.NotThreadSafe;
import org.jetbrains.annotations.NotNull;

import java.util.Arrays;

/**
 * {@link BitSet} implementation based on {@code long} array.
 *
 * Based on Lucene {@code FixedBitSet}.
 *
 * @author incubos
 */
@NotThreadSafe
public final class LongArrayBitSet implements ArrayBitSet {
    private final int size;
    private final int usedWords;
    @NotNull
    private final long[] words;

    private LongArrayBitSet(final int size, @NotNull final long[] words) {
        assert size >= 0;
        assert words.length >= arraySize(size);

        this.size = size;
        this.usedWords = arraySize(size);
        this.words = words;
    }

    static int arraySize(final int size) {
        return (size >>> 6) + 1;
    }

    @NotNull
    static ArrayBitSet zero(final int size, @NotNull final long[] words) {
        final LongArrayBitSet result = new LongArrayBitSet(size, words);
        Arrays.fill(result.words, 0, result.usedWords, 0L);
        return result;
    }

    @NotNull
    public static ArrayBitSet zero(final int size) {
        return new LongArrayBitSet(size, new long[arraySize(size)]);
    }

    @NotNull
    public static ArrayBitSet one(final int size) {
        final LongArrayBitSet result = new LongArrayBitSet(size, new long[arraySize(size)]);

        // Filling with ones
        final int last = result.usedWords - 1;
        Arrays.fill(result.words, 0, last, -1L);
        final int shift = size & 0x3f;
        if (shift != 0) {
            result.words[last] = ~(-1L << shift);
        }

        return result;
    }

    @Override
    public int getSize() {
        return size;
    }

    @Override
    public int cardinality() {
        int result = 0;
        for (int i = 0; i < usedWords; i++) {
            result += Long.bitCount(words[i]);
        }

        return result;
    }

    @NotNull
    @Override
    public long[] toArray() {
        return words;
    }

    @Override
    public void set(final int i) {
        assert 0 <= i && i < size;
        final int word = i >> 6; // div 64
        final int bit = i & 0x3f; // mod 64
        final long mask = 1L << bit;
        words[word] |= mask;
    }

    @Override
    public boolean get(final int i) {
        assert 0 <= i && i < size;
        final int word = i >> 6; // div 64
        final int bit = i & 0x3f; // mod 64
        final long mask = 1L << bit;
        return (words[word] & mask) != 0;
    }

    public void clear() {
        Arrays.fill(words, 0, usedWords, 0L);
    }

    @Override
    public boolean inverse() {
        boolean notEmpty = false;

        // Inverse all the words except last one
        final int last = usedWords - 1;
        for (int i = 0; i < last; i++) {
            words[i] = ~words[i];
            if (words[i] != 0)
                notEmpty = true;
        }

        // Fix bits in last word
        final int shift = size & 0x3f;
        if (shift != 0) {
            words[last] = ~words[last] & ~(-1L << shift);

            if (words[last] != 0)
                notEmpty = true;
        }

        return notEmpty;
    }

    public void set() {
        // Filling with ones
        final int last = usedWords - 1;
        Arrays.fill(words, 0, last, -1L);
        final int shift = size & 0x3f;
        if (shift != 0) {
            words[last] = ~(-1L << shift);
        }
    }

    @Override
    public boolean and(@NotNull final BitSet set) {
        assert size == set.getSize();

        boolean notEmpty = false;
        final long[] from = ((ArrayBitSet) set).toArray();
        for (int i = 0; i < usedWords; i++) {
            final long word = words[i] & from[i];
            words[i] = word;
            if (word != 0) {
                notEmpty = true;
            }
        }

        return notEmpty;
    }

    @Override
    public boolean or(@NotNull final BitSet set) {
        assert size == set.getSize();

        boolean notEmpty = false;
        final long[] from = ((ArrayBitSet) set).toArray();
        for (int i = 0; i < usedWords; i++) {
            final long word = words[i] | from[i];
            words[i] = word;
            if (word != 0) {
                notEmpty = true;
            }
        }

        return notEmpty;
    }

    @Override
    public boolean or(@NotNull final Buffer longArrayBitSetInByteBuffer, final long startPosition,
            final int bitSetSizeInLongs) {
        boolean notEmpty = false;
        long currentPosition = startPosition;

        assert usedWords == bitSetSizeInLongs;

        for (int i = 0; i < usedWords; i++) {
            final long currentWord = longArrayBitSetInByteBuffer.getLong(currentPosition);
            currentPosition += Longs.BYTES;
            final long word = words[i] | currentWord;
            words[i] = word;
            if (word != 0) {
                notEmpty = true;
            }
        }

        return notEmpty;
    }

    @Override
    public boolean isEmpty() {
        for (long w : words)
            if (w != 0) {
                return false;
            }

        return true;
    }

    /**
     * See {@link java.util.BitSet#nextSetBit(int)}
     */
    @Override
    public int nextSetBit(final int fromIndexInclusive) {
        assert 0 <= fromIndexInclusive;

        if (fromIndexInclusive >= size) {
            return -1;
        }

        int u = fromIndexInclusive >> 6;
        long word = words[u];

        // Edge case
        if (word == ~0L)
            return fromIndexInclusive;

        word &= 0xffffffffffffffffL << fromIndexInclusive;

        while (true) {
            if (word != 0) {
                return (u << 6) | Long.numberOfTrailingZeros(word);
            }
            if (++u == usedWords) {
                return -1;
            }
            word = words[u];
        }
    }
}