using System.Globalization; namespace Just.PreciseMath.Tests; public class DoubleDoubleSpanFormattingTests { [Theory] [InlineData("")] [InlineData("G32")] [InlineData("g999")] [InlineData("E20")] [InlineData("F54")] public void SpanFormattingMatchesExactComponentFormatting(string format) { DoubleDouble value = DoubleDouble.FromComponents(1.0, Math.ScaleB(1.0, -54)); NumberFormatInfo provider = new() { NumberDecimalSeparator = "::", NegativeSign = "minus" }; string expected = value.ToString(format, provider); char[] buffer = new char[expected.Length + 1]; buffer[^1] = '!'; ((ISpanFormattable)value).TryFormat(buffer.AsSpan(0, expected.Length), out int written, format, provider).ShouldBeTrue(); written.ShouldBe(expected.Length); new string(buffer, 0, written).ShouldBe(expected); buffer[^1].ShouldBe('!'); } [Fact] public void DefaultSpanFormattingRetainsLowComponentDigits() { Span buffer = stackalloc char[64]; DoubleDouble.FromComponents(1.0, Math.ScaleB(1.0, -54)) .TryFormat(buffer, out int written, provider: CultureInfo.InvariantCulture).ShouldBeTrue(); buffer[..written].ToString().ShouldBe("1.0000000000000000555111512312578"); } [Fact] public void ShortDestinationIsUnchangedAndReportsZero() { char[] buffer = ['!', '!']; DoubleDouble.Pi.TryFormat(buffer, out int written, "G32", CultureInfo.InvariantCulture).ShouldBeFalse(); written.ShouldBe(0); new string(buffer).ShouldBe("!!"); DoubleDouble.One.TryFormat(Span.Empty, out written, provider: CultureInfo.InvariantCulture).ShouldBeFalse(); written.ShouldBe(0); } [Theory] [InlineData(-0.0)] [InlineData(double.NaN)] [InlineData(double.PositiveInfinity)] [InlineData(double.NegativeInfinity)] public void SpanFormattingPreservesSpecialValues(double high) { NumberFormatInfo provider = new() { NegativeSign = "minus", NaNSymbol = "unknown" }; DoubleDouble value = new(high); Span buffer = stackalloc char[64]; value.TryFormat(buffer, out int written, "F2", provider).ShouldBeTrue(); buffer[..written].ToString().ShouldBe(value.ToString("F2", provider)); } [Theory] [InlineData("R")] [InlineData("F1000")] [InlineData("G-1")] public void InvalidFormatThrowsEvenForEmptyDestination(string format) { Should.Throw(() => DoubleDouble.One.TryFormat(Span.Empty, out _, format, CultureInfo.InvariantCulture)); } }