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

fj.data.hamt.BitSet Maven / Gradle / Ivy

Go to download

Functional Java is an open source library that supports closures for the Java programming language

There is a newer version: 5.0
Show newest version
package fj.data.hamt;

import fj.Equal;
import fj.F2;
import fj.Monoid;
import fj.Show;
import fj.data.List;
import fj.data.Stream;

/**
 * A sequence of bits representing a value.  The most significant bit (the
 * bit with the highest value) is the leftmost bit and has the highest index.
 * For example, the BitSet("1011") represents the decimal number 11 and has
 * indices [3, 0] inclusive where the bit with the lowest value has the lowest
 * index and is the rightmost bit.
 *
 * Created by maperr on 31/05/2016.
 */
public final class BitSet {

    public static final int TRUE_BIT = 1;
    public static final int FALSE_BIT = 0;
    public static final BitSet EMPTY = new BitSet(FALSE_BIT);

    public static final long BASE_LONG = 1L;
    public static final int MAX_BIT_SIZE = Long.SIZE;
    public static final int MAX_BIT_INDEX = Long.SIZE - 1;

    private final long value;

    private BitSet(final long l) {
        value = l;
    }

    public static BitSet empty() {
        return EMPTY;
    }

    public static BitSet longBitSet(final long l) {
        return new BitSet(l);
    }

    public static BitSet listBitSet(final List list) {
        final int n = list.length();
        if (n > MAX_BIT_SIZE) {
            throw new IllegalArgumentException("Does not support lists greater than " + MAX_BIT_SIZE + " bits, actual size is " + n);
        }
        long result = 0;
        for (Boolean b: list) {
            result = (result << 1) | toInt(b);
        }
        return longBitSet(result);
    }

    public static BitSet streamBitSet(final Stream s) {
        return listBitSet(s.toList());
    }

    public static BitSet stringBitSet(final String s) {
        return streamBitSet(Stream.fromString(s).map(BitSet::toBoolean));
    }

    public boolean isSet(final int index) {
        return (value & (BASE_LONG << index)) != 0;
    }

    public boolean isEmpty() {
        return value == 0;
    }

    public BitSet set(final int index) {
        return longBitSet(value | (BASE_LONG << index));
    }

    public BitSet set(final int index, boolean b) {
        return b ? set(index) : clear(index);
    }

    public BitSet clear(final int index) {
        return longBitSet(value & ~(BASE_LONG << index));
    }

    public long longValue() {
        return value;
    }

    public BitSet and(final BitSet bs) {
        return longBitSet(value & bs.longValue());
    }

    public BitSet or(final BitSet bs) {
        return longBitSet(value | bs.longValue());
    }

    public BitSet shiftRight(final int n) {
        return longBitSet(value >> n);
    }

    public BitSet shiftLeft(final int n) {
        return longBitSet(value << n);
    }

    public int bitsUsed() {
        return toStream().length();
    }

    public int bitsOn() {
        return toStream().foldLeft((acc, b) -> acc + (b ? 1 : 0), 0);
    }

    /**
     * Returns a stream of boolean where the head is the most significant bit
     * (the bit with the largest value)
     */
    public Stream toStream() {
        return Stream.fromString(Long.toBinaryString(value)).map(BitSet::toBoolean).dropWhile(b -> !b);
    }

    @Override
    public String toString() {
        return Show.bitSetShow.showS(this);
    }

    @Override
    public boolean equals(Object obj) {
        return Equal.equals0(BitSet.class, this, obj, Equal.bitSetSequal);
    }

    public int bitsToRight(final int index) {
        if (index >= MAX_BIT_SIZE) {
            throw new IllegalArgumentException("Does not support an index " +
                    "greater than or equal to " + MAX_BIT_SIZE + " bits, actual argument is " + index);
        }
        int pos = index - 1;
        long mask = BASE_LONG << (pos);
        int result = 0;
        while (pos >= 0) {
            if ((mask & value) != 0) {
                result++;
            }
            mask = mask >> 1;
            pos--;
        }
        return result;
    }

    public List toList() {
        return toStream().toList();
    }

    public  A foldRight(final F2 f, A acc) {
        return toStream().foldRight(b -> p -> f.f(b, p._1()), acc);
    }

    public  A foldLeft(final F2 f, A acc) {
        return toStream().foldLeft(f, acc);
    }

    public BitSet xor(final BitSet bs) {
        return longBitSet(value ^ bs.longValue());
    }

    public BitSet not() {
        return longBitSet(~value);
    }

    public BitSet takeLower(final int n) {
        return streamBitSet(toStream().reverse().take(n).reverse());
    }

    public BitSet takeUpper(final int n) {
        String zero = Integer.toString(FALSE_BIT);
        String current = asString();
        String pad = Monoid.stringMonoid.sumLeft(List.replicate(MAX_BIT_SIZE - current.length(), zero));
        return stringBitSet(pad + current.substring(0, Math.max(n - pad.length(), 0)));
    }

    /**
     * Returns the bit set from indices in the range from low (inclusive)
     * to high(exclusive) from the least significant bit (on the right),
     * e.g. "101101".range(1, 4) == "0110"
     */
    public BitSet range(final int highIndex, final int lowIndex) {
        int max = Math.max(lowIndex, highIndex);
        int min = Math.min(lowIndex, highIndex);
        return new BitSet(max == min ? 0L : (value << (64 - max)) >>> (64 - max + min));
    }

    public static boolean toBoolean(final char c) {
        return c != '0';
    }

    public static boolean toBoolean(final int i) {
        return i != FALSE_BIT;
    }

    public static int toInt(final boolean b) {
        return b ? TRUE_BIT : FALSE_BIT;
    }

    public String asString() {
        return Long.toBinaryString(value);
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy