diff --git a/src/Common/src/System/Globalization/FormatProvider.Number.cs b/src/Common/src/System/Globalization/FormatProvider.Number.cs index 969d4793abbd..ccd74e3a65bb 100644 --- a/src/Common/src/System/Globalization/FormatProvider.Number.cs +++ b/src/Common/src/System/Globalization/FormatProvider.Number.cs @@ -542,7 +542,7 @@ private static unsafe bool ParseNumber(ref char* str, NumberStyles options, ref return false; } - private static bool TrailingZeros(string s, int index) + private static bool TrailingZeros(ReadOnlySpan s, int index) { // For compatibility, we need to allow trailing zeros at the end of a number string for (int i = index; i < s.Length; i++) @@ -555,15 +555,11 @@ private static bool TrailingZeros(string s, int index) return true; } - internal static unsafe bool TryStringToNumber(string str, NumberStyles options, ref NumberBuffer number, StringBuilder sb, NumberFormatInfo numfmt, bool parseDecimal) + internal static unsafe bool TryStringToNumber(ReadOnlySpan str, NumberStyles options, ref NumberBuffer number, StringBuilder sb, NumberFormatInfo numfmt, bool parseDecimal) { - if (str == null) - { - return false; - } Debug.Assert(numfmt != null); - fixed (char* stringPointer = str) + fixed (char* stringPointer = &str.DangerousGetPinnableReference()) { char* p = stringPointer; if (!ParseNumber(ref p, options, ref number, sb, numfmt, parseDecimal) diff --git a/src/System.Runtime.Numerics/ref/System.Runtime.Numerics.cs b/src/System.Runtime.Numerics/ref/System.Runtime.Numerics.cs index eeb9a6fef77f..d1e87b9a0a14 100644 --- a/src/System.Runtime.Numerics/ref/System.Runtime.Numerics.cs +++ b/src/System.Runtime.Numerics/ref/System.Runtime.Numerics.cs @@ -13,6 +13,7 @@ public partial struct BigInteger : System.IComparable, System.IComparable value) { throw null; } public BigInteger(decimal value) { throw null; } public BigInteger(double value) { throw null; } public BigInteger(int value) { throw null; } @@ -46,6 +47,7 @@ public partial struct BigInteger : System.IComparable, System.IComparable value, System.Globalization.NumberStyles style = System.Globalization.NumberStyles.Integer, System.IFormatProvider provider = null) { throw null; } public static System.Numerics.BigInteger Pow(System.Numerics.BigInteger value, int exponent) { throw null; } public static System.Numerics.BigInteger Remainder(System.Numerics.BigInteger dividend, System.Numerics.BigInteger divisor) { throw null; } public static System.Numerics.BigInteger Subtract(System.Numerics.BigInteger left, System.Numerics.BigInteger right) { throw null; } @@ -156,6 +159,8 @@ public partial struct BigInteger : System.IComparable, System.IComparable value, out System.Numerics.BigInteger result, System.Globalization.NumberStyles style = System.Globalization.NumberStyles.Integer, System.IFormatProvider provider = null) { throw null; } + public bool TryWriteBytes(System.Span destination, out int bytesWritten) { throw null; } } [System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential)] public partial struct Complex : System.IEquatable, System.IFormattable diff --git a/src/System.Runtime.Numerics/src/System/Globalization/FormatProvider.BigInteger.cs b/src/System.Runtime.Numerics/src/System/Globalization/FormatProvider.BigInteger.cs index 2db17923bb8b..c8ff75f9e6bc 100644 --- a/src/System.Runtime.Numerics/src/System/Globalization/FormatProvider.BigInteger.cs +++ b/src/System.Runtime.Numerics/src/System/Globalization/FormatProvider.BigInteger.cs @@ -33,7 +33,7 @@ internal static string FormatBigInteger(int precision, int scale, bool sign, str [SecurityCritical] internal static bool TryStringToBigInteger( - string s, + ReadOnlySpan s, NumberStyles styles, NumberFormatInfo numberFormatInfo, StringBuilder receiver, // Receives the decimal digits diff --git a/src/System.Runtime.Numerics/src/System/Numerics/BigInteger.cs b/src/System.Runtime.Numerics/src/System/Numerics/BigInteger.cs index 0addf84af271..5bae91d5ba23 100644 --- a/src/System.Runtime.Numerics/src/System/Numerics/BigInteger.cs +++ b/src/System.Runtime.Numerics/src/System/Numerics/BigInteger.cs @@ -251,12 +251,13 @@ public BigInteger(decimal value) /// /// [CLSCompliant(false)] - public BigInteger(byte[] value) + public BigInteger(byte[] value) : + this(new ReadOnlySpan(value ?? throw new ArgumentNullException(nameof(value)))) { - if (value == null) - throw new ArgumentNullException(nameof(value)); - Contract.EndContractBlock(); + } + public BigInteger(ReadOnlySpan value) + { int byteCount = value.Length; bool isNegative = byteCount > 0 && ((value[byteCount - 1] & 0x80) == 0x80); @@ -605,6 +606,16 @@ public static bool TryParse(string value, NumberStyles style, IFormatProvider pr return BigNumber.TryParseBigInteger(value, style, NumberFormatInfo.GetInstance(provider), out result); } + public static BigInteger Parse(ReadOnlySpan value, NumberStyles style = NumberStyles.Integer, IFormatProvider provider = null) + { + return BigNumber.ParseBigInteger(value, style, NumberFormatInfo.GetInstance(provider)); + } + + public static bool TryParse(ReadOnlySpan value, out BigInteger result, NumberStyles style = NumberStyles.Integer, IFormatProvider provider = null) + { + return BigNumber.TryParseBigInteger(value, style, NumberFormatInfo.GetInstance(provider), out result); + } + public static int Compare(BigInteger left, BigInteger right) { return left.CompareTo(right); @@ -1024,10 +1035,75 @@ public int CompareTo(object obj) /// public byte[] ToByteArray() { + bool success = TryGetBytes(GetBytesMode.AllocateArray, default(Span), out byte[] array, out int bytesWritten); + Debug.Assert(success, "ToByteArray should always succeed"); + Debug.Assert(array != null, "Expected non-null array"); + Debug.Assert(bytesWritten == array.Length); + return array; + } + + /// + /// Copies the value of this BigInteger as little-endian twos-complement + /// bytes, using the fewest number of bytes possible. If the value is zero, + /// outputs one byte whose element is 0x00. + /// + /// The destination span to which the resulting bytes should be written. + /// The number of bytes written to . + /// true if the bytes fit in ; false if not all bytes could be written due to lack of space. + public bool TryWriteBytes(Span destination, out int bytesWritten) => + TryGetBytes(GetBytesMode.Span, destination, out byte[] _, out bytesWritten); + + /// Gets the number of bytes that will be output by and . + /// The number of bytes. + public int GetByteCount() + { + bool success = TryGetBytes(GetBytesMode.Count, default(Span), out byte[] _, out int count); + Debug.Assert(success); + return count; + } + + /// Mode used to enable sharing for multiple purposes. + private enum GetBytesMode { Count, AllocateArray, Span } + + /// Shared logic for , , and . + /// Which entry point is being used. + /// The destination span, if mode is . + /// The output array, if mode is . + /// + /// The number of bytes written to or , + /// or if counting, the number of bytes that would have been written. + /// + /// false if in mode and the destination isn't large enough; otherwise, true. + private bool TryGetBytes(GetBytesMode mode, Span destination, out byte[] array, out int bytesWritten) + { + Debug.Assert(mode == GetBytesMode.AllocateArray || mode == GetBytesMode.Count || mode == GetBytesMode.Span, + $"Unexpected mode {mode}."); + Debug.Assert(mode == GetBytesMode.Span || destination.IsEmpty, + $"If we're not in span mode, we shouldn't have been passed a destination."); + array = null; + bytesWritten = 0; + int sign = _sign; if (sign == 0) { - return new byte[] { 0 }; + switch (mode) + { + case GetBytesMode.Count: + bytesWritten = 1; + return true; + case GetBytesMode.AllocateArray: + array = new byte[] { 0 }; + bytesWritten = 1; + return true; + default: // case GetBytesMode.Span: + if (destination.Length < 1) + { + return false; + } + destination[0] = 0; + bytesWritten = 1; + return true; + } } byte highByte; @@ -1096,17 +1172,29 @@ public byte[] ToByteArray() // Ensure high bit is 0 if positive, 1 if negative bool needExtraByte = (msb & 0x80) != (highByte & 0x80); - byte[] bytes; - int curByte = 0; - if (bits == null) - { - bytes = new byte[msbIndex + 1 + (needExtraByte ? 1 : 0)]; - Debug.Assert(bytes.Length <= 4); + int length = bits == null ? + msbIndex + 1 + (needExtraByte ? 1 : 0) : + checked(4 * (bits.Length - 1) + msbIndex + 1 + (needExtraByte ? 1 : 0)); + switch (mode) + { + case GetBytesMode.Count: + bytesWritten = length; + return true; + case GetBytesMode.AllocateArray: + destination = array = new byte[length]; + break; + default: // case GetBytesMode.Span: + if (destination.Length < length) + { + bytesWritten = 0; + return false; + } + break; } - else - { - bytes = new byte[checked(4 * (bits.Length - 1) + msbIndex + 1 + (needExtraByte ? 1 : 0))]; + int curByte = 0; + if (bits != null) + { for (int i = 0; i < bits.Length - 1; i++) { uint dword = bits[i]; @@ -1120,21 +1208,24 @@ public byte[] ToByteArray() } for (int j = 0; j < 4; j++) { - bytes[curByte++] = unchecked((byte)dword); + destination[curByte++] = unchecked((byte)dword); dword >>= 8; } } } + for (int j = 0; j <= msbIndex; j++) { - bytes[curByte++] = unchecked((byte)highDword); + destination[curByte++] = unchecked((byte)highDword); highDword >>= 8; } if (needExtraByte) { - bytes[bytes.Length - 1] = highByte; + destination[length - 1] = highByte; } - return bytes; + + bytesWritten = length; + return true; } /// diff --git a/src/System.Runtime.Numerics/src/System/Numerics/BigNumber.cs b/src/System.Runtime.Numerics/src/System/Numerics/BigNumber.cs index ebc1a9268601..ebf3e3459333 100644 --- a/src/System.Runtime.Numerics/src/System/Numerics/BigNumber.cs +++ b/src/System.Runtime.Numerics/src/System/Numerics/BigNumber.cs @@ -324,6 +324,18 @@ internal static bool TryValidateParseStyleInteger(NumberStyles style, out Argume [SecuritySafeCritical] internal static bool TryParseBigInteger(string value, NumberStyles style, NumberFormatInfo info, out BigInteger result) + { + if (value == null) + { + result = default(BigInteger); + return false; + } + + return TryParseBigInteger(AsReadOnlySpan(value), style, info, out result); + } + + [SecuritySafeCritical] + internal static bool TryParseBigInteger(ReadOnlySpan value, NumberStyles style, NumberFormatInfo info, out BigInteger result) { unsafe { @@ -357,8 +369,26 @@ internal static bool TryParseBigInteger(string value, NumberStyles style, Number internal static BigInteger ParseBigInteger(string value, NumberStyles style, NumberFormatInfo info) { if (value == null) + { throw new ArgumentNullException(nameof(value)); + } + + return ParseBigInteger(AsReadOnlySpan(value), style, info); + } + // TODO #22688: Remove this and replace it with the real AsReadOnlySpan extension + // method from System.Memory once the System.Memory package is marked stable + // and the package validation system allows us to take a dependency on it. + private static unsafe ReadOnlySpan AsReadOnlySpan(string s) + { + fixed (char* c = s) + { + return new ReadOnlySpan(c, s.Length); + } + } + + internal static BigInteger ParseBigInteger(ReadOnlySpan value, NumberStyles style, NumberFormatInfo info) + { ArgumentException e; if (!TryValidateParseStyleInteger(style, out e)) throw e; diff --git a/src/System.Runtime.Numerics/tests/BigInteger/ToByteArray.cs b/src/System.Runtime.Numerics/tests/BigInteger/ToByteArray.cs index 60e1a9ad9c01..224e23f27eb5 100644 --- a/src/System.Runtime.Numerics/tests/BigInteger/ToByteArray.cs +++ b/src/System.Runtime.Numerics/tests/BigInteger/ToByteArray.cs @@ -2,36 +2,42 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +using System.Collections.Generic; using Xunit; namespace System.Numerics.Tests { - public class ToByteArrayTest + public partial class ExtractBytesMembersTests { + public static IEnumerable FromIntTests_MemberData() + { + yield return new object[] { 0, new byte[] { 0x00 } }; + yield return new object[] { 3, new byte[] { 0x03 } }; + yield return new object[] { 128, new byte[] { 0x80, 0x00 } }; + yield return new object[] { 200, new byte[] { 0xc8, 0x00 } }; + yield return new object[] { 256, new byte[] { 0x00, 0x01 } }; + yield return new object[] { 2005, new byte[] { 0xd5, 0x07 } }; + yield return new object[] { 10197, new byte[] { 0xd5, 0x27 } }; + yield return new object[] { 33023, new byte[] { 0xff, 0x80, 0x00 } }; + yield return new object[] { 2368349, new byte[] { 0x5d, 0x23, 0x24 } }; + yield return new object[] { 10756957, new byte[] { 0x5d, 0x23, 0xa4, 0x00 } }; + yield return new object[] { 193100307, new byte[] { 0x13, 0x7a, 0x82, 0x0b } }; + yield return new object[] { 1266842131, new byte[] { 0x13, 0x7a, 0x82, 0x4b } }; + yield return new object[] { int.MaxValue, new byte[] { 0xff, 0xff, 0xff, 0x7f } }; + yield return new object[] { -1, new byte[] { 0xff } }; + yield return new object[] { -128, new byte[] { 0x80 } }; + yield return new object[] { -172, new byte[] { 0x54, 0xff } }; + yield return new object[] { -23439, new byte[] { 0x71, 0xa4 } }; + yield return new object[] { -51301, new byte[] { 0x9b, 0x37, 0xff } }; + yield return new object[] { -126341, new byte[] { 0x7b, 0x12, 0xfe } }; + yield return new object[] { -13194515, new byte[] { 0xed, 0xaa, 0x36, 0xff } }; + yield return new object[] { -2068145902, new byte[] { 0x12, 0x99, 0xba, 0x84 } }; + yield return new object[] { int.MinValue, new byte[] { 0x00, 0x00, 0x00, 0x80 } }; + } + [Theory] - [InlineData(0, new byte[] { 0x00 })] - [InlineData(3, new byte[] { 0x03 })] - [InlineData(128, new byte[] { 0x80, 0x00 })] - [InlineData(200, new byte[] { 0xc8, 0x00 })] - [InlineData(256, new byte[] { 0x00, 0x01 })] - [InlineData(2005, new byte[] { 0xd5, 0x07 })] - [InlineData(10197, new byte[] { 0xd5, 0x27 })] - [InlineData(33023, new byte[] { 0xff, 0x80, 0x00 })] - [InlineData(2368349, new byte[] { 0x5d, 0x23, 0x24 })] - [InlineData(10756957, new byte[] { 0x5d, 0x23, 0xa4, 0x00 })] - [InlineData(193100307, new byte[] { 0x13, 0x7a, 0x82, 0x0b })] - [InlineData(1266842131, new byte[] { 0x13, 0x7a, 0x82, 0x4b })] - [InlineData(int.MaxValue, new byte[] { 0xff, 0xff, 0xff, 0x7f })] - [InlineData(-1, new byte[] { 0xff })] - [InlineData(-128, new byte[] { 0x80 })] - [InlineData(-172, new byte[] { 0x54, 0xff })] - [InlineData(-23439, new byte[] { 0x71, 0xa4 })] - [InlineData(-51301, new byte[] { 0x9b, 0x37, 0xff })] - [InlineData(-126341, new byte[] { 0x7b, 0x12, 0xfe })] - [InlineData(-13194515, new byte[] { 0xed, 0xaa, 0x36, 0xff })] - [InlineData(-2068145902, new byte[] { 0x12, 0x99, 0xba, 0x84 })] - [InlineData(int.MinValue, new byte[] { 0x00, 0x00, 0x00, 0x80 })] - public void FromIntTests(int i, byte[] expectedBytes) + [MemberData(nameof(FromIntTests_MemberData))] + public void ToByteArray_FromIntTests(int i, byte[] expectedBytes) { BigInteger bi = new BigInteger(i); byte[] bytes = bi.ToByteArray(); @@ -40,34 +46,39 @@ public void FromIntTests(int i, byte[] expectedBytes) Assert.Equal(bi, bi2); } + public static IEnumerable FromLongTests_MemberData() + { + yield return new object[] { 0x100112233L, new byte[] { 0x33, 0x22, 0x11, 0x00, 0x01 } }; + yield return new object[] { 0x300112233L, new byte[] { 0x33, 0x22, 0x11, 0x00, 0x03 } }; + yield return new object[] { 0x8000112233L, new byte[] { 0x33, 0x22, 0x11, 0x00, 0x80, 0x00 } }; + yield return new object[] { 0x3cd00112233L, new byte[] { 0x33, 0x22, 0x11, 0x00, 0xcd, 0x03 } }; + yield return new object[] { 0xf92100112233L, new byte[] { 0x33, 0x22, 0x11, 0x00, 0x21, 0xf9, 0x00 } }; + yield return new object[] { 0x749aa00112233L, new byte[] { 0x33, 0x22, 0x11, 0x00, 0xaa, 0x49, 0x07 } }; + yield return new object[] { 0x80112200112233L, new byte[] { 0x33, 0x22, 0x11, 0x00, 0x22, 0x11, 0x80, 0x00 } }; + yield return new object[] { 0x7654321000112233L, new byte[] { 0x33, 0x22, 0x11, 0x00, 0x10, 0x32, 0x54, 0x76 } }; + yield return new object[] { long.MaxValue, new byte[] { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f } }; + yield return new object[] { -0x100112233L, new byte[] { 0xcd, 0xdd, 0xee, 0xff, 0xfe } }; + yield return new object[] { -0x8000112233L, new byte[] { 0xcd, 0xdd, 0xee, 0xff, 0x7f, 0xff } }; + yield return new object[] { -0x3cd00112233L, new byte[] { 0xcd, 0xdd, 0xee, 0xff, 0x32, 0xfc } }; + yield return new object[] { -0xf92100112233L, new byte[] { 0xcd, 0xdd, 0xee, 0xff, 0xde, 0x06, 0xff } }; + yield return new object[] { -0x749aa00112233L, new byte[] { 0xcd, 0xdd, 0xee, 0xff, 0x55, 0xb6, 0xf8 } }; + yield return new object[] { -0x80112200112233L, new byte[] { 0xcd, 0xdd, 0xee, 0xff, 0xdd, 0xee, 0x7f, 0xff } }; + yield return new object[] { -0x7654321000112233L, new byte[] { 0xcd, 0xdd, 0xee, 0xff, 0xef, 0xcd, 0xab, 0x89 } }; + yield return new object[] { long.MinValue, new byte[] { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80 } }; + yield return new object[] { -0x100000000L, new byte[] { 0x00, 0x00, 0x00, 0x00, 0xff } }; + yield return new object[] { -0x300000000L, new byte[] { 0x00, 0x00, 0x00, 0x00, 0xfd } }; + yield return new object[] { -0x8000000000L, new byte[] { 0x00, 0x00, 0x00, 0x00, 0x80 } }; + yield return new object[] { -0xfe00000000L, new byte[] { 0x00, 0x00, 0x00, 0x00, 0x02, 0xff } }; + yield return new object[] { -0xff00000000L, new byte[] { 0x00, 0x00, 0x00, 0x00, 0x01, 0xff } }; + yield return new object[] { -0xfeff00000000L, new byte[] { 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0xff } }; + yield return new object[] { -0xffff00000000L, new byte[] { 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0xff } }; + yield return new object[] { -0xfeffff00000000L, new byte[] { 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0xff } }; + yield return new object[] { -0xffffff00000000L, new byte[] { 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0xff } }; + } + [Theory] - [InlineData(0x100112233L, new byte[] { 0x33, 0x22, 0x11, 0x00, 0x01 })] - [InlineData(0x300112233L, new byte[] { 0x33, 0x22, 0x11, 0x00, 0x03 })] - [InlineData(0x8000112233L, new byte[] { 0x33, 0x22, 0x11, 0x00, 0x80, 0x00 })] - [InlineData(0x3cd00112233L, new byte[] { 0x33, 0x22, 0x11, 0x00, 0xcd, 0x03 })] - [InlineData(0xf92100112233L, new byte[] { 0x33, 0x22, 0x11, 0x00, 0x21, 0xf9, 0x00 })] - [InlineData(0x749aa00112233L, new byte[] { 0x33, 0x22, 0x11, 0x00, 0xaa, 0x49, 0x07 })] - [InlineData(0x80112200112233L, new byte[] { 0x33, 0x22, 0x11, 0x00, 0x22, 0x11, 0x80, 0x00 })] - [InlineData(0x7654321000112233L, new byte[] { 0x33, 0x22, 0x11, 0x00, 0x10, 0x32, 0x54, 0x76 })] - [InlineData(long.MaxValue, new byte[] { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f })] - [InlineData(-0x100112233L, new byte[] { 0xcd, 0xdd, 0xee, 0xff, 0xfe })] - [InlineData(-0x8000112233L, new byte[] { 0xcd, 0xdd, 0xee, 0xff, 0x7f, 0xff })] - [InlineData(-0x3cd00112233L, new byte[] { 0xcd, 0xdd, 0xee, 0xff, 0x32, 0xfc })] - [InlineData(-0xf92100112233L, new byte[] { 0xcd, 0xdd, 0xee, 0xff, 0xde, 0x06, 0xff })] - [InlineData(-0x749aa00112233L, new byte[] { 0xcd, 0xdd, 0xee, 0xff, 0x55, 0xb6, 0xf8 })] - [InlineData(-0x80112200112233L, new byte[] { 0xcd, 0xdd, 0xee, 0xff, 0xdd, 0xee, 0x7f, 0xff })] - [InlineData(-0x7654321000112233L, new byte[] { 0xcd, 0xdd, 0xee, 0xff, 0xef, 0xcd, 0xab, 0x89 })] - [InlineData(long.MinValue, new byte[] { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80 })] - [InlineData(-0x100000000L, new byte[] { 0x00, 0x00, 0x00, 0x00, 0xff })] - [InlineData(-0x300000000L, new byte[] { 0x00, 0x00, 0x00, 0x00, 0xfd })] - [InlineData(-0x8000000000L, new byte[] { 0x00, 0x00, 0x00, 0x00, 0x80 })] - [InlineData(-0xfe00000000L, new byte[] { 0x00, 0x00, 0x00, 0x00, 0x02, 0xff })] - [InlineData(-0xff00000000L, new byte[] { 0x00, 0x00, 0x00, 0x00, 0x01, 0xff })] - [InlineData(-0xfeff00000000L, new byte[] { 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0xff })] - [InlineData(-0xffff00000000L, new byte[] { 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0xff })] - [InlineData(-0xfeffff00000000L, new byte[] { 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0xff })] - [InlineData(-0xffffff00000000L, new byte[] { 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0xff })] - public void FromLongTests(long l, byte[] expectedBytes) + [MemberData(nameof(FromLongTests_MemberData))] + public void ToByteArray_FromLongTests(long l, byte[] expectedBytes) { BigInteger bi = new BigInteger(l); byte[] bytes = bi.ToByteArray(); @@ -76,12 +87,16 @@ public void FromLongTests(long l, byte[] expectedBytes) Assert.Equal(bi, bi2); } + public static IEnumerable FromStringTests_MemberData() + { + yield return new object[] { "-18374686475376656384", new byte[] { 0xff, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00 } }; + yield return new object[] { "-18446744069414584320", new byte[] { 0xff, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00 } }; + yield return new object[] { "12364093636075302621581796971036731159910277399901099375861080574506898189967563102391591201943540153492149033597384108294298661111799425262742266671957323486506857011293831406641316917374615487590434666756862524718179898130435474398176187353530443750986128762955255137790631223519091107256083370837751230886741470719554141609004126665185940207631783192780186624919167901565253877397154522582982120840364212333366972597473045167409184762879376102731157263235904816835054250885637739932914015117504485702897712016943555929710070193511128651378003670520306509417025958556935067307123832592173743652726898616663215056178200135054604939862749863002480827458494339065850786495122398411385446068167146399066035389699059499954747263948595492570959736940353095030589033792026029085438901525807032848103038290802923997216273712349905230080849822000411239032166420681788646737098078876258256753058713515144604794792139863186822520361187685685356628044518258989638970651859178568755065879235553215218267011024902142765549091793970027321040036512883269922219608216030987714165823965404563131018846411947569009598716649463301689241563037584803938711917477764863093448004918315253652379776337794243677630540042379049027", new byte[] { 0x00, 0xf0, 0x1d, 0x7b, 0xa2, 0xfd, 0x50, 0xf9, 0x50, 0x07, 0xce, 0x2a, 0xdf, 0xfb, 0x75, 0x70, 0x49, 0x5e, 0x5d, 0xf7, 0x1b, 0x0a, 0x76, 0x1f, 0xe7, 0xe3, 0xc7, 0x0a, 0xc7, 0xee, 0xca, 0x4e, 0xa2, 0xe6, 0xae, 0xe8, 0x1a, 0x2c, 0x3b, 0xa9, 0x12, 0x77, 0xb1, 0x47, 0x3c, 0xb5, 0xab, 0x32, 0x26, 0x18, 0x0d, 0x43, 0x51, 0x6b, 0x11, 0x0c, 0x45, 0xed, 0x52, 0x7d, 0xce, 0xe8, 0x75, 0x6c, 0xe1, 0xda, 0xaf, 0x42, 0x1c, 0xc6, 0x21, 0x23, 0x1f, 0x5d, 0x2d, 0x48, 0xf8, 0x20, 0x67, 0x2f, 0x49, 0x3d, 0x3e, 0x5d, 0xc2, 0x53, 0xc8, 0xe0, 0x3d, 0xe2, 0xdc, 0x51, 0x2f, 0x44, 0xc9, 0x72, 0xb6, 0x04, 0xa0, 0x19, 0x1f, 0x03, 0xb9, 0x0f, 0x57, 0x80, 0x55, 0x41, 0x10, 0x7e, 0x7c, 0x78, 0xdc, 0xbb, 0x82, 0x6e, 0x6a, 0xd9, 0x0e, 0xac, 0x87, 0x0c, 0xfd, 0xc0, 0x79, 0xdf, 0xf5, 0x98, 0xfe, 0x9c, 0x58, 0xa9, 0x63, 0xc2, 0x99, 0x31, 0x09, 0x1c, 0x50, 0xcf, 0x03, 0x4f, 0x96, 0xef, 0x98, 0x56, 0x44, 0xc2, 0x0f, 0x63, 0x20, 0x19, 0x0b, 0x60, 0x28, 0x09, 0xb2, 0x3e, 0xe5, 0xe3, 0x91, 0xc2, 0x98, 0x3d, 0xc0, 0x81, 0x0b, 0x5a, 0xdd, 0x88, 0x6a, 0xc1, 0xff, 0x94, 0x7f, 0xe0, 0x96, 0x6b, 0x67, 0x75, 0x80, 0x53, 0xa1, 0x89, 0x14, 0x19, 0x59, 0xdc, 0x13, 0x67, 0x01, 0x7c, 0x64, 0xfe, 0xeb, 0x7b, 0x8c, 0x97, 0x2d, 0x1a, 0x90, 0x48, 0x4b, 0xea, 0x48, 0xc0, 0x77, 0x23, 0x68, 0x65, 0x19, 0xcf, 0xcf, 0x1c, 0x89, 0x93, 0xe0, 0xd2, 0xfd, 0x81, 0x6a, 0x6e, 0xd8, 0x76, 0xad, 0x65, 0xb5, 0xe0, 0xe1, 0xe2, 0x9c, 0x13, 0x70, 0x0e, 0x79, 0x1c, 0xaa, 0xac, 0x0d, 0x3f, 0x10, 0x4e, 0x47, 0x36, 0xb9, 0x23, 0xd3, 0x6a, 0x50, 0x9a, 0xe2, 0x83, 0x94, 0xf8, 0x1b, 0x41, 0x4c, 0x22, 0x92, 0x58, 0x9f, 0xc8, 0xad, 0x36, 0x51, 0x59, 0xa6, 0xbb, 0x86, 0x4f, 0x9d, 0x3a, 0x9f, 0x1d, 0x0b, 0x2e, 0x7f, 0xf8, 0x83, 0xfd, 0x1c, 0x3b, 0xe1, 0x3d, 0xb2, 0xdc, 0x13, 0x18, 0x71, 0xec, 0x63, 0xf3, 0xfc, 0x41, 0x6f, 0x14, 0xec, 0xcc, 0x7f, 0x28, 0xeb, 0x12, 0xc6, 0x4c, 0xa4, 0x92, 0x7f, 0x7a, 0x65, 0xcf, 0x8f, 0x63, 0x47, 0x3e, 0x4f, 0xeb, 0x03, 0x7b, 0x20, 0xf8, 0x01, 0xa2, 0x9d, 0xe2, 0x5f, 0x85, 0xfb, 0x7b, 0xdf, 0x10, 0x45, 0x2f, 0x6f, 0xb2, 0x6b, 0xff, 0x69, 0xf5, 0x64, 0x8e, 0x18, 0x71, 0x7a, 0x04, 0x31, 0xc3, 0xf8, 0xa0, 0x6c, 0x0f, 0x0a, 0x57, 0x83, 0x83, 0x58, 0xda, 0xaf, 0x99, 0xe6, 0x68, 0x13, 0xe8, 0x15, 0xbc, 0xd7, 0xef, 0xb2, 0x4b, 0x08, 0x18, 0x97, 0xb2, 0x77, 0x0c, 0xb5, 0x96, 0xdb, 0x21, 0x14, 0x39, 0x52, 0x9f, 0x83, 0x47, 0x96, 0xe8, 0x9f, 0x94, 0xe2, 0x73, 0x40, 0x02, 0x7f, 0xbd, 0xb9, 0x65, 0x6a, 0x33, 0x15, 0xb8, 0xc8, 0x9d, 0x12, 0xf9, 0x14, 0x04, 0x77, 0x56, 0xdc, 0x87, 0xd2, 0xca, 0xb2, 0x05, 0x99, 0xad, 0xa6, 0xd2, 0x81, 0x8f, 0x64, 0xcd, 0xe5, 0x70, 0x2c, 0xbf, 0xc0, 0xb6, 0xb7, 0xa8, 0x4a, 0x45, 0x6b, 0x98, 0x8f, 0x5b, 0xb8, 0x87, 0xf5, 0x64, 0xd1, 0x67, 0xd6, 0xdd, 0x76, 0x29, 0xf0, 0x77, 0x45, 0xfc, 0x27, 0xa4, 0x4a, 0xac, 0xaa, 0x1a, 0x90, 0xbe, 0xf8, 0x91, 0x50, 0x30, 0x6d, 0x73, 0x49, 0x3c, 0xab, 0xa4, 0xaf, 0x13, 0xa8, 0xdd, 0x0a, 0xf5, 0xc3, 0x34, 0x98, 0xb4, 0x7f, 0x0b, 0xb4, 0x63, 0x0f, 0xe3, 0x6e, 0xcc, 0xf8, 0x1d, 0xea, 0x34, 0x71, 0x8b, 0x06, 0xa5, 0x4f, 0x81, 0x12, 0xa9, 0xfd, 0xb8, 0x43 } }; + yield return new object[] { "-1500566381192798663042470094195709329888702572609999105286667163606153967917290138712408909178830809119008530236180974166477902167438722120032328817587204550920260039698718901932896233377293832747667996098291476468951412311792579258943277768740116090186686963715856483147820131067091322876669577393210366426487028489206389247040659375214497672166049911500383423054774768058254673393263777607084960848658501529675225559011863409579602879830226289200557853195239635009395081629845517655774307827048680743808664945667425540772434721298573889660136104342949269877806888346513652384111162522895043239369803590295673472600852282901495791087130835483730406094888840219829189061112151151001898468218215751327382511813082884657126285166508024920536549363279290734920537316417286759974845704859198588552892947264856714040130408613412473996518038227113385600353365608575770837750435553392852567153310861059766627383200108369176626042676222592985818614861742325706568951932845447397512345181981733524874445871904571909006536844113768514813826258460666950996534336842871477679076553532049073323784011247842133811527684859166963235747571306708361946012941167234981369225227878132777327321706825860067928644566542309248", new byte[] { 0xe2, 0xdb, 0xc3, 0xee, 0xdc, 0xd0, 0xa4, 0xdc, 0x41, 0xec, 0xf7, 0xf3, 0x53, 0x2f, 0xd9, 0x5e, 0xe5, 0xbf, 0x5e, 0xea, 0x84, 0xde, 0x00, 0x79, 0x48, 0xc6, 0xf4, 0xd0, 0x29, 0xd9, 0x41, 0xb3, 0xc1, 0x31, 0xe0, 0x18, 0x42, 0xa5, 0x76, 0x88, 0x95, 0x60, 0xe8, 0x55, 0x51, 0x98, 0x01, 0xdb, 0x58, 0x0f, 0x76, 0xe5, 0x23, 0xb3, 0xa3, 0x8b, 0xb6, 0x8b, 0x66, 0x30, 0xd2, 0xb4, 0x13, 0x44, 0xd7, 0xa1, 0x6f, 0xa1, 0xee, 0x41, 0xab, 0x87, 0x5b, 0x64, 0x53, 0x80, 0x1b, 0x1b, 0x15, 0xba, 0x7e, 0x19, 0xbd, 0xc5, 0x9e, 0xfa, 0x1e, 0x59, 0x19, 0x56, 0x59, 0x7e, 0xa3, 0x2d, 0x97, 0xc8, 0xd9, 0x9f, 0xd3, 0x9b, 0x43, 0x25, 0x31, 0x4b, 0x17, 0x5c, 0x5d, 0x95, 0xd2, 0x5a, 0x91, 0xca, 0x83, 0xe9, 0x16, 0x33, 0x10, 0x26, 0x65, 0x31, 0x79, 0xa3, 0xf7, 0x89, 0xd5, 0xe3, 0x8d, 0x45, 0x86, 0x2a, 0xc9, 0xd8, 0x40, 0x93, 0xd8, 0xbf, 0x6f, 0xfa, 0x13, 0xf5, 0x4a, 0x62, 0x15, 0xd9, 0x55, 0xd9, 0xf6, 0xcc, 0xc2, 0xdb, 0xbc, 0xce, 0x50, 0x7a, 0x45, 0xca, 0xca, 0x54, 0x20, 0x76, 0x8e, 0x26, 0x9a, 0x5d, 0x3b, 0x23, 0xad, 0x80, 0xa5, 0xae, 0x63, 0x27, 0x03, 0x10, 0x65, 0x06, 0x6e, 0x65, 0x38, 0x70, 0x10, 0xef, 0xfb, 0xbc, 0xcf, 0xf3, 0x3d, 0x0a, 0x40, 0xe7, 0xd3, 0x20, 0x5d, 0x4f, 0x84, 0xd8, 0xcb, 0xea, 0x65, 0x28, 0x26, 0x15, 0x54, 0x08, 0x77, 0x07, 0xd4, 0x21, 0xb4, 0x69, 0xc6, 0x70, 0x02, 0xd2, 0x5d, 0x4b, 0x7f, 0xf6, 0xb4, 0x11, 0x7d, 0x1b, 0x74, 0x59, 0x1f, 0x2d, 0x5d, 0x75, 0x5c, 0x1a, 0x6e, 0x78, 0xad, 0x12, 0x8d, 0x3b, 0x52, 0x0d, 0x4a, 0x9f, 0x28, 0x22, 0xc4, 0x36, 0xb3, 0xdf, 0xd5, 0xa3, 0xa3, 0xa7, 0x06, 0xea, 0x49, 0x16, 0x01, 0xc8, 0xb2, 0x27, 0xab, 0x04, 0xa2, 0x62, 0x93, 0xcb, 0xdc, 0xfe, 0x33, 0xe4, 0x31, 0x58, 0x7c, 0x08, 0x23, 0x4c, 0x88, 0x1e, 0x9f, 0xc9, 0x39, 0x46, 0xea, 0x7a, 0x69, 0xfa, 0xff, 0x38, 0x87, 0x6b, 0xde, 0x7c, 0x6b, 0xfa, 0x2f, 0x81, 0xff, 0xb1, 0x82, 0x34, 0x38, 0xb8, 0xd1, 0xbf, 0x68, 0x60, 0x07, 0x3d, 0x91, 0x4e, 0xb2, 0x02, 0x1a, 0x05, 0x70, 0xb7, 0x26, 0xbb, 0x95, 0xad, 0xfd, 0xcc, 0x52, 0x80, 0xf9, 0xda, 0x45, 0x04, 0x24, 0xc4, 0x8f, 0x46, 0x22, 0x9a, 0x0d, 0xa0, 0x88, 0x03, 0x54, 0x2d, 0x2f, 0x54, 0x1b, 0xf1, 0xe5, 0xfe, 0xa0, 0x6c, 0x70, 0x31, 0xb1, 0x36, 0x8b, 0xcf, 0x33, 0xf5, 0xc1, 0x77, 0x6c, 0x89, 0xa3, 0xb3, 0xd9, 0x66, 0x5d, 0xb8, 0x40, 0x66, 0xb3, 0x0d, 0xcd, 0x0c, 0xde, 0xd4, 0x6c, 0x55, 0x66, 0x95, 0x78, 0x7f, 0xc9, 0x0a, 0x8e, 0x41, 0x50, 0xc2, 0xe9, 0x88, 0x91, 0xce, 0x56, 0xa2, 0xc6, 0xc4, 0x87, 0xb0, 0x25, 0xc9, 0x74, 0xf6, 0x58, 0xbe, 0xde, 0xf9, 0xee, 0x37, 0x5c, 0xfe, 0x54, 0xc1, 0x68, 0x40, 0x64, 0x99, 0x66, 0x2e, 0x18, 0x6b, 0xa6, 0x0a, 0xfe, 0x13, 0xec, 0x1e, 0x6f, 0xf3, 0xa0, 0xc9, 0x17, 0x9b, 0x6e, 0x92, 0xf2, 0x42, 0xfb, 0xbd, 0xfb, 0x11, 0x53, 0x7c, 0xeb, 0xd4, 0xd2, 0x16, 0xaf, 0x20, 0x5e, 0x42, 0x09, 0xea, 0x92, 0x0b, 0xab, 0x94, 0xaa, 0xaf, 0x23, 0xda, 0xda, 0xe3, 0x40, 0xc1, 0x5a, 0xab, 0xc2, 0xdd, 0x8d, 0x76, 0x62, 0xb3, 0xd4, 0x13, 0xac, 0x0c, 0x06, 0xa9, 0x98, 0x27, 0xa8, 0x34, 0x94, 0xd6, 0x85, 0x99, 0x24, 0x7e, 0x8a, 0xf1, 0xf8, 0x6d, 0xef, 0x66, 0xf0, 0xe6, 0xc9, 0x2c, 0x4d, 0x1f, 0x3e, 0xfa, 0x28, 0x80 } }; + } + [Theory] - [InlineData("-18374686475376656384", new byte[] { 0xff, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00 })] - [InlineData("-18446744069414584320", new byte[] { 0xff, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00 })] - [InlineData("12364093636075302621581796971036731159910277399901099375861080574506898189967563102391591201943540153492149033597384108294298661111799425262742266671957323486506857011293831406641316917374615487590434666756862524718179898130435474398176187353530443750986128762955255137790631223519091107256083370837751230886741470719554141609004126665185940207631783192780186624919167901565253877397154522582982120840364212333366972597473045167409184762879376102731157263235904816835054250885637739932914015117504485702897712016943555929710070193511128651378003670520306509417025958556935067307123832592173743652726898616663215056178200135054604939862749863002480827458494339065850786495122398411385446068167146399066035389699059499954747263948595492570959736940353095030589033792026029085438901525807032848103038290802923997216273712349905230080849822000411239032166420681788646737098078876258256753058713515144604794792139863186822520361187685685356628044518258989638970651859178568755065879235553215218267011024902142765549091793970027321040036512883269922219608216030987714165823965404563131018846411947569009598716649463301689241563037584803938711917477764863093448004918315253652379776337794243677630540042379049027", new byte[] { 0x00, 0xf0, 0x1d, 0x7b, 0xa2, 0xfd, 0x50, 0xf9, 0x50, 0x07, 0xce, 0x2a, 0xdf, 0xfb, 0x75, 0x70, 0x49, 0x5e, 0x5d, 0xf7, 0x1b, 0x0a, 0x76, 0x1f, 0xe7, 0xe3, 0xc7, 0x0a, 0xc7, 0xee, 0xca, 0x4e, 0xa2, 0xe6, 0xae, 0xe8, 0x1a, 0x2c, 0x3b, 0xa9, 0x12, 0x77, 0xb1, 0x47, 0x3c, 0xb5, 0xab, 0x32, 0x26, 0x18, 0x0d, 0x43, 0x51, 0x6b, 0x11, 0x0c, 0x45, 0xed, 0x52, 0x7d, 0xce, 0xe8, 0x75, 0x6c, 0xe1, 0xda, 0xaf, 0x42, 0x1c, 0xc6, 0x21, 0x23, 0x1f, 0x5d, 0x2d, 0x48, 0xf8, 0x20, 0x67, 0x2f, 0x49, 0x3d, 0x3e, 0x5d, 0xc2, 0x53, 0xc8, 0xe0, 0x3d, 0xe2, 0xdc, 0x51, 0x2f, 0x44, 0xc9, 0x72, 0xb6, 0x04, 0xa0, 0x19, 0x1f, 0x03, 0xb9, 0x0f, 0x57, 0x80, 0x55, 0x41, 0x10, 0x7e, 0x7c, 0x78, 0xdc, 0xbb, 0x82, 0x6e, 0x6a, 0xd9, 0x0e, 0xac, 0x87, 0x0c, 0xfd, 0xc0, 0x79, 0xdf, 0xf5, 0x98, 0xfe, 0x9c, 0x58, 0xa9, 0x63, 0xc2, 0x99, 0x31, 0x09, 0x1c, 0x50, 0xcf, 0x03, 0x4f, 0x96, 0xef, 0x98, 0x56, 0x44, 0xc2, 0x0f, 0x63, 0x20, 0x19, 0x0b, 0x60, 0x28, 0x09, 0xb2, 0x3e, 0xe5, 0xe3, 0x91, 0xc2, 0x98, 0x3d, 0xc0, 0x81, 0x0b, 0x5a, 0xdd, 0x88, 0x6a, 0xc1, 0xff, 0x94, 0x7f, 0xe0, 0x96, 0x6b, 0x67, 0x75, 0x80, 0x53, 0xa1, 0x89, 0x14, 0x19, 0x59, 0xdc, 0x13, 0x67, 0x01, 0x7c, 0x64, 0xfe, 0xeb, 0x7b, 0x8c, 0x97, 0x2d, 0x1a, 0x90, 0x48, 0x4b, 0xea, 0x48, 0xc0, 0x77, 0x23, 0x68, 0x65, 0x19, 0xcf, 0xcf, 0x1c, 0x89, 0x93, 0xe0, 0xd2, 0xfd, 0x81, 0x6a, 0x6e, 0xd8, 0x76, 0xad, 0x65, 0xb5, 0xe0, 0xe1, 0xe2, 0x9c, 0x13, 0x70, 0x0e, 0x79, 0x1c, 0xaa, 0xac, 0x0d, 0x3f, 0x10, 0x4e, 0x47, 0x36, 0xb9, 0x23, 0xd3, 0x6a, 0x50, 0x9a, 0xe2, 0x83, 0x94, 0xf8, 0x1b, 0x41, 0x4c, 0x22, 0x92, 0x58, 0x9f, 0xc8, 0xad, 0x36, 0x51, 0x59, 0xa6, 0xbb, 0x86, 0x4f, 0x9d, 0x3a, 0x9f, 0x1d, 0x0b, 0x2e, 0x7f, 0xf8, 0x83, 0xfd, 0x1c, 0x3b, 0xe1, 0x3d, 0xb2, 0xdc, 0x13, 0x18, 0x71, 0xec, 0x63, 0xf3, 0xfc, 0x41, 0x6f, 0x14, 0xec, 0xcc, 0x7f, 0x28, 0xeb, 0x12, 0xc6, 0x4c, 0xa4, 0x92, 0x7f, 0x7a, 0x65, 0xcf, 0x8f, 0x63, 0x47, 0x3e, 0x4f, 0xeb, 0x03, 0x7b, 0x20, 0xf8, 0x01, 0xa2, 0x9d, 0xe2, 0x5f, 0x85, 0xfb, 0x7b, 0xdf, 0x10, 0x45, 0x2f, 0x6f, 0xb2, 0x6b, 0xff, 0x69, 0xf5, 0x64, 0x8e, 0x18, 0x71, 0x7a, 0x04, 0x31, 0xc3, 0xf8, 0xa0, 0x6c, 0x0f, 0x0a, 0x57, 0x83, 0x83, 0x58, 0xda, 0xaf, 0x99, 0xe6, 0x68, 0x13, 0xe8, 0x15, 0xbc, 0xd7, 0xef, 0xb2, 0x4b, 0x08, 0x18, 0x97, 0xb2, 0x77, 0x0c, 0xb5, 0x96, 0xdb, 0x21, 0x14, 0x39, 0x52, 0x9f, 0x83, 0x47, 0x96, 0xe8, 0x9f, 0x94, 0xe2, 0x73, 0x40, 0x02, 0x7f, 0xbd, 0xb9, 0x65, 0x6a, 0x33, 0x15, 0xb8, 0xc8, 0x9d, 0x12, 0xf9, 0x14, 0x04, 0x77, 0x56, 0xdc, 0x87, 0xd2, 0xca, 0xb2, 0x05, 0x99, 0xad, 0xa6, 0xd2, 0x81, 0x8f, 0x64, 0xcd, 0xe5, 0x70, 0x2c, 0xbf, 0xc0, 0xb6, 0xb7, 0xa8, 0x4a, 0x45, 0x6b, 0x98, 0x8f, 0x5b, 0xb8, 0x87, 0xf5, 0x64, 0xd1, 0x67, 0xd6, 0xdd, 0x76, 0x29, 0xf0, 0x77, 0x45, 0xfc, 0x27, 0xa4, 0x4a, 0xac, 0xaa, 0x1a, 0x90, 0xbe, 0xf8, 0x91, 0x50, 0x30, 0x6d, 0x73, 0x49, 0x3c, 0xab, 0xa4, 0xaf, 0x13, 0xa8, 0xdd, 0x0a, 0xf5, 0xc3, 0x34, 0x98, 0xb4, 0x7f, 0x0b, 0xb4, 0x63, 0x0f, 0xe3, 0x6e, 0xcc, 0xf8, 0x1d, 0xea, 0x34, 0x71, 0x8b, 0x06, 0xa5, 0x4f, 0x81, 0x12, 0xa9, 0xfd, 0xb8, 0x43 })] - [InlineData("-1500566381192798663042470094195709329888702572609999105286667163606153967917290138712408909178830809119008530236180974166477902167438722120032328817587204550920260039698718901932896233377293832747667996098291476468951412311792579258943277768740116090186686963715856483147820131067091322876669577393210366426487028489206389247040659375214497672166049911500383423054774768058254673393263777607084960848658501529675225559011863409579602879830226289200557853195239635009395081629845517655774307827048680743808664945667425540772434721298573889660136104342949269877806888346513652384111162522895043239369803590295673472600852282901495791087130835483730406094888840219829189061112151151001898468218215751327382511813082884657126285166508024920536549363279290734920537316417286759974845704859198588552892947264856714040130408613412473996518038227113385600353365608575770837750435553392852567153310861059766627383200108369176626042676222592985818614861742325706568951932845447397512345181981733524874445871904571909006536844113768514813826258460666950996534336842871477679076553532049073323784011247842133811527684859166963235747571306708361946012941167234981369225227878132777327321706825860067928644566542309248", new byte[] { 0xe2, 0xdb, 0xc3, 0xee, 0xdc, 0xd0, 0xa4, 0xdc, 0x41, 0xec, 0xf7, 0xf3, 0x53, 0x2f, 0xd9, 0x5e, 0xe5, 0xbf, 0x5e, 0xea, 0x84, 0xde, 0x00, 0x79, 0x48, 0xc6, 0xf4, 0xd0, 0x29, 0xd9, 0x41, 0xb3, 0xc1, 0x31, 0xe0, 0x18, 0x42, 0xa5, 0x76, 0x88, 0x95, 0x60, 0xe8, 0x55, 0x51, 0x98, 0x01, 0xdb, 0x58, 0x0f, 0x76, 0xe5, 0x23, 0xb3, 0xa3, 0x8b, 0xb6, 0x8b, 0x66, 0x30, 0xd2, 0xb4, 0x13, 0x44, 0xd7, 0xa1, 0x6f, 0xa1, 0xee, 0x41, 0xab, 0x87, 0x5b, 0x64, 0x53, 0x80, 0x1b, 0x1b, 0x15, 0xba, 0x7e, 0x19, 0xbd, 0xc5, 0x9e, 0xfa, 0x1e, 0x59, 0x19, 0x56, 0x59, 0x7e, 0xa3, 0x2d, 0x97, 0xc8, 0xd9, 0x9f, 0xd3, 0x9b, 0x43, 0x25, 0x31, 0x4b, 0x17, 0x5c, 0x5d, 0x95, 0xd2, 0x5a, 0x91, 0xca, 0x83, 0xe9, 0x16, 0x33, 0x10, 0x26, 0x65, 0x31, 0x79, 0xa3, 0xf7, 0x89, 0xd5, 0xe3, 0x8d, 0x45, 0x86, 0x2a, 0xc9, 0xd8, 0x40, 0x93, 0xd8, 0xbf, 0x6f, 0xfa, 0x13, 0xf5, 0x4a, 0x62, 0x15, 0xd9, 0x55, 0xd9, 0xf6, 0xcc, 0xc2, 0xdb, 0xbc, 0xce, 0x50, 0x7a, 0x45, 0xca, 0xca, 0x54, 0x20, 0x76, 0x8e, 0x26, 0x9a, 0x5d, 0x3b, 0x23, 0xad, 0x80, 0xa5, 0xae, 0x63, 0x27, 0x03, 0x10, 0x65, 0x06, 0x6e, 0x65, 0x38, 0x70, 0x10, 0xef, 0xfb, 0xbc, 0xcf, 0xf3, 0x3d, 0x0a, 0x40, 0xe7, 0xd3, 0x20, 0x5d, 0x4f, 0x84, 0xd8, 0xcb, 0xea, 0x65, 0x28, 0x26, 0x15, 0x54, 0x08, 0x77, 0x07, 0xd4, 0x21, 0xb4, 0x69, 0xc6, 0x70, 0x02, 0xd2, 0x5d, 0x4b, 0x7f, 0xf6, 0xb4, 0x11, 0x7d, 0x1b, 0x74, 0x59, 0x1f, 0x2d, 0x5d, 0x75, 0x5c, 0x1a, 0x6e, 0x78, 0xad, 0x12, 0x8d, 0x3b, 0x52, 0x0d, 0x4a, 0x9f, 0x28, 0x22, 0xc4, 0x36, 0xb3, 0xdf, 0xd5, 0xa3, 0xa3, 0xa7, 0x06, 0xea, 0x49, 0x16, 0x01, 0xc8, 0xb2, 0x27, 0xab, 0x04, 0xa2, 0x62, 0x93, 0xcb, 0xdc, 0xfe, 0x33, 0xe4, 0x31, 0x58, 0x7c, 0x08, 0x23, 0x4c, 0x88, 0x1e, 0x9f, 0xc9, 0x39, 0x46, 0xea, 0x7a, 0x69, 0xfa, 0xff, 0x38, 0x87, 0x6b, 0xde, 0x7c, 0x6b, 0xfa, 0x2f, 0x81, 0xff, 0xb1, 0x82, 0x34, 0x38, 0xb8, 0xd1, 0xbf, 0x68, 0x60, 0x07, 0x3d, 0x91, 0x4e, 0xb2, 0x02, 0x1a, 0x05, 0x70, 0xb7, 0x26, 0xbb, 0x95, 0xad, 0xfd, 0xcc, 0x52, 0x80, 0xf9, 0xda, 0x45, 0x04, 0x24, 0xc4, 0x8f, 0x46, 0x22, 0x9a, 0x0d, 0xa0, 0x88, 0x03, 0x54, 0x2d, 0x2f, 0x54, 0x1b, 0xf1, 0xe5, 0xfe, 0xa0, 0x6c, 0x70, 0x31, 0xb1, 0x36, 0x8b, 0xcf, 0x33, 0xf5, 0xc1, 0x77, 0x6c, 0x89, 0xa3, 0xb3, 0xd9, 0x66, 0x5d, 0xb8, 0x40, 0x66, 0xb3, 0x0d, 0xcd, 0x0c, 0xde, 0xd4, 0x6c, 0x55, 0x66, 0x95, 0x78, 0x7f, 0xc9, 0x0a, 0x8e, 0x41, 0x50, 0xc2, 0xe9, 0x88, 0x91, 0xce, 0x56, 0xa2, 0xc6, 0xc4, 0x87, 0xb0, 0x25, 0xc9, 0x74, 0xf6, 0x58, 0xbe, 0xde, 0xf9, 0xee, 0x37, 0x5c, 0xfe, 0x54, 0xc1, 0x68, 0x40, 0x64, 0x99, 0x66, 0x2e, 0x18, 0x6b, 0xa6, 0x0a, 0xfe, 0x13, 0xec, 0x1e, 0x6f, 0xf3, 0xa0, 0xc9, 0x17, 0x9b, 0x6e, 0x92, 0xf2, 0x42, 0xfb, 0xbd, 0xfb, 0x11, 0x53, 0x7c, 0xeb, 0xd4, 0xd2, 0x16, 0xaf, 0x20, 0x5e, 0x42, 0x09, 0xea, 0x92, 0x0b, 0xab, 0x94, 0xaa, 0xaf, 0x23, 0xda, 0xda, 0xe3, 0x40, 0xc1, 0x5a, 0xab, 0xc2, 0xdd, 0x8d, 0x76, 0x62, 0xb3, 0xd4, 0x13, 0xac, 0x0c, 0x06, 0xa9, 0x98, 0x27, 0xa8, 0x34, 0x94, 0xd6, 0x85, 0x99, 0x24, 0x7e, 0x8a, 0xf1, 0xf8, 0x6d, 0xef, 0x66, 0xf0, 0xe6, 0xc9, 0x2c, 0x4d, 0x1f, 0x3e, 0xfa, 0x28, 0x80 })] - public void FromStringTests(string str, byte[] expectedBigEndianBytes) + public void ToByteArray_FromStringTests(string str, byte[] expectedBigEndianBytes) { byte[] expectedBytes = new byte[expectedBigEndianBytes.Length]; for (var i = 0; i < expectedBigEndianBytes.Length; i++) diff --git a/src/System.Runtime.Numerics/tests/BigInteger/TryWriteBytes.cs b/src/System.Runtime.Numerics/tests/BigInteger/TryWriteBytes.cs new file mode 100644 index 000000000000..4c9e2315e02d --- /dev/null +++ b/src/System.Runtime.Numerics/tests/BigInteger/TryWriteBytes.cs @@ -0,0 +1,55 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using Xunit; + +namespace System.Numerics.Tests +{ + public partial class ExtractBytesMembersTests + { + [Theory] + [MemberData(nameof(FromIntTests_MemberData))] + public void TryWriteBytes_FromIntTests(int i, byte[] expectedBytes) => + ValidateGetByteCountAndTryWriteBytes(new BigInteger(i), expectedBytes); + + [Theory] + [MemberData(nameof(FromLongTests_MemberData))] + public void TryWriteBytes_FromLongTests(long l, byte[] expectedBytes) => + ValidateGetByteCountAndTryWriteBytes(new BigInteger(l), expectedBytes); + + [Theory] + public void TryWriteBytes_FromStringTests(string str, byte[] expectedBigEndianBytes) + { + byte[] expectedBytes = (byte[])expectedBigEndianBytes.Clone(); + Array.Reverse(expectedBytes); + ValidateGetByteCountAndTryWriteBytes(BigInteger.Parse(str), expectedBytes); + } + + private void ValidateGetByteCountAndTryWriteBytes(BigInteger bi, byte[] expectedBytes) + { + byte[] bytes = bi.ToByteArray(); + Assert.Equal(expectedBytes, bytes); + + int count = bi.GetByteCount(); + Assert.Equal(expectedBytes.Length, count); + + int bytesWritten; + for (int i = 0; i < 2; i++) + { + Span destination = i == 0 ? + new byte[expectedBytes.Length] : // make sure it works with a span just long enough + new byte[expectedBytes.Length + 1]; // make sure it also works with a longer span + + // Fails if the span is too small + Assert.False(bi.TryWriteBytes(destination.Slice(0, expectedBytes.Length - 1), out bytesWritten)); + Assert.Equal(0, bytesWritten); + + // Succeeds if the span is sufficiently large + Assert.True(bi.TryWriteBytes(destination, out bytesWritten)); + Assert.Equal(expectedBytes.Length, bytesWritten); + Assert.Equal(expectedBytes, destination.Slice(0, bytesWritten).ToArray()); + } + } + } +} diff --git a/src/System.Runtime.Numerics/tests/BigInteger/ctor.cs b/src/System.Runtime.Numerics/tests/BigInteger/ctor.cs index 9fe5c408ce58..d642efe456c2 100644 --- a/src/System.Runtime.Numerics/tests/BigInteger/ctor.cs +++ b/src/System.Runtime.Numerics/tests/BigInteger/ctor.cs @@ -6,7 +6,7 @@ namespace System.Numerics.Tests { - public class BigIntegerConstructorTest + public partial class BigIntegerConstructorTest { private static int s_samples = 10; private static Random s_random = new Random(100); @@ -953,6 +953,7 @@ private static void VerifyCtorByteArray(byte[] value, UInt64 expectedValue) VerifyCtorByteArray(value); } + static partial void VerifyCtorByteSpan(byte[] value); private static void VerifyCtorByteArray(byte[] value) { @@ -961,6 +962,7 @@ private static void VerifyCtorByteArray(byte[] value) bool isZero = MyBigIntImp.IsZero(value); bigInteger = new BigInteger(value); + VerifyCtorByteSpan(value); roundTrippedByteArray = bigInteger.ToByteArray(); diff --git a/src/System.Runtime.Numerics/tests/BigInteger/ctor.netcoreapp.cs b/src/System.Runtime.Numerics/tests/BigInteger/ctor.netcoreapp.cs new file mode 100644 index 000000000000..d11723b95353 --- /dev/null +++ b/src/System.Runtime.Numerics/tests/BigInteger/ctor.netcoreapp.cs @@ -0,0 +1,14 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using Xunit; + +namespace System.Numerics.Tests +{ + public partial class BigIntegerConstructorTest + { + static partial void VerifyCtorByteSpan(byte[] value) => + Assert.Equal(new BigInteger(value), new BigInteger(new ReadOnlySpan(value))); + } +} diff --git a/src/System.Runtime.Numerics/tests/BigInteger/parse.cs b/src/System.Runtime.Numerics/tests/BigInteger/parse.cs index c3d2a1781d99..4caf4203441e 100644 --- a/src/System.Runtime.Numerics/tests/BigInteger/parse.cs +++ b/src/System.Runtime.Numerics/tests/BigInteger/parse.cs @@ -9,7 +9,7 @@ namespace System.Numerics.Tests { - public class parseTest + public partial class parseTest { private readonly static int s_samples = 10; private readonly static Random s_random = new Random(100); @@ -403,6 +403,8 @@ private static void VerifyParseToString(string num1, NumberStyles ns, bool failu VerifyParseToString(num1, ns, failureNotExpected, Fix(num1.Trim(), ((ns & NumberStyles.AllowHexSpecifier) != 0), failureNotExpected)); } + static partial void VerifyParseSpanToString(string num1, NumberStyles ns, bool failureNotExpected, string expected); + private static void VerifyParseToString(string num1, NumberStyles ns, bool failureNotExpected, string expected) { BigInteger test; @@ -425,8 +427,15 @@ private static void VerifyParseToString(string num1, NumberStyles ns, bool failu } Assert.False(BigInteger.TryParse(num1, ns, null, out test), String.Format("Expected TryParse to fail on {0}", num1)); } + + if (num1 != null) + { + VerifyParseSpanToString(num1, ns, failureNotExpected, expected); + } } + static partial void VerifySimpleFormatParseSpan(string num1, NumberFormatInfo nfi, BigInteger expected, bool failureExpected); + private static void VerifySimpleFormatParse(string num1, NumberFormatInfo nfi, BigInteger expected, bool failureExpected = false) { BigInteger test; @@ -442,8 +451,15 @@ private static void VerifySimpleFormatParse(string num1, NumberFormatInfo nfi, B Assert.Throws(() => { BigInteger.Parse(num1, nfi); }); Assert.False(BigInteger.TryParse(num1, NumberStyles.Any, nfi, out test), String.Format("Expected TryParse to fail on {0}", num1)); } + + if (num1 != null) + { + VerifySimpleFormatParseSpan(num1, nfi, expected, failureExpected); + } } - + + static partial void VerifyFormatParseSpan(string s, NumberStyles ns, NumberFormatInfo nfi, BigInteger expected, bool failureExpected); + private static void VerifyFormatParse(string num1, NumberStyles ns, NumberFormatInfo nfi, BigInteger expected, bool failureExpected = false) { BigInteger test; @@ -459,6 +475,11 @@ private static void VerifyFormatParse(string num1, NumberStyles ns, NumberFormat Assert.Throws(() => { BigInteger.Parse(num1, ns, nfi); }); Assert.False(BigInteger.TryParse(num1, ns, nfi, out test), String.Format("Expected TryParse to fail on {0}", num1)); } + + if (num1 != null) + { + VerifyFormatParseSpan(num1, ns, nfi, expected, failureExpected); + } } private static String GetDigitSequence(int min, int max, Random random) diff --git a/src/System.Runtime.Numerics/tests/BigInteger/parse.netcoreapp.cs b/src/System.Runtime.Numerics/tests/BigInteger/parse.netcoreapp.cs new file mode 100644 index 000000000000..fc3d966713ef --- /dev/null +++ b/src/System.Runtime.Numerics/tests/BigInteger/parse.netcoreapp.cs @@ -0,0 +1,59 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.Collections.Generic; +using System.Globalization; +using System.Threading; +using Xunit; + +namespace System.Numerics.Tests +{ + public partial class parseTest + { + static partial void VerifyParseSpanToString(string num1, NumberStyles ns, bool failureNotExpected, string expected) + { + if (failureNotExpected) + { + Eval(BigInteger.Parse(num1.AsReadOnlySpan(), ns), expected); + Assert.True(BigInteger.TryParse(num1.AsReadOnlySpan(), out BigInteger test, ns)); + Eval(test, expected); + } + else + { + Assert.Throws(() => { BigInteger.Parse(num1.AsReadOnlySpan(), ns); }); + Assert.False(BigInteger.TryParse(num1.AsReadOnlySpan(), out BigInteger test, ns), String.Format("Expected TryParse to fail on {0}", num1)); + } + } + + static partial void VerifySimpleFormatParseSpan(string num1, NumberFormatInfo nfi, BigInteger expected, bool failureExpected) + { + if (!failureExpected) + { + Assert.Equal(expected, BigInteger.Parse(num1.AsReadOnlySpan(), provider: nfi)); + Assert.True(BigInteger.TryParse(num1.AsReadOnlySpan(), out BigInteger test, NumberStyles.Any, nfi)); + Assert.Equal(expected, test); + } + else + { + Assert.Throws(() => { BigInteger.Parse(num1.AsReadOnlySpan(), provider: nfi); }); + Assert.False(BigInteger.TryParse(num1.AsReadOnlySpan(), out BigInteger test, NumberStyles.Any, nfi), String.Format("Expected TryParse to fail on {0}", num1)); + } + } + + static partial void VerifyFormatParseSpan(string num1, NumberStyles ns, NumberFormatInfo nfi, BigInteger expected, bool failureExpected) + { + if (!failureExpected) + { + Assert.Equal(expected, BigInteger.Parse(num1.AsReadOnlySpan(), ns, nfi)); + Assert.True(BigInteger.TryParse(num1.AsReadOnlySpan(), out BigInteger test, NumberStyles.Any, nfi)); + Assert.Equal(expected, test); + } + else + { + Assert.Throws(() => { BigInteger.Parse(num1.AsReadOnlySpan(), ns, nfi); }); + Assert.False(BigInteger.TryParse(num1.AsReadOnlySpan(), out BigInteger test, ns, nfi), String.Format("Expected TryParse to fail on {0}", num1)); + } + } + } +} diff --git a/src/System.Runtime.Numerics/tests/Configurations.props b/src/System.Runtime.Numerics/tests/Configurations.props index 78953dfc8851..271a4be4c93c 100644 --- a/src/System.Runtime.Numerics/tests/Configurations.props +++ b/src/System.Runtime.Numerics/tests/Configurations.props @@ -3,6 +3,7 @@ netstandard; + netcoreapp; diff --git a/src/System.Runtime.Numerics/tests/System.Runtime.Numerics.Tests.csproj b/src/System.Runtime.Numerics/tests/System.Runtime.Numerics.Tests.csproj index 3e90f7e24ef6..248a18b06d1b 100644 --- a/src/System.Runtime.Numerics/tests/System.Runtime.Numerics.Tests.csproj +++ b/src/System.Runtime.Numerics/tests/System.Runtime.Numerics.Tests.csproj @@ -7,6 +7,8 @@ + + @@ -17,6 +19,7 @@ + @@ -45,6 +48,7 @@ + @@ -52,10 +56,11 @@ + Common\System\PlatformDetection.cs - + \ No newline at end of file