using BenchmarkDotNet.Attributes; namespace Just.PreciseMath.Benchmarks; /// Isolates ordinary/fallback exponent transitions, not special-value handling. [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; } }