From 026c1dfddb097ae5279fb5f480adca1d32b5cc1a Mon Sep 17 00:00:00 2001 From: Rafael Vuijk Date: Thu, 6 Aug 2026 17:46:12 +0000 Subject: [PATCH] Pin the logarithmic subtraction edge cases for Level Level's logarithmic operators are covered by LevelTestsBase for the ordinary case, but not where the linear result stops being positive. Two such cases return silently today: v - v -> -Infinity, since log10(0) is -infinity smaller - larger -> NaN, since log10 of a negative number is undefined The second is inconsistent with the rest of the quantity: the Level(quantity, reference) constructor rejects a non-positive ratio with ArgumentOutOfRangeException and the message "The base-10 logarithm of a number <= 0 is undefined", while operator- performs that same logarithm and yields NaN without signalling anything. These tests pin the current behaviour rather than endorse it, so that any later change to it is a visible decision. Also adds the addition case from #1569 with the reporter's own values, asserted against 10 * log10(10^0.16 + 10^0.07), since that issue reads the result as wrong on the assumption that adding levels adds their decibel numbers. --- UnitsNet.Tests/CustomCode/LevelTests.cs | 36 +++++++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/UnitsNet.Tests/CustomCode/LevelTests.cs b/UnitsNet.Tests/CustomCode/LevelTests.cs index 33c7da370a..4468be85a5 100644 --- a/UnitsNet.Tests/CustomCode/LevelTests.cs +++ b/UnitsNet.Tests/CustomCode/LevelTests.cs @@ -41,5 +41,41 @@ public void InvalidReference_ExpectArgumentOutOfRangeException(double quantity, // reference can't be zero or less than zero if quantity is postive. Assert.Throws(() => new Level(quantity, reference)); } + + [Fact] + public void LogarithmicAddition_OfTwoLevels_CombinesThemInLinearSpace() + { + // The values from https://github.com/angularsen/UnitsNet/issues/1569, which read + // 4.18 dB as wrong on the assumption that adding levels adds their decibel numbers. + // Adding two levels combines them in linear power space, so the result is + // 10 * log10(10^0.16 + 10^0.07). + Level sum = Level.FromDecibels(1.6) + Level.FromDecibels(0.7); + + var expected = 10 * Math.Log10(Math.Pow(10, 0.16) + Math.Pow(10, 0.07)); + AssertEx.EqualTolerance(expected, sum.Decibels, DecibelsTolerance); + AssertEx.EqualTolerance(4.18357203248652, sum.Decibels, DecibelsTolerance); + } + + [Fact] + public void LogarithmicSubtraction_OfEqualLevels_ReturnsNegativeInfinity() + { + // Removing a level from itself leaves no power at all, and log10(0) is -infinity. + // Pinned because it is returned silently rather than signalled. + Level v = Level.FromDecibels(40); + + Assert.Equal(double.NegativeInfinity, (double)(v - v).Decibels); + } + + [Fact] + public void LogarithmicSubtraction_WhenSubtrahendIsLarger_ReturnsNaN() + { + // The linear difference is negative here, and log10 of a negative number is undefined. + // The constructor rejects that case with ArgumentOutOfRangeException; this operator + // returns NaN silently instead. Pinned as current behaviour, not endorsed as correct. + Level smaller = Level.FromDecibels(0.7); + Level larger = Level.FromDecibels(1.6); + + Assert.Equal(double.NaN, (double)(smaller - larger).Decibels); + } } }