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

165 lines
5.6 KiB
C#

using BenchmarkDotNet.Attributes;
using BenchmarkDotNet.Configs;
using Just.PreciseMath.PerformanceComparison.Reference;
namespace Just.PreciseMath.PerformanceComparison;
/// <summary>
/// Compares the four arithmetic operators on the same ordinary finite operands across
/// binary64, the <c>Just.PreciseMath</c> double-double, and the blog reference
/// implementation. Every category measures one operator, 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, conversion, and fixture validation
/// stay outside the timed methods.
/// </remarks>
[MemoryDiagnoser]
[GroupBenchmarksBy(BenchmarkLogicalGroupRule.ByCategory)]
[CategoriesColumn]
public class ArithmeticComparisonBenchmarks
{
private double[] _doubleLeft = [];
private double[] _doubleRight = [];
private DoubleDouble[] _left = [];
private DoubleDouble[] _right = [];
private DoubleDoubleSample[] _sampleLeft = [];
private DoubleDoubleSample[] _sampleRight = [];
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();
_doubleLeft = inputs.DoubleLeft;
_doubleRight = inputs.DoubleRight;
_left = inputs.Left;
_right = inputs.Right;
_sampleLeft = inputs.SampleLeft;
_sampleRight = inputs.SampleRight;
}
[Benchmark(Baseline = true, OperationsPerInvoke = PerformanceInputs.Count), BenchmarkCategory("Addition")]
public double[] DoubleAdd()
{
for (int i = 0; i < PerformanceInputs.Count; i++)
{
_doubleResults[i] = _doubleLeft[i] + _doubleRight[i];
}
return _doubleResults;
}
[Benchmark(OperationsPerInvoke = PerformanceInputs.Count), BenchmarkCategory("Addition")]
public DoubleDouble[] DoubleDoubleAdd()
{
for (int i = 0; i < PerformanceInputs.Count; i++)
{
_results[i] = _left[i] + _right[i];
}
return _results;
}
[Benchmark(OperationsPerInvoke = PerformanceInputs.Count), BenchmarkCategory("Addition")]
public DoubleDoubleSample[] DoubleDoubleSampleAdd()
{
for (int i = 0; i < PerformanceInputs.Count; i++)
{
_sampleResults[i] = _sampleLeft[i] + _sampleRight[i];
}
return _sampleResults;
}
[Benchmark(Baseline = true, OperationsPerInvoke = PerformanceInputs.Count), BenchmarkCategory("Subtraction")]
public double[] DoubleSubtract()
{
for (int i = 0; i < PerformanceInputs.Count; i++)
{
_doubleResults[i] = _doubleLeft[i] - _doubleRight[i];
}
return _doubleResults;
}
[Benchmark(OperationsPerInvoke = PerformanceInputs.Count), BenchmarkCategory("Subtraction")]
public DoubleDouble[] DoubleDoubleSubtract()
{
for (int i = 0; i < PerformanceInputs.Count; i++)
{
_results[i] = _left[i] - _right[i];
}
return _results;
}
[Benchmark(OperationsPerInvoke = PerformanceInputs.Count), BenchmarkCategory("Subtraction")]
public DoubleDoubleSample[] DoubleDoubleSampleSubtract()
{
for (int i = 0; i < PerformanceInputs.Count; i++)
{
_sampleResults[i] = _sampleLeft[i] - _sampleRight[i];
}
return _sampleResults;
}
[Benchmark(Baseline = true, OperationsPerInvoke = PerformanceInputs.Count), BenchmarkCategory("Multiplication")]
public double[] DoubleMultiply()
{
for (int i = 0; i < PerformanceInputs.Count; i++)
{
_doubleResults[i] = _doubleLeft[i] * _doubleRight[i];
}
return _doubleResults;
}
[Benchmark(OperationsPerInvoke = PerformanceInputs.Count), BenchmarkCategory("Multiplication")]
public DoubleDouble[] DoubleDoubleMultiply()
{
for (int i = 0; i < PerformanceInputs.Count; i++)
{
_results[i] = _left[i] * _right[i];
}
return _results;
}
[Benchmark(OperationsPerInvoke = PerformanceInputs.Count), BenchmarkCategory("Multiplication")]
public DoubleDoubleSample[] DoubleDoubleSampleMultiply()
{
for (int i = 0; i < PerformanceInputs.Count; i++)
{
_sampleResults[i] = _sampleLeft[i] * _sampleRight[i];
}
return _sampleResults;
}
[Benchmark(Baseline = true, OperationsPerInvoke = PerformanceInputs.Count), BenchmarkCategory("Division")]
public double[] DoubleDivide()
{
for (int i = 0; i < PerformanceInputs.Count; i++)
{
_doubleResults[i] = _doubleLeft[i] / _doubleRight[i];
}
return _doubleResults;
}
[Benchmark(OperationsPerInvoke = PerformanceInputs.Count), BenchmarkCategory("Division")]
public DoubleDouble[] DoubleDoubleDivide()
{
for (int i = 0; i < PerformanceInputs.Count; i++)
{
_results[i] = _left[i] / _right[i];
}
return _results;
}
[Benchmark(OperationsPerInvoke = PerformanceInputs.Count), BenchmarkCategory("Division")]
public DoubleDoubleSample[] DoubleDoubleSampleDivide()
{
for (int i = 0; i < PerformanceInputs.Count; i++)
{
_sampleResults[i] = _sampleLeft[i] / _sampleRight[i];
}
return _sampleResults;
}
}