Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 52a186b7 authored by Michael Wright's avatar Michael Wright Committed by Android (Google) Code Review
Browse files

Merge "Add BitSet64"

parents 8e1943b4 bab6ea0b
Loading
Loading
Loading
Loading
+98 −5
Original line number Diff line number Diff line
@@ -40,7 +40,7 @@ struct BitSet32 {
    inline void clear() { value = 0; }

    // Returns the number of marked bits in the set.
    inline uint32_t count() const { return __builtin_popcount(value); }
    inline uint32_t count() const { return __builtin_popcountl(value); }

    // Returns true if the bit set does not contain any marked bits.
    inline bool isEmpty() const { return ! value; }
@@ -59,15 +59,15 @@ struct BitSet32 {

    // Finds the first marked bit in the set.
    // Result is undefined if all bits are unmarked.
    inline uint32_t firstMarkedBit() const { return __builtin_clz(value); }
    inline uint32_t firstMarkedBit() const { return __builtin_clzl(value); }

    // Finds the first unmarked bit in the set.
    // Result is undefined if all bits are marked.
    inline uint32_t firstUnmarkedBit() const { return __builtin_clz(~ value); }
    inline uint32_t firstUnmarkedBit() const { return __builtin_clzl(~ value); }

    // Finds the last marked bit in the set.
    // Result is undefined if all bits are unmarked.
    inline uint32_t lastMarkedBit() const { return 31 - __builtin_ctz(value); }
    inline uint32_t lastMarkedBit() const { return 31 - __builtin_ctzl(value); }

    // Finds the first marked bit in the set and clears it.  Returns the bit index.
    // Result is undefined if all bits are unmarked.
@@ -96,7 +96,7 @@ struct BitSet32 {
    // Gets the index of the specified bit in the set, which is the number of
    // marked bits that appear before the specified bit.
    inline uint32_t getIndexOfBit(uint32_t n) const {
        return __builtin_popcount(value & ~(0xffffffffUL >> n));
        return __builtin_popcountl(value & ~(0xffffffffUL >> n));
    }

    inline bool operator== (const BitSet32& other) const { return value == other.value; }
@@ -119,6 +119,99 @@ struct BitSet32 {

ANDROID_BASIC_TYPES_TRAITS(BitSet32)

// A simple set of 64 bits that can be individually marked or cleared.
struct BitSet64 {
    uint64_t value;

    inline BitSet64() : value(0ULL) { }
    explicit inline BitSet64(uint64_t value) : value(value) { }

    // Gets the value associated with a particular bit index.
    static inline uint64_t valueForBit(uint32_t n) { return 0x8000000000000000ULL >> n; }

    // Clears the bit set.
    inline void clear() { value = 0ULL; }

    // Returns the number of marked bits in the set.
    inline uint32_t count() const { return __builtin_popcountll(value); }

    // Returns true if the bit set does not contain any marked bits.
    inline bool isEmpty() const { return ! value; }

    // Returns true if the bit set does not contain any unmarked bits.
    inline bool isFull() const { return value == 0xffffffffffffffffULL; }

    // Returns true if the specified bit is marked.
    inline bool hasBit(uint32_t n) const { return value & valueForBit(n); }

    // Marks the specified bit.
    inline void markBit(uint32_t n) { value |= valueForBit(n); }

    // Clears the specified bit.
    inline void clearBit(uint32_t n) { value &= ~ valueForBit(n); }

    // Finds the first marked bit in the set.
    // Result is undefined if all bits are unmarked.
    inline uint32_t firstMarkedBit() const { return __builtin_clzll(value); }

    // Finds the first unmarked bit in the set.
    // Result is undefined if all bits are marked.
    inline uint32_t firstUnmarkedBit() const { return __builtin_clzll(~ value); }

    // Finds the last marked bit in the set.
    // Result is undefined if all bits are unmarked.
    inline uint32_t lastMarkedBit() const { return 63 - __builtin_ctzll(value); }

    // Finds the first marked bit in the set and clears it.  Returns the bit index.
    // Result is undefined if all bits are unmarked.
    inline uint32_t clearFirstMarkedBit() {
        uint64_t n = firstMarkedBit();
        clearBit(n);
        return n;
    }

    // Finds the first unmarked bit in the set and marks it.  Returns the bit index.
    // Result is undefined if all bits are marked.
    inline uint32_t markFirstUnmarkedBit() {
        uint64_t n = firstUnmarkedBit();
        markBit(n);
        return n;
    }

    // Finds the last marked bit in the set and clears it.  Returns the bit index.
    // Result is undefined if all bits are unmarked.
    inline uint32_t clearLastMarkedBit() {
        uint64_t n = lastMarkedBit();
        clearBit(n);
        return n;
    }

    // Gets the index of the specified bit in the set, which is the number of
    // marked bits that appear before the specified bit.
    inline uint32_t getIndexOfBit(uint32_t n) const {
        return __builtin_popcountll(value & ~(0xffffffffffffffffULL >> n));
    }

    inline bool operator== (const BitSet64& other) const { return value == other.value; }
    inline bool operator!= (const BitSet64& other) const { return value != other.value; }
    inline BitSet64 operator& (const BitSet64& other) const {
        return BitSet64(value & other.value);
    }
    inline BitSet64& operator&= (const BitSet64& other) {
        value &= other.value;
        return *this;
    }
    inline BitSet64 operator| (const BitSet64& other) const {
        return BitSet64(value | other.value);
    }
    inline BitSet64& operator|= (const BitSet64& other) {
        value |= other.value;
        return *this;
    }
};

ANDROID_BASIC_TYPES_TRAITS(BitSet32)

} // namespace android

#endif // UTILS_BITSET_H
+66 −4
Original line number Diff line number Diff line
@@ -23,7 +23,7 @@

namespace android {

class BitSetTest : public testing::Test {
class BitSet32Test : public testing::Test {
protected:
    BitSet32 b1;
    BitSet32 b2;
@@ -34,7 +34,7 @@ protected:
};


TEST_F(BitSetTest, BitWiseOr) {
TEST_F(BitSet32Test, BitWiseOr) {
    b1.markBit(2);
    b2.markBit(4);

@@ -49,7 +49,7 @@ TEST_F(BitSetTest, BitWiseOr) {
    EXPECT_TRUE(b1.hasBit(2) && b1.hasBit(4));
    EXPECT_TRUE(b2.hasBit(4) && b2.count() == 1u);
}
TEST_F(BitSetTest, BitWiseAnd_Disjoint) {
TEST_F(BitSet32Test, BitWiseAnd_Disjoint) {
    b1.markBit(2);
    b1.markBit(4);
    b1.markBit(6);
@@ -65,7 +65,7 @@ TEST_F(BitSetTest, BitWiseAnd_Disjoint) {
    EXPECT_TRUE(b1.hasBit(2) && b1.hasBit(4) && b1.hasBit(6));
}

TEST_F(BitSetTest, BitWiseAnd_NonDisjoint) {
TEST_F(BitSet32Test, BitWiseAnd_NonDisjoint) {
    b1.markBit(2);
    b1.markBit(4);
    b1.markBit(6);
@@ -84,4 +84,66 @@ TEST_F(BitSetTest, BitWiseAnd_NonDisjoint) {
    EXPECT_EQ(b2.count(), 3u);
    EXPECT_TRUE(b2.hasBit(3) && b2.hasBit(6) && b2.hasBit(9));
}

class BitSet64Test : public testing::Test {
protected:
    BitSet64 b1;
    BitSet64 b2;
    virtual void TearDown() {
        b1.clear();
        b2.clear();
    }
};


TEST_F(BitSet64Test, BitWiseOr) {
    b1.markBit(20);
    b2.markBit(40);

    BitSet64 tmp = b1 | b2;
    EXPECT_EQ(tmp.count(), 2u);
    EXPECT_TRUE(tmp.hasBit(20) && tmp.hasBit(40));
    // Check that the operator is symmetric
    EXPECT_TRUE((b2 | b1) == (b1 | b2));

    b1 |= b2;
    EXPECT_EQ(b1.count(), 2u);
    EXPECT_TRUE(b1.hasBit(20) && b1.hasBit(40));
    EXPECT_TRUE(b2.hasBit(40) && b2.count() == 1u);
}
TEST_F(BitSet64Test, BitWiseAnd_Disjoint) {
    b1.markBit(20);
    b1.markBit(40);
    b1.markBit(60);

    BitSet64 tmp = b1 & b2;
    EXPECT_TRUE(tmp.isEmpty());
    // Check that the operator is symmetric
    EXPECT_TRUE((b2 & b1) == (b1 & b2));

    b2 &= b1;
    EXPECT_TRUE(b2.isEmpty());
    EXPECT_EQ(b1.count(), 3u);
    EXPECT_TRUE(b1.hasBit(20) && b1.hasBit(40) && b1.hasBit(60));
}

TEST_F(BitSet64Test, BitWiseAnd_NonDisjoint) {
    b1.markBit(20);
    b1.markBit(40);
    b1.markBit(60);
    b2.markBit(30);
    b2.markBit(60);
    b2.markBit(63);

    BitSet64 tmp = b1 & b2;
    EXPECT_EQ(tmp.count(), 1u);
    EXPECT_TRUE(tmp.hasBit(60));
    // Check that the operator is symmetric
    EXPECT_TRUE((b2 & b1) == (b1 & b2));

    b1 &= b2;
    EXPECT_EQ(b1.count(), 1u);
    EXPECT_EQ(b2.count(), 3u);
    EXPECT_TRUE(b2.hasBit(30) && b2.hasBit(60) && b2.hasBit(63));
}
} // namespace android