public static bool TryParse([System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] string? value, out System.Numerics.BigInteger result) { throw null; }
public bool TryWriteBytes(System.Span<byte> destination, out int bytesWritten, bool isUnsigned = false, bool isBigEndian = false) { throw null; }
}
- public readonly partial struct Complex : System.IEquatable<System.Numerics.Complex>, System.IFormattable, System.IParsable<System.Numerics.Complex>, System.ISpanFormattable, System.ISpanParsable<System.Numerics.Complex>, System.Numerics.IAdditionOperators<System.Numerics.Complex, System.Numerics.Complex, System.Numerics.Complex>, System.Numerics.IAdditiveIdentity<System.Numerics.Complex, System.Numerics.Complex>, System.Numerics.IDecrementOperators<System.Numerics.Complex>, System.Numerics.IDivisionOperators<System.Numerics.Complex, System.Numerics.Complex, System.Numerics.Complex>, System.Numerics.IEqualityOperators<System.Numerics.Complex, System.Numerics.Complex, bool>, System.Numerics.IIncrementOperators<System.Numerics.Complex>, System.Numerics.IMultiplicativeIdentity<System.Numerics.Complex, System.Numerics.Complex>, System.Numerics.IMultiplyOperators<System.Numerics.Complex, System.Numerics.Complex, System.Numerics.Complex>, System.Numerics.INumberBase<System.Numerics.Complex>, System.Numerics.ISignedNumber<System.Numerics.Complex>, System.Numerics.ISubtractionOperators<System.Numerics.Complex, System.Numerics.Complex, System.Numerics.Complex>, System.Numerics.IUnaryNegationOperators<System.Numerics.Complex, System.Numerics.Complex>, System.Numerics.IUnaryPlusOperators<System.Numerics.Complex, System.Numerics.Complex>
+ public readonly partial struct Complex : System.IEquatable<System.Numerics.Complex>, System.IFormattable, System.IParsable<System.Numerics.Complex>, System.ISpanFormattable, System.ISpanParsable<System.Numerics.Complex>, System.Numerics.IAdditionOperators<System.Numerics.Complex, System.Numerics.Complex, System.Numerics.Complex>, System.Numerics.IAdditiveIdentity<System.Numerics.Complex, System.Numerics.Complex>, System.Numerics.IDecrementOperators<System.Numerics.Complex>, System.Numerics.IDivisionOperators<System.Numerics.Complex, System.Numerics.Complex, System.Numerics.Complex>, System.Numerics.IEqualityOperators<System.Numerics.Complex, System.Numerics.Complex, bool>, System.Numerics.IIncrementOperators<System.Numerics.Complex>, System.Numerics.IMultiplicativeIdentity<System.Numerics.Complex, System.Numerics.Complex>, System.Numerics.IMultiplyOperators<System.Numerics.Complex, System.Numerics.Complex, System.Numerics.Complex>, System.Numerics.INumberBase<System.Numerics.Complex>, System.Numerics.ISignedNumber<System.Numerics.Complex>, System.Numerics.ISubtractionOperators<System.Numerics.Complex, System.Numerics.Complex, System.Numerics.Complex>, System.Numerics.IUnaryNegationOperators<System.Numerics.Complex, System.Numerics.Complex>, System.Numerics.IUnaryPlusOperators<System.Numerics.Complex, System.Numerics.Complex>, System.IUtf8SpanFormattable
{
private readonly int _dummyPrimitive;
public static readonly System.Numerics.Complex ImaginaryOne;
public string ToString(System.IFormatProvider? provider) { throw null; }
public string ToString([System.Diagnostics.CodeAnalysis.StringSyntaxAttribute("NumericFormat")] string? format) { throw null; }
public string ToString([System.Diagnostics.CodeAnalysis.StringSyntaxAttribute("NumericFormat")] string? format, System.IFormatProvider? provider) { throw null; }
- public bool TryFormat(System.Span<char> destination, out int charsWritten, System.ReadOnlySpan<char> format, System.IFormatProvider? provider) { throw null; }
+ public bool TryFormat(System.Span<char> destination, out int charsWritten, [System.Diagnostics.CodeAnalysis.StringSyntaxAttribute("NumericFormat")] System.ReadOnlySpan<char> format = default, System.IFormatProvider? provider = null) { throw null; }
+ public bool TryFormat(System.Span<byte> utf8Destination, out int bytesWritten, [System.Diagnostics.CodeAnalysis.StringSyntaxAttribute("NumericFormat")] System.ReadOnlySpan<char> format = default, System.IFormatProvider? provider = null) { throw null; }
public static bool TryParse(System.ReadOnlySpan<char> s, System.Globalization.NumberStyles style, System.IFormatProvider? provider, out System.Numerics.Complex result) { throw null; }
public static bool TryParse(System.ReadOnlySpan<char> s, System.IFormatProvider? provider, out System.Numerics.Complex result) { throw null; }
public static bool TryParse([System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] string? s, System.Globalization.NumberStyles style, System.IFormatProvider? provider, out System.Numerics.Complex result) { throw null; }
: IEquatable<Complex>,
IFormattable,
INumberBase<Complex>,
- ISignedNumber<Complex>
+ ISignedNumber<Complex>,
+ IUtf8SpanFormattable
{
private const NumberStyles DefaultNumberStyle = NumberStyles.Float | NumberStyles.AllowThousands;
public override int GetHashCode() => HashCode.Combine(m_real, m_imaginary);
- public override string ToString() => $"<{m_real}; {m_imaginary}>";
+ public override string ToString() => ToString(null, null);
public string ToString([StringSyntax(StringSyntaxAttribute.NumericFormat)] string? format) => ToString(format, null);
public string ToString(IFormatProvider? provider) => ToString(null, provider);
- public string ToString([StringSyntax(StringSyntaxAttribute.NumericFormat)] string? format, IFormatProvider? provider) =>
- $"<{m_real.ToString(format, provider)}; {m_imaginary.ToString(format, provider)}>";
+ public string ToString([StringSyntax(StringSyntaxAttribute.NumericFormat)] string? format, IFormatProvider? provider)
+ {
+ // $"<{m_real.ToString(format, provider)}; {m_imaginary.ToString(format, provider)}>";
+ var handler = new DefaultInterpolatedStringHandler(4, 2, provider, stackalloc char[512]);
+ handler.AppendLiteral("<");
+ handler.AppendFormatted(m_real, format);
+ handler.AppendLiteral("; ");
+ handler.AppendFormatted(m_imaginary, format);
+ handler.AppendLiteral(">");
+ return handler.ToStringAndClear();
+ }
public static Complex Sin(Complex value)
{
//
/// <inheritdoc cref="ISpanFormattable.TryFormat(Span{char}, out int, ReadOnlySpan{char}, IFormatProvider?)" />
- public bool TryFormat(Span<char> destination, out int charsWritten, ReadOnlySpan<char> format, IFormatProvider? provider)
- {
- int charsWrittenSoFar = 0;
-
- // We have at least 6 more characters for: <0; 0>
- if (destination.Length < 6)
- {
- charsWritten = charsWrittenSoFar;
- return false;
- }
+ public bool TryFormat(Span<char> destination, out int charsWritten, [StringSyntax(StringSyntaxAttribute.NumericFormat)] ReadOnlySpan<char> format = default, IFormatProvider? provider = null) =>
+ TryFormatCore(destination, out charsWritten, format, provider);
- destination[charsWrittenSoFar++] = '<';
+ public bool TryFormat(Span<byte> utf8Destination, out int bytesWritten, [StringSyntax(StringSyntaxAttribute.NumericFormat)] ReadOnlySpan<char> format = default, IFormatProvider? provider = null) =>
+ TryFormatCore(utf8Destination, out bytesWritten, format, provider);
- bool tryFormatSucceeded = m_real.TryFormat(destination.Slice(charsWrittenSoFar), out int tryFormatCharsWritten, format, provider);
- charsWrittenSoFar += tryFormatCharsWritten;
+ private bool TryFormatCore<TChar>(Span<TChar> destination, out int charsWritten, ReadOnlySpan<char> format, IFormatProvider? provider) where TChar : unmanaged, IBinaryInteger<TChar>
+ {
+ Debug.Assert(typeof(TChar) == typeof(char) || typeof(TChar) == typeof(byte));
- // We have at least 4 more characters for: ; 0>
- if (!tryFormatSucceeded || (destination.Length < (charsWrittenSoFar + 4)))
+ // We have at least 6 more characters for: <0; 0>
+ if (destination.Length >= 6)
{
- charsWritten = charsWrittenSoFar;
- return false;
- }
-
- destination[charsWrittenSoFar++] = ';';
- destination[charsWrittenSoFar++] = ' ';
-
- tryFormatSucceeded = m_imaginary.TryFormat(destination.Slice(charsWrittenSoFar), out tryFormatCharsWritten, format, provider);
- charsWrittenSoFar += tryFormatCharsWritten;
+ int realChars;
+ if (typeof(TChar) == typeof(char) ?
+ m_real.TryFormat(MemoryMarshal.Cast<TChar, char>(destination.Slice(1)), out realChars, format, provider) :
+ m_real.TryFormat(MemoryMarshal.Cast<TChar, byte>(destination.Slice(1)), out realChars, format, provider))
+ {
+ destination[0] = TChar.CreateTruncating('<');
+ destination = destination.Slice(1 + realChars); // + 1 for <
- // We have at least 1 more character for: >
- if (!tryFormatSucceeded || (destination.Length < (charsWrittenSoFar + 1)))
- {
- charsWritten = charsWrittenSoFar;
- return false;
+ // We have at least 4 more characters for: ; 0>
+ if (destination.Length >= 4)
+ {
+ int imaginaryChars;
+ if (typeof(TChar) == typeof(char) ?
+ m_imaginary.TryFormat(MemoryMarshal.Cast<TChar, char>(destination.Slice(2)), out imaginaryChars, format, provider) :
+ m_imaginary.TryFormat(MemoryMarshal.Cast<TChar, byte>(destination.Slice(2)), out imaginaryChars, format, provider))
+ {
+ // We have 1 more character for: >
+ if ((uint)(2 + imaginaryChars) < (uint)destination.Length)
+ {
+ destination[0] = TChar.CreateTruncating(';');
+ destination[1] = TChar.CreateTruncating(' ');
+ destination[2 + imaginaryChars] = TChar.CreateTruncating('>');
+
+ charsWritten = realChars + imaginaryChars + 4;
+ return true;
+ }
+ }
+ }
+ }
}
- destination[charsWrittenSoFar++] = '>';
-
- charsWritten = charsWrittenSoFar;
- return true;
+ charsWritten = 0;
+ return false;
}
//
using System.Collections.Generic;
using System.Globalization;
+using System.Linq;
using System.Runtime.CompilerServices;
-
+using System.Text;
using Xunit;
namespace System.Numerics.Tests
public static void ToStringTest(double real, double imaginary)
{
var complex = new Complex(real, imaginary);
+ NumberFormatInfo numberFormatInfo = CultureInfo.CurrentCulture.NumberFormat;
- string expected = "<" + real.ToString() + "; " + imaginary.ToString() + ">";
- string actual = complex.ToString();
- Assert.Equal(expected, actual);
+ Assert.Equal($"<{real}; {imaginary}>", complex.ToString());
- NumberFormatInfo numberFormatInfo = CultureInfo.CurrentCulture.NumberFormat;
- expected = "<" + real.ToString(numberFormatInfo) + "; " + imaginary.ToString(numberFormatInfo) + ">";
- actual = complex.ToString(numberFormatInfo);
- Assert.Equal(expected, complex.ToString(numberFormatInfo));
+ Assert.Equal($"<{real.ToString(numberFormatInfo)}; {imaginary.ToString(numberFormatInfo)}>", complex.ToString(numberFormatInfo));
+ Assert.Equal($"<{real.ToString((string)null)}; {imaginary.ToString((string)null)}>", complex.ToString((string)null));
+ Assert.Equal($"<{real.ToString((string)null, numberFormatInfo)}; {imaginary.ToString((string)null, numberFormatInfo)}>", complex.ToString((string)null, numberFormatInfo));
foreach (string format in s_supportedStandardNumericFormats)
{
- expected = "<" + real.ToString(format) + "; " + imaginary.ToString(format) + ">";
- actual = complex.ToString(format);
- Assert.Equal(expected, actual);
+ Assert.Equal($"<{real.ToString(format)}; {imaginary.ToString(format)}>", complex.ToString(format));
+ Assert.Equal($"<{real.ToString(format, numberFormatInfo)}; {imaginary.ToString(format, numberFormatInfo)}>", complex.ToString(format, numberFormatInfo));
+ }
+ }
+
+ [Theory]
+ [MemberData(nameof(Boundaries_2_TestData))]
+ [MemberData(nameof(Primitives_2_TestData))]
+ [MemberData(nameof(Random_2_TestData))]
+ [MemberData(nameof(SmallRandom_2_TestData))]
+ [MemberData(nameof(Invalid_2_TestData))]
+ public static void TryFormatTest(double real, double imaginary)
+ {
+ var complex = new Complex(real, imaginary);
+
+ // UTF16
+ {
+ foreach (NumberFormatInfo numberFormatInfo in new[] { CultureInfo.CurrentCulture.NumberFormat, null })
+ {
+ foreach (string format in s_supportedStandardNumericFormats.Append(null))
+ {
+ string expected = $"<{real.ToString(format, numberFormatInfo)}; {imaginary.ToString(format, numberFormatInfo)}>";
+ int charsWritten;
+
+ // Just right or larger than required storage
+ for (int additional = 0; additional < 2; additional++)
+ {
+ char[] chars = new char[expected.Length + additional];
+ Assert.True(complex.TryFormat(chars, out charsWritten, format, numberFormatInfo));
+ Assert.Equal(expected.Length, charsWritten);
+ Assert.Equal(expected, new string(expected.AsSpan(0, expected.Length)));
+ }
+
+ // Too small storage
+ Assert.False(complex.TryFormat(new char[expected.Length - 1], out charsWritten, format, numberFormatInfo));
+ Assert.Equal(0, charsWritten);
+ }
+ }
+ }
- expected = "<" + real.ToString(format, numberFormatInfo) + "; " + imaginary.ToString(format, numberFormatInfo) + ">";
- actual = complex.ToString(format, numberFormatInfo);
- Assert.Equal(expected, actual);
+ // UTF8
+ {
+ foreach (NumberFormatInfo numberFormatInfo in new[] { CultureInfo.CurrentCulture.NumberFormat, null })
+ {
+ foreach (string format in s_supportedStandardNumericFormats.Append(null))
+ {
+ byte[] expected = Encoding.UTF8.GetBytes($"<{real.ToString(format, numberFormatInfo)}; {imaginary.ToString(format, numberFormatInfo)}>");
+ int bytesWritten;
+
+ // Just right or larger than required storage
+ for (int additional = 0; additional < 2; additional++)
+ {
+ byte[] bytes = new byte[expected.Length + additional];
+ Assert.True(complex.TryFormat(bytes, out bytesWritten, format, numberFormatInfo));
+ Assert.Equal(expected.Length, bytesWritten);
+ Assert.Equal(expected, bytes.AsSpan(0, expected.Length).ToArray());
+ }
+
+ // Too small storage
+ Assert.False(complex.TryFormat(new byte[expected.Length - 1], out bytesWritten, format, numberFormatInfo));
+ Assert.Equal(0, bytesWritten);
+ }
+ }
}
}