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

com.tencent.angel.sona.tree.util.RangeBitSet Maven / Gradle / Ivy

/*
 * Tencent is pleased to support the open source community by making Angel available.
 *
 * Copyright (C) 2017-2018 THL A29 Limited, a Tencent company. All rights reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in
 * compliance with the License. You may obtain a copy of the License at
 *
 * https://opensource.org/licenses/Apache-2.0
 *
 * Unless required by applicable law or agreed to in writing, software distributed under the License
 * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
 * or implied. See the License for the specific language governing permissions and limitations under
 * the License.
 *
 */
package com.tencent.angel.sona.tree.util;

import java.io.Serializable;
import java.util.List;

public class RangeBitSet implements Serializable {
    private byte[] bits;
    private int from;
    private int to;
    private int offset;

    public RangeBitSet(int from, int to) {
        this.from = from;
        this.to = to;
        this.offset = from & 0b111;
        this.bits = new byte[needNumBytes(from, to)];
    }

    public RangeBitSet(int from, int to, byte[] bits) {
        this.from = from;
        this.to = to;
        this.offset = from & 0b111;
        if (bits.length != needNumBytes(from, to)) {
            throw new RuntimeException(String.format("Invalid RangeBitSet size: " +
                    "%d, should be %d", bits.length, needNumBytes(from, to)));
        } else {
            this.bits = bits;
        }
    }

    public RangeBitSet() {
        this.from = -1;
        this.to = -1;
        this.offset = -1;
        this.bits = null;
    }

    private int needNumBytes(int from, int to) {
        int first = from >> 3;
        int last = to >> 3;
        return last - first + 1;
    }

    public void set(int index) {
        index = index - from + offset;
        int x = index >> 3;
        int y = index & 0b111;
        bits[x] = (byte) (bits[x] | (1 << y));
    }

    public void clear(int index) {
        index = index - from + offset;
        int x = index >> 3;
        int y = index & 0b111;
        bits[x] = (byte) (bits[x] & (~(1 << y)));
    }

    // TODO: use arraycopy to make it faster
    public void or(RangeBitSet other) {
        int from = other.getRangeFrom(), to = other.getRangeTo();
        // assert from >= this.from && to <= this.to;
        for (int i = from; i <= to; i++) {
            if (other.get(i)) {
                set(i);
            }
        }
    }

    public boolean get(int index) {
        index = index - from + offset;
        int x = index >> 3;
        int y = index & 0b111;
        return ((bits[x] >> y) & 0x1) == 1;
    }

    public RangeBitSet subset(int newFrom, int newTo) {
        if ((newFrom <= from && newTo >= to) || newFrom > newTo) {
            throw new RuntimeException(String.format("Invalid subset range: [%d-%d], " +
                    "should be in [%d-%d]", newFrom, newTo, from, to));
        }
        int firstByteIdx = (newFrom - from) >> 3;
        int lastByteIdx = (newTo - from) >> 3;
        int numBytes = lastByteIdx - firstByteIdx + 1;
        byte[] subset = new byte[numBytes];
        System.arraycopy(bits, firstByteIdx, subset, 0, numBytes);
        return new RangeBitSet(newFrom, newTo, subset);
    }

    public RangeBitSet overlap(int newFrom, int newTo) {
        newFrom = Math.max(newFrom, from);
        newTo = Math.min(newTo, to);
        if (newFrom > newTo) {
            return null;
        }
        if (newFrom != from || newTo != to) {
            return subset(newFrom, newTo);
        } else {
            return this;
        }
    }

    public byte[] toByteArray() {
        return bits;
    }

    public int getRangeFrom() {
        return from;
    }

    public int getRangeTo() {
        return to;
    }

    public int getNumValid() {
        int res = 0;
        for (int i = from; i <= to; i++) {
            if (get(i)) {
                res++;
            }
        }
        return res;
    }

    public static RangeBitSet or(RangeBitSet bs1, RangeBitSet bs2) {
        int from = Math.min(bs1.getRangeFrom(), bs2.getRangeFrom());
        int to = Math.max(bs1.getRangeTo(), bs2.getRangeTo());
        RangeBitSet res = new RangeBitSet(from, to);
        res.or(bs1);
        res.or(bs2);
        return res;
    }

    public static RangeBitSet or(List bitsets) {
        int from = Integer.MAX_VALUE, to = Integer.MIN_VALUE;
        int size = bitsets.size();
        for (int i = 0; i < size; i++) {
            from = Math.min(bitsets.get(i).getRangeFrom(), from);
            to = Math.max(bitsets.get(i).getRangeTo(), to);
        }
        RangeBitSet res = new RangeBitSet(from, to);
        for (int i = 0; i < size; i++) {
            res.or(bitsets.get(i));
        }
        return res;
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy