Skip to content

Commit cc14f35

Browse files
Create BitArray.HasAllSet() and .HasAnySet(). (#81527)
* 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.
1 parent fd8298e commit cc14f35

File tree

3 files changed

+97
-0
lines changed

3 files changed

+97
-0
lines changed

src/libraries/System.Collections/ref/System.Collections.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,8 @@ public BitArray(int[] values) { }
2626
public void CopyTo(System.Array array, int index) { }
2727
public bool Get(int index) { throw null; }
2828
public System.Collections.IEnumerator GetEnumerator() { throw null; }
29+
public bool HasAllSet() { throw null; }
30+
public bool HasAnySet() { throw null; }
2931
public System.Collections.BitArray LeftShift(int count) { throw null; }
3032
public System.Collections.BitArray Not() { throw null; }
3133
public System.Collections.BitArray Or(System.Collections.BitArray value) { throw null; }

src/libraries/System.Collections/src/System/Collections/BitArray.cs

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -910,6 +910,66 @@ public unsafe void CopyTo(Array array, int index)
910910
}
911911
}
912912

913+
/// <summary>
914+
/// Determines whether all bits in the <see cref="BitArray"/> are set to <c>true</c>.
915+
/// </summary>
916+
/// <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>
917+
public bool HasAllSet()
918+
{
919+
Div32Rem(m_length, out int extraBits);
920+
int intCount = GetInt32ArrayLengthFromBitLength(m_length);
921+
if (extraBits != 0)
922+
{
923+
intCount--;
924+
}
925+
926+
const int AllSetBits = -1; // 0xFF_FF_FF_FF
927+
if (m_array.AsSpan(0, intCount).IndexOfAnyExcept(AllSetBits) >= 0)
928+
{
929+
return false;
930+
}
931+
932+
if (extraBits == 0)
933+
{
934+
return true;
935+
}
936+
937+
Debug.Assert(GetInt32ArrayLengthFromBitLength(m_length) > 0);
938+
Debug.Assert(intCount == GetInt32ArrayLengthFromBitLength(m_length) - 1);
939+
940+
int mask = (1 << extraBits) - 1;
941+
return (m_array[intCount] & mask) == mask;
942+
}
943+
944+
/// <summary>
945+
/// Determines whether any bit in the <see cref="BitArray"/> is set to <c>true</c>.
946+
/// </summary>
947+
/// <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>
948+
public bool HasAnySet()
949+
{
950+
Div32Rem(m_length, out int extraBits);
951+
int intCount = GetInt32ArrayLengthFromBitLength(m_length);
952+
if (extraBits != 0)
953+
{
954+
intCount--;
955+
}
956+
957+
if (m_array.AsSpan(0, intCount).IndexOfAnyExcept(0) >= 0)
958+
{
959+
return true;
960+
}
961+
962+
if (extraBits == 0)
963+
{
964+
return false;
965+
}
966+
967+
Debug.Assert(GetInt32ArrayLengthFromBitLength(m_length) > 0);
968+
Debug.Assert(intCount == GetInt32ArrayLengthFromBitLength(m_length) - 1);
969+
970+
return (m_array[intCount] & (1 << extraBits) - 1) != 0;
971+
}
972+
913973
public int Count => m_length;
914974

915975
public object SyncRoot => this;

src/libraries/System.Collections/tests/BitArray/BitArray_GetSetTests.cs

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -552,5 +552,40 @@ public static void CopyTo_Byte_Hidden(string label, BitArray bits)
552552
Assert.Equal((byte)((1 << remainder) - 1), data[fullBytes]);
553553
}
554554
}
555+
556+
[Theory]
557+
[MemberData(nameof(HasAllSet_TestData))]
558+
public static void HasAllSet(bool[] bits, bool expectedResult)
559+
{
560+
var bitArray = new BitArray(bits);
561+
Assert.Equal(expectedResult, bitArray.HasAllSet());
562+
}
563+
564+
[Theory]
565+
[MemberData(nameof(HasAnySet_TestData))]
566+
public static void HasAnySet(bool[] bits, bool expectedResult)
567+
{
568+
var bitArray = new BitArray(bits);
569+
Assert.Equal(expectedResult, bitArray.HasAnySet());
570+
}
571+
572+
public static IEnumerable<object[]> HasAllSet_TestData() => HasAnySet_TestData().Select(parameters => new object[] { ((bool[])parameters[0]).Select(bit => !bit).ToArray(), !(bool)parameters[1] });
573+
574+
public static IEnumerable<object[]> HasAnySet_TestData()
575+
{
576+
yield return new object[] { Array.Empty<bool>(), false };
577+
578+
foreach (int size in new[] { 1, BitsPerInt32 - 1, BitsPerInt32, BitsPerInt32 + 1, BitsPerInt32 * 2 - 1 })
579+
{
580+
yield return new object[] { new bool[size], false };
581+
582+
for (int i = 0; i < size; i++)
583+
{
584+
bool[] bits = new bool[size];
585+
bits[i] = true;
586+
yield return new object[] { bits, true };
587+
}
588+
}
589+
}
555590
}
556591
}

0 commit comments

Comments
 (0)