Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Create BitArray.HasAllSet() and .HasAnySet(). #81527

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()
stephentoub marked this conversation as resolved.
Show resolved Hide resolved
{
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;
}
stephentoub marked this conversation as resolved.
Show resolved Hide resolved

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;
}

stephentoub marked this conversation as resolved.
Show resolved Hide resolved
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 };
}
}
}
}
}