Files
Just.PreciseMath/2-benchmarks/Just.PreciseMath.Benchmarks/ArithmeticBoundaryBenchmarks.cs
T
just 08036a31d5
.NET Test / .NET tests (push) Successful in 1m26s
the first optimization round
2026-09-14 13:58:04 +04:00

115 lines
3.2 KiB
C#

using BenchmarkDotNet.Attributes;
namespace Just.PreciseMath.Benchmarks;
/// <summary>Isolates ordinary/fallback exponent transitions, not special-value handling.</summary>
[MemoryDiagnoser]
[CategoriesColumn]
public class ArithmeticBoundaryBenchmarks
{
private DoubleDouble _addLeft;
private DoubleDouble _addRight;
private DoubleDouble _multiplyLeft;
private DoubleDouble _divideLeft;
private DoubleDouble _factor;
[Params(false, true)]
public bool Fallback { get; set; }
[GlobalSetup]
public void Setup()
{
int offset = Fallback ? 1 : 0;
_addLeft = Pair(1020 + offset);
_addRight = Pair(1019);
_multiplyLeft = Pair(900 + offset);
_divideLeft = Pair(450 + offset);
_factor = DoubleDouble.FromComponents(1.125, Math.ScaleB(1.0, -56));
// Pin dispatch assumptions to the current source guards. Both signs/orders
// remain finite; boundary timing is intentionally separate from ordinary data.
if ((Math.ILogB(_addLeft.High) > 1020) != Fallback
|| (Math.ILogB(_multiplyLeft.High) + Math.ILogB(_factor.High) > 900) != Fallback
|| (Math.Abs(Math.ILogB(_divideLeft.High)) > 450) != Fallback)
{
throw new InvalidOperationException("Boundary fixture does not select the requested guard branch.");
}
}
private static DoubleDouble Pair(int exponent)
{
return DoubleDouble.FromComponents(Math.ScaleB(1.0, exponent), Math.ScaleB(1.0, exponent - 56));
}
[Benchmark, BenchmarkCategory("Addition")]
public DoubleDouble DDAdd()
{
return _addLeft + _addRight;
}
[Benchmark, BenchmarkCategory("Addition")]
public DoubleDouble DDScalarAdd()
{
return _addLeft + _addRight.High;
}
[Benchmark, BenchmarkCategory("Addition")]
public DoubleDouble ScalarDDAdd()
{
return _addLeft.High + _addRight;
}
[Benchmark, BenchmarkCategory("Subtraction")]
public DoubleDouble DDSubtract()
{
return _addLeft - _addRight;
}
[Benchmark, BenchmarkCategory("Subtraction")]
public DoubleDouble DDScalarSubtract()
{
return _addLeft - _addRight.High;
}
[Benchmark, BenchmarkCategory("Subtraction")]
public DoubleDouble ScalarDDSubtract()
{
return _addLeft.High - _addRight;
}
[Benchmark, BenchmarkCategory("Multiplication")]
public DoubleDouble DDMultiply()
{
return _multiplyLeft * _factor;
}
[Benchmark, BenchmarkCategory("Multiplication")]
public DoubleDouble DDScalarMultiply()
{
return _multiplyLeft * _factor.High;
}
[Benchmark, BenchmarkCategory("Multiplication")]
public DoubleDouble ScalarDDMultiply()
{
return _multiplyLeft.High * _factor;
}
[Benchmark, BenchmarkCategory("Division")]
public DoubleDouble DDDivide()
{
return _divideLeft / _factor;
}
[Benchmark, BenchmarkCategory("Division")]
public DoubleDouble DDScalarDivide()
{
return _divideLeft / _factor.High;
}
[Benchmark, BenchmarkCategory("Division")]
public DoubleDouble ScalarDDDivide()
{
return _factor.High / _divideLeft;
}
}