Files
Just.PreciseMath/2-benchmarks/Just.PreciseMath.PerformanceComparison/MathComparisonBenchmarks.cs
T
just 75925ab184
.NET Test / .NET tests (push) Successful in 1m56s
small arithmetic optimization
2026-09-20 00:52:24 +04:00

136 lines
4.7 KiB
C#

using BenchmarkDotNet.Attributes;
using BenchmarkDotNet.Configs;
using Just.PreciseMath.PerformanceComparison.Reference;
namespace Just.PreciseMath.PerformanceComparison;
/// <summary>
/// Compares Square, Sqrt, and Abs on the same ordinary finite operands across binary64,
/// the <c>Just.PreciseMath</c> double-double, and the blog reference implementation.
/// Every category measures one function, and its binary64 method is the baseline, so
/// the ratio columns read as "times the cost of a double".
/// </summary>
/// <remarks>
/// Operands are independent array elements, so the measurements include loads, stores,
/// and loop overhead on purpose; input construction and fixture validation stay outside
/// the timed methods.
/// </remarks>
[MemoryDiagnoser]
[GroupBenchmarksBy(BenchmarkLogicalGroupRule.ByCategory)]
[CategoriesColumn]
public class MathComparisonBenchmarks
{
private double[] _doublePositive = [];
private DoubleDouble[] _positive = [];
private DoubleDoubleSample[] _samplePositive = [];
private double[] _doubleMixed = [];
private DoubleDouble[] _mixed = [];
private DoubleDoubleSample[] _sampleMixed = [];
private readonly double[] _doubleResults = new double[PerformanceInputs.Count];
private readonly DoubleDouble[] _results = new DoubleDouble[PerformanceInputs.Count];
private readonly DoubleDoubleSample[] _sampleResults = new DoubleDoubleSample[PerformanceInputs.Count];
[GlobalSetup]
public void Setup()
{
PerformanceInputs inputs = PerformanceInputs.Create();
_doublePositive = inputs.DoublePositive;
_positive = inputs.Positive;
_samplePositive = inputs.SamplePositive;
// Square and Sqrt need positive operands; Abs also covers negative ones.
_doubleMixed = inputs.DoubleLeft;
_mixed = inputs.Left;
_sampleMixed = inputs.SampleLeft;
}
[Benchmark(Baseline = true, OperationsPerInvoke = PerformanceInputs.Count), BenchmarkCategory("Square")]
public double[] DoubleSquare()
{
for (int i = 0; i < PerformanceInputs.Count; i++)
{
_doubleResults[i] = _doublePositive[i] * _doublePositive[i];
}
return _doubleResults;
}
[Benchmark(OperationsPerInvoke = PerformanceInputs.Count), BenchmarkCategory("Square")]
public DoubleDouble[] DoubleDoubleSquare()
{
for (int i = 0; i < PerformanceInputs.Count; i++)
{
_results[i] = DoubleDouble.Square(_positive[i]);
}
return _results;
}
[Benchmark(OperationsPerInvoke = PerformanceInputs.Count), BenchmarkCategory("Square")]
public DoubleDoubleSample[] DoubleDoubleSampleSquare()
{
for (int i = 0; i < PerformanceInputs.Count; i++)
{
_sampleResults[i] = _samplePositive[i].Square();
}
return _sampleResults;
}
[Benchmark(Baseline = true, OperationsPerInvoke = PerformanceInputs.Count), BenchmarkCategory("Sqrt")]
public double[] DoubleSqrt()
{
for (int i = 0; i < PerformanceInputs.Count; i++)
{
_doubleResults[i] = Math.Sqrt(_doublePositive[i]);
}
return _doubleResults;
}
[Benchmark(OperationsPerInvoke = PerformanceInputs.Count), BenchmarkCategory("Sqrt")]
public DoubleDouble[] DoubleDoubleSqrt()
{
for (int i = 0; i < PerformanceInputs.Count; i++)
{
_results[i] = DoubleDouble.Sqrt(_positive[i]);
}
return _results;
}
[Benchmark(OperationsPerInvoke = PerformanceInputs.Count), BenchmarkCategory("Sqrt")]
public DoubleDoubleSample[] DoubleDoubleSampleSqrt()
{
for (int i = 0; i < PerformanceInputs.Count; i++)
{
_sampleResults[i] = _samplePositive[i].Sqrt();
}
return _sampleResults;
}
[Benchmark(Baseline = true, OperationsPerInvoke = PerformanceInputs.Count), BenchmarkCategory("Abs")]
public double[] DoubleAbs()
{
for (int i = 0; i < PerformanceInputs.Count; i++)
{
_doubleResults[i] = Math.Abs(_doubleMixed[i]);
}
return _doubleResults;
}
[Benchmark(OperationsPerInvoke = PerformanceInputs.Count), BenchmarkCategory("Abs")]
public DoubleDouble[] DoubleDoubleAbs()
{
for (int i = 0; i < PerformanceInputs.Count; i++)
{
_results[i] = DoubleDouble.Abs(_mixed[i]);
}
return _results;
}
[Benchmark(OperationsPerInvoke = PerformanceInputs.Count), BenchmarkCategory("Abs")]
public DoubleDoubleSample[] DoubleDoubleSampleAbs()
{
for (int i = 0; i < PerformanceInputs.Count; i++)
{
_sampleResults[i] = _sampleMixed[i].Abs();
}
return _sampleResults;
}
}