Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
50 changes: 50 additions & 0 deletions csharp/Platform.Collections.Benchmarks/BitStringBenchmarks.cs
Original file line number Diff line number Diff line change
Expand Up @@ -70,5 +70,55 @@ public void Setup()

[Benchmark]
public BitString ParallelVectorXor() => new BitString(_left).ParallelVectorXor(_right);

[Benchmark]
public BitString ChainedOperationsSeparate()
{
// Traditional approach: multiple passes through memory
var result = new BitString(_left);
result.Not();
result.And(_right);
result.Xor(_left);
return result;
}

[Benchmark]
public BitString ChainedOperationsOptimized()
{
// Optimized approach: single pass through memory using chaining
return new BitString(_left)
.Chain()
.Not()
.And(_right)
.Xor(_left)
.Execute();
}

[Benchmark]
public BitString ComplexChainedOperationsSeparate()
{
// More complex operations with traditional approach
var result = new BitString(_left);
result.Not();
result.And(_right);
result.Not();
result.Or(_left);
result.Xor(_right);
return result;
}

[Benchmark]
public BitString ComplexChainedOperationsOptimized()
{
// More complex operations with chaining
return new BitString(_left)
.Chain()
.Not()
.And(_right)
.Not()
.Or(_left)
.Xor(_right)
.Execute();
}
}
}
121 changes: 121 additions & 0 deletions csharp/Platform.Collections.Tests/BitStringTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -161,5 +161,126 @@ private static void TestToOperationsWithSameMeaning(Action<BitString, BitString,
test(x, y, w, v);
Assert.True(x.Equals(w));
}

[Fact]
public static void BitStringChainBasicTest()
{
const int n = 100;
var bitString1 = new BitString(n);
var bitString2 = new BitString(n);
var bitString3 = new BitString(n);

bitString1.SetRandomBits();
bitString2.SetRandomBits();
bitString3.SetRandomBits();

// Test that chaining produces same result as individual operations
var expected = new BitString(bitString1);
expected.Not().And(bitString2).Or(bitString3);

var actual = new BitString(bitString1);
actual.Chain().Not().And(bitString2).Or(bitString3).Execute();

Assert.True(expected.Equals(actual));
}

[Fact]
public static void BitStringChainEmptyTest()
{
const int n = 100;
var bitString = new BitString(n);
bitString.SetRandomBits();
var original = new BitString(bitString);

// Test that empty chain does not modify the original
bitString.Chain().Execute();
Assert.True(original.Equals(bitString));
}

[Fact]
public static void BitStringChainComplexOperationsTest()
{
const int n = 250;
var a = new BitString(n);
var b = new BitString(n);
var c = new BitString(n);
var d = new BitString(n);

a.SetRandomBits();
b.SetRandomBits();
c.SetRandomBits();
d.SetRandomBits();

// Complex sequence: NOT a, then AND with b, then XOR with c, then OR with d
var expected = new BitString(a);
expected.Not().And(b).Xor(c).Or(d);

var actual = new BitString(a);
actual.Chain().Not().And(b).Xor(c).Or(d).Execute();

Assert.True(expected.Equals(actual));
}

[Fact]
public static void BitStringChainSingleOperationTest()
{
const int n = 100;
var bitString1 = new BitString(n);
var bitString2 = new BitString(n);

bitString1.SetRandomBits();
bitString2.SetRandomBits();

// Test single NOT operation
var expectedNot = new BitString(bitString1);
expectedNot.Not();
var actualNot = new BitString(bitString1);
actualNot.Chain().Not().Execute();
Assert.True(expectedNot.Equals(actualNot));

// Test single AND operation
var expectedAnd = new BitString(bitString1);
expectedAnd.And(bitString2);
var actualAnd = new BitString(bitString1);
actualAnd.Chain().And(bitString2).Execute();
Assert.True(expectedAnd.Equals(actualAnd));

// Test single OR operation
var expectedOr = new BitString(bitString1);
expectedOr.Or(bitString2);
var actualOr = new BitString(bitString1);
actualOr.Chain().Or(bitString2).Execute();
Assert.True(expectedOr.Equals(actualOr));

// Test single XOR operation
var expectedXor = new BitString(bitString1);
expectedXor.Xor(bitString2);
var actualXor = new BitString(bitString1);
actualXor.Chain().Xor(bitString2).Execute();
Assert.True(expectedXor.Equals(actualXor));
}

[Fact]
public static void BitStringChainReusabilityTest()
{
const int n = 100;
var bitString1 = new BitString(n);
var bitString2 = new BitString(n);

bitString1.SetRandomBits();
bitString2.SetRandomBits();

var original = new BitString(bitString1);

// Execute chain multiple times - should be able to reuse
var chain = bitString1.Chain().Not().And(bitString2);
var result1 = chain.Execute();

// Reset to original state
bitString1 = new BitString(original);
var result2 = bitString1.Chain().Not().And(bitString2).Execute();

Assert.True(result1.Equals(result2));
}
}
}
33 changes: 31 additions & 2 deletions csharp/Platform.Collections/BitString.cs
Original file line number Diff line number Diff line change
Expand Up @@ -892,7 +892,7 @@ static private void VectorXorLoop(long[] array, long[] otherArray, int step, int
}
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private void RefreshBordersByWord(long wordIndex)
internal void RefreshBordersByWord(long wordIndex)
{
if (_array[wordIndex] == 0)
{
Expand Down Expand Up @@ -1533,7 +1533,7 @@ private void EnsureBitStringHasTheSameSize(BitString other, string argumentName)
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private void MarkBordersAsAllBitsSet() => SetBorders(0, _array.LongLength - 1);
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private void GetBorders(out long from, out long to)
internal void GetBorders(out long from, out long to)
{
from = _minPositiveWord;
to = _maxPositiveWord;
Expand Down Expand Up @@ -1859,5 +1859,34 @@ public static void GetCommonBorders(BitString left, BitString right, out ulong f
/// </returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public override string ToString() => base.ToString();

/// <summary>
/// <para>
/// Creates a new BitStringChain for chaining multiple operations efficiently.
/// This allows multiple operations to be applied in a single memory pass,
/// reducing memory bandwidth usage and improving performance.
/// </para>
/// <para></para>
/// </summary>
/// <returns>
/// <para>A new BitStringChain instance for method chaining.</para>
/// <para></para>
/// </returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public BitStringChain Chain() => new BitStringChain(this);

/// <summary>
/// <para>
/// Gets the internal array for internal operations. This method is used by BitStringChain.
/// </para>
/// <para></para>
/// </summary>
/// <returns>
/// <para>The internal long array.</para>
/// <para></para>
/// </returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
internal long[] GetInternalArray() => _array;

}
}
Loading
Loading