Skip to content

Commit

Permalink
Create BitArray.HasAllSet() and .HasAnySet(). (#81527)
Browse files Browse the repository at this point in the history
* Create BitArray.HasAllSet().

* Fix comment: use span rather than vector directly.

* Create BitArray.HasAnySet().

* Fix comment: alpha order ref methods.

* Create tests.

* Fix comment: rename variable; check by '>= 0'.

* Add xml doc.

* Fix comment: add cases of other bits besides of the last bit.
  • Loading branch information
lateapexearlyspeed committed Feb 13, 2023
1 parent fd8298e commit cc14f35
Show file tree
Hide file tree
Showing 3 changed files with 97 additions and 0 deletions.
2 changes: 2 additions & 0 deletions src/libraries/System.Collections/ref/System.Collections.cs
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@ public sealed partial class BitArray : System.Collections.ICollection, System.Co
public void CopyTo(System.Array array, int index) { }
public bool Get(int index) { throw null; }
public System.Collections.IEnumerator GetEnumerator() { throw null; }
public bool HasAllSet() { throw null; }
public bool HasAnySet() { throw null; }
public System.Collections.BitArray LeftShift(int count) { throw null; }
public System.Collections.BitArray Not() { throw null; }
public System.Collections.BitArray Or(System.Collections.BitArray value) { throw null; }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -910,6 +910,66 @@ public unsafe void CopyTo(Array array, int index)
}
}

/// <summary>
/// Determines whether all bits in the <see cref="BitArray"/> are set to <c>true</c>.
/// </summary>
/// <returns><c>true</c> if every bit in the <see cref="BitArray"/> is set to <c>true</c>, or if <see cref="BitArray"/> is empty; otherwise, <c>false</c>.</returns>
public bool HasAllSet()
{
Div32Rem(m_length, out int extraBits);
int intCount = GetInt32ArrayLengthFromBitLength(m_length);
if (extraBits != 0)
{
intCount--;
}

const int AllSetBits = -1; // 0xFF_FF_FF_FF
if (m_array.AsSpan(0, intCount).IndexOfAnyExcept(AllSetBits) >= 0)
{
return false;
}

if (extraBits == 0)
{
return true;
}

Debug.Assert(GetInt32ArrayLengthFromBitLength(m_length) > 0);
Debug.Assert(intCount == GetInt32ArrayLengthFromBitLength(m_length) - 1);

int mask = (1 << extraBits) - 1;
return (m_array[intCount] & mask) == mask;
}

/// <summary>
/// Determines whether any bit in the <see cref="BitArray"/> is set to <c>true</c>.
/// </summary>
/// <returns><c>true</c> if <see cref="BitArray"/> is not empty and at least one of its bit is set to <c>true</c>; otherwise, <c>false</c>.</returns>
public bool HasAnySet()
{
Div32Rem(m_length, out int extraBits);
int intCount = GetInt32ArrayLengthFromBitLength(m_length);
if (extraBits != 0)
{
intCount--;
}

if (m_array.AsSpan(0, intCount).IndexOfAnyExcept(0) >= 0)
{
return true;
}

if (extraBits == 0)
{
return false;
}

Debug.Assert(GetInt32ArrayLengthFromBitLength(m_length) > 0);
Debug.Assert(intCount == GetInt32ArrayLengthFromBitLength(m_length) - 1);

return (m_array[intCount] & (1 << extraBits) - 1) != 0;
}

public int Count => m_length;

public object SyncRoot => this;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -552,5 +552,40 @@ public static void CopyTo_Byte_Hidden(string label, BitArray bits)
Assert.Equal((byte)((1 << remainder) - 1), data[fullBytes]);
}
}

[Theory]
[MemberData(nameof(HasAllSet_TestData))]
public static void HasAllSet(bool[] bits, bool expectedResult)
{
var bitArray = new BitArray(bits);
Assert.Equal(expectedResult, bitArray.HasAllSet());
}

[Theory]
[MemberData(nameof(HasAnySet_TestData))]
public static void HasAnySet(bool[] bits, bool expectedResult)
{
var bitArray = new BitArray(bits);
Assert.Equal(expectedResult, bitArray.HasAnySet());
}

public static IEnumerable<object[]> HasAllSet_TestData() => HasAnySet_TestData().Select(parameters => new object[] { ((bool[])parameters[0]).Select(bit => !bit).ToArray(), !(bool)parameters[1] });

public static IEnumerable<object[]> HasAnySet_TestData()
{
yield return new object[] { Array.Empty<bool>(), false };

foreach (int size in new[] { 1, BitsPerInt32 - 1, BitsPerInt32, BitsPerInt32 + 1, BitsPerInt32 * 2 - 1 })
{
yield return new object[] { new bool[size], false };

for (int i = 0; i < size; i++)
{
bool[] bits = new bool[size];
bits[i] = true;
yield return new object[] { bits, true };
}
}
}
}
}

0 comments on commit cc14f35

Please sign in to comment.