136 lines
4.7 KiB
C#
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;
|
|
}
|
|
}
|