using BenchmarkDotNet.Attributes; namespace Just.PreciseMath.Benchmarks; /// Measures bounded dependent chains; each invocation resets the seed. [MemoryDiagnoser] [CategoriesColumn] public class ArithmeticLatencyBenchmarks { private DoubleDouble[] _left = []; private DoubleDouble[] _right = []; private double[] _scalarRight = []; [Params("BothResidual", "Mixed")] public string Scenario { get; set; } = "BothResidual"; [GlobalSetup] public void Setup() { ArithmeticInputs inputs = ArithmeticInputs.Create(Scenario, true); _left = inputs.Left; _right = inputs.Right; _scalarRight = Array.ConvertAll(_right, value => value.High); } [Benchmark(OperationsPerInvoke = ArithmeticInputs.Count), BenchmarkCategory("Addition")] public DoubleDouble DDAdd() { DoubleDouble value = _left[0]; for (int i = 0; i < ArithmeticInputs.Count; i++) { value = value + _right[i]; } return value; } [Benchmark(OperationsPerInvoke = ArithmeticInputs.Count), BenchmarkCategory("Addition")] public DoubleDouble DDScalarAdd() { DoubleDouble value = _left[0]; for (int i = 0; i < ArithmeticInputs.Count; i++) { value = value + _scalarRight[i]; } return value; } [Benchmark(OperationsPerInvoke = ArithmeticInputs.Count), BenchmarkCategory("Addition")] public DoubleDouble ScalarDDAdd() { DoubleDouble value = _left[0]; for (int i = 0; i < ArithmeticInputs.Count; i++) { value = _scalarRight[i] + value; } return value; } [Benchmark(OperationsPerInvoke = ArithmeticInputs.Count), BenchmarkCategory("Subtraction")] public DoubleDouble DDSubtract() { DoubleDouble value = _left[0]; for (int i = 0; i < ArithmeticInputs.Count; i++) { value = value - _right[i]; } return value; } [Benchmark(OperationsPerInvoke = ArithmeticInputs.Count), BenchmarkCategory("Subtraction")] public DoubleDouble DDScalarSubtract() { DoubleDouble value = _left[0]; for (int i = 0; i < ArithmeticInputs.Count; i++) { value = value - _scalarRight[i]; } return value; } [Benchmark(OperationsPerInvoke = ArithmeticInputs.Count), BenchmarkCategory("Subtraction")] public DoubleDouble ScalarDDSubtract() { DoubleDouble value = _left[0]; for (int i = 0; i < ArithmeticInputs.Count; i++) { value = _scalarRight[i] - value; } return value; } [Benchmark(OperationsPerInvoke = ArithmeticInputs.Count), BenchmarkCategory("Multiplication")] public DoubleDouble DDMultiply() { DoubleDouble value = _left[0]; for (int i = 0; i < ArithmeticInputs.Count; i++) { value = value * _right[i]; } return value; } [Benchmark(OperationsPerInvoke = ArithmeticInputs.Count), BenchmarkCategory("Multiplication")] public DoubleDouble DDScalarMultiply() { DoubleDouble value = _left[0]; for (int i = 0; i < ArithmeticInputs.Count; i++) { value = value * _scalarRight[i]; } return value; } [Benchmark(OperationsPerInvoke = ArithmeticInputs.Count), BenchmarkCategory("Multiplication")] public DoubleDouble ScalarDDMultiply() { DoubleDouble value = _left[0]; for (int i = 0; i < ArithmeticInputs.Count; i++) { value = _scalarRight[i] * value; } return value; } [Benchmark(OperationsPerInvoke = ArithmeticInputs.Count), BenchmarkCategory("Division")] public DoubleDouble DDDivide() { DoubleDouble value = _left[0]; for (int i = 0; i < ArithmeticInputs.Count; i++) { value = value / _right[i]; } return value; } [Benchmark(OperationsPerInvoke = ArithmeticInputs.Count), BenchmarkCategory("Division")] public DoubleDouble DDScalarDivide() { DoubleDouble value = _left[0]; for (int i = 0; i < ArithmeticInputs.Count; i++) { value = value / _scalarRight[i]; } return value; } [Benchmark(OperationsPerInvoke = ArithmeticInputs.Count), BenchmarkCategory("Division")] public DoubleDouble ScalarDDDivide() { DoubleDouble value = _left[0]; for (int i = 0; i < ArithmeticInputs.Count; i++) { value = _scalarRight[i] / value; } return value; } }