diff --git a/csharp/Platform.Collections.Benchmarks/BitStringBenchmarks.cs b/csharp/Platform.Collections.Benchmarks/BitStringBenchmarks.cs
index 67649f9b..105cd2ce 100644
--- a/csharp/Platform.Collections.Benchmarks/BitStringBenchmarks.cs
+++ b/csharp/Platform.Collections.Benchmarks/BitStringBenchmarks.cs
@@ -23,6 +23,17 @@ public void Setup()
}
}
+ [Benchmark]
+ public BitString CreateWithRandomBitsOld()
+ {
+ var bitString = new BitString(N);
+ bitString.SetRandomBits();
+ return bitString;
+ }
+
+ [Benchmark]
+ public BitString CreateWithRandomBitsNew() => BitStringExtensions.CreateWithRandomBits(N);
+
[Benchmark]
public BitString Not() => new BitString(_left).Not();
diff --git a/csharp/Platform.Collections.Tests/BitStringTests.cs b/csharp/Platform.Collections.Tests/BitStringTests.cs
index 988deca8..5655d532 100644
--- a/csharp/Platform.Collections.Tests/BitStringTests.cs
+++ b/csharp/Platform.Collections.Tests/BitStringTests.cs
@@ -23,6 +23,40 @@ public static void BitGetSetTest()
}
}
+ [Fact]
+ public static void BitStringArrayConstructorTest()
+ {
+ const int n = 128;
+ var array = new long[] { unchecked((long)0x1234567890ABCDEF), unchecked((long)0xFEDCBA0987654321) };
+ var bitString = new BitString(array, n);
+
+ var normalBitString = new BitString(n);
+ for (var i = 0L; i < BitString.GetWordsCountFromIndex(n); i++)
+ {
+ for (var j = 0; j < 64 && (i * 64 + j) < n; j++)
+ {
+ var bitIndex = i * 64 + j;
+ var expectedValue = (array[i] & (1L << j)) != 0;
+ normalBitString.Set(bitIndex, expectedValue);
+ Assert.Equal(expectedValue, bitString.Get(bitIndex));
+ }
+ }
+
+ Assert.Equal(normalBitString.CountSetBits(), bitString.CountSetBits());
+ }
+
+ [Fact]
+ public static void CreateWithRandomBitsTest()
+ {
+ const int n = 1000;
+ var bitString1 = BitStringExtensions.CreateWithRandomBits(n);
+ var bitString2 = BitStringExtensions.CreateWithRandomBits(n);
+
+ Assert.Equal(n, bitString1.Length);
+ Assert.Equal(n, bitString2.Length);
+ Assert.False(bitString1.Equals(bitString2));
+ }
+
[Fact]
public static void BitVectorNotTest()
{
diff --git a/csharp/Platform.Collections.Tests/PerformanceComparisonTest.cs b/csharp/Platform.Collections.Tests/PerformanceComparisonTest.cs
new file mode 100644
index 00000000..89b9ad88
--- /dev/null
+++ b/csharp/Platform.Collections.Tests/PerformanceComparisonTest.cs
@@ -0,0 +1,60 @@
+using System;
+using System.Diagnostics;
+using Xunit;
+using Xunit.Abstractions;
+
+namespace Platform.Collections.Tests
+{
+ public class PerformanceComparisonTest
+ {
+ private readonly ITestOutputHelper _output;
+
+ public PerformanceComparisonTest(ITestOutputHelper output)
+ {
+ _output = output;
+ }
+
+ [Fact]
+ public void BitStringInitializationPerformanceComparison()
+ {
+ const int iterations = 100;
+ const long bitStringLength = 10000;
+
+ _output.WriteLine($"Testing BitString initialization performance with {iterations} iterations for length {bitStringLength}");
+
+ // Test old method (SetRandomBits)
+ var sw = Stopwatch.StartNew();
+ for (int i = 0; i < iterations; i++)
+ {
+ var bitString = new BitString(bitStringLength);
+ bitString.SetRandomBits();
+ }
+ sw.Stop();
+ var oldMethodTime = sw.ElapsedMilliseconds;
+ _output.WriteLine($"Old method (SetRandomBits): {oldMethodTime} ms");
+
+ // Test new method (array constructor)
+ sw.Restart();
+ for (int i = 0; i < iterations; i++)
+ {
+ var bitString = BitStringExtensions.CreateWithRandomBits(bitStringLength);
+ }
+ sw.Stop();
+ var newMethodTime = sw.ElapsedMilliseconds;
+ _output.WriteLine($"New method (CreateWithRandomBits): {newMethodTime} ms");
+
+ if (oldMethodTime > 0 && newMethodTime > 0)
+ {
+ var improvement = (double)oldMethodTime / newMethodTime;
+ _output.WriteLine($"Performance improvement: {improvement:F2}x faster");
+
+ // Assert that the new method is faster or at least not significantly slower
+ Assert.True(newMethodTime <= oldMethodTime, $"New method should be faster or equal. Old: {oldMethodTime}ms, New: {newMethodTime}ms");
+ }
+ else
+ {
+ _output.WriteLine("Performance test completed, but times were too small to measure accurately");
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/csharp/Platform.Collections/BitString.cs b/csharp/Platform.Collections/BitString.cs
index 4b0b36ac..33d4e116 100644
--- a/csharp/Platform.Collections/BitString.cs
+++ b/csharp/Platform.Collections/BitString.cs
@@ -193,6 +193,36 @@ public BitString(long length, bool defaultValue)
}
}
+ ///
+ ///
+ /// Initializes a new instance.
+ ///
+ ///
+ ///
+ ///
+ /// An array of integers to initialize the bit string with.
+ ///
+ ///
+ ///
+ /// A length.
+ ///
+ ///
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public BitString(long[] array, long length)
+ {
+ Ensure.Always.ArgumentNotNull(array, nameof(array));
+ Ensure.Always.ArgumentInRange(length, GetValidLengthRange(), nameof(length));
+ var wordsCount = GetWordsCountFromIndex(length);
+ if (array.LongLength < wordsCount)
+ {
+ throw new ArgumentException($"Array must have at least {wordsCount} elements for length {length}.", nameof(array));
+ }
+ _length = length;
+ _array = new long[wordsCount];
+ Array.Copy(array, _array, wordsCount);
+ SetBordersFromArray();
+ }
+
#endregion
///
@@ -1533,6 +1563,33 @@ private void EnsureBitStringHasTheSameSize(BitString other, string argumentName)
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private void MarkBordersAsAllBitsSet() => SetBorders(0, _array.LongLength - 1);
[MethodImpl(MethodImplOptions.AggressiveInlining)]
+ private void SetBordersFromArray()
+ {
+ long minPositiveWord = _array.LongLength - 1;
+ long maxPositiveWord = 0;
+ var hasPositiveBits = false;
+ for (var i = 0L; i < _array.LongLength; i++)
+ {
+ if (_array[i] != 0)
+ {
+ if (!hasPositiveBits)
+ {
+ minPositiveWord = i;
+ hasPositiveBits = true;
+ }
+ maxPositiveWord = i;
+ }
+ }
+ if (!hasPositiveBits)
+ {
+ MarkBordersAsAllBitsReset();
+ }
+ else
+ {
+ SetBorders(minPositiveWord, maxPositiveWord);
+ }
+ }
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
private void GetBorders(out long from, out long to)
{
from = _minPositiveWord;
diff --git a/csharp/Platform.Collections/BitStringExtensions.cs b/csharp/Platform.Collections/BitStringExtensions.cs
index 85c92e62..be7354a8 100644
--- a/csharp/Platform.Collections/BitStringExtensions.cs
+++ b/csharp/Platform.Collections/BitStringExtensions.cs
@@ -32,5 +32,31 @@ public static void SetRandomBits(this BitString @string)
@string.Set(i, value);
}
}
+
+ ///
+ ///
+ /// Creates a new BitString with random bits using the efficient constructor.
+ ///
+ ///
+ ///
+ ///
+ /// The length of the bit string.
+ ///
+ ///
+ ///
+ /// A new BitString with random bits.
+ ///
+ ///
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static BitString CreateWithRandomBits(long length)
+ {
+ var wordsCount = BitString.GetWordsCountFromIndex(length);
+ var randomArray = new long[wordsCount];
+ for (var i = 0L; i < wordsCount; i++)
+ {
+ randomArray[i] = RandomHelpers.Default.NextInt64();
+ }
+ return new BitString(randomArray, length);
+ }
}
}