Imported Upstream version 5.10.0.47

Former-commit-id: d0813289fa2d35e1f8ed77530acb4fb1df441bc0
This commit is contained in:
Xamarin Public Jenkins (auto-signing)
2018-01-24 17:04:36 +00:00
parent 88ff76fe28
commit e46a49ecf1
5927 changed files with 226314 additions and 129848 deletions

View File

@@ -7,6 +7,11 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "System.Runtime.Numerics.Tes
{D2C99D27-0BEF-4319-ADB3-05CBEBA8F69B} = {D2C99D27-0BEF-4319-ADB3-05CBEBA8F69B}
EndProjectSection
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "System.Runtime.Numerics.Performance.Tests", "tests\Performance\System.Runtime.Numerics.Performance.Tests.csproj", "{3842BE38-1A99-41B2-81B5-186E64077B95}"
ProjectSection(ProjectDependencies) = postProject
{D2C99D27-0BEF-4319-ADB3-05CBEBA8F69B} = {D2C99D27-0BEF-4319-ADB3-05CBEBA8F69B}
EndProjectSection
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "System.Runtime.Numerics", "src\System.Runtime.Numerics.csproj", "{D2C99D27-0BEF-4319-ADB3-05CBEBA8F69B}"
ProjectSection(ProjectDependencies) = postProject
{7D5CBF2F-337C-4AEB-B035-A17D33A9BC1F} = {7D5CBF2F-337C-4AEB-B035-A17D33A9BC1F}
@@ -26,10 +31,14 @@ Global
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{28AE24F8-BEF4-4358-B612-ADD9D587C8E1}.Debug|Any CPU.ActiveCfg = netstandard-Debug|Any CPU
{28AE24F8-BEF4-4358-B612-ADD9D587C8E1}.Debug|Any CPU.Build.0 = netstandard-Debug|Any CPU
{28AE24F8-BEF4-4358-B612-ADD9D587C8E1}.Release|Any CPU.ActiveCfg = netstandard-Release|Any CPU
{28AE24F8-BEF4-4358-B612-ADD9D587C8E1}.Release|Any CPU.Build.0 = netstandard-Release|Any CPU
{28AE24F8-BEF4-4358-B612-ADD9D587C8E1}.Debug|Any CPU.ActiveCfg = netcoreapp-Debug|Any CPU
{28AE24F8-BEF4-4358-B612-ADD9D587C8E1}.Debug|Any CPU.Build.0 = netcoreapp-Debug|Any CPU
{28AE24F8-BEF4-4358-B612-ADD9D587C8E1}.Release|Any CPU.ActiveCfg = netcoreapp-Release|Any CPU
{28AE24F8-BEF4-4358-B612-ADD9D587C8E1}.Release|Any CPU.Build.0 = netcoreapp-Release|Any CPU
{3842BE38-1A99-41B2-81B5-186E64077B95}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{3842BE38-1A99-41B2-81B5-186E64077B95}.Debug|Any CPU.Build.0 = Debug|Any CPU
{3842BE38-1A99-41B2-81B5-186E64077B95}.Release|Any CPU.ActiveCfg = Release|Any CPU
{3842BE38-1A99-41B2-81B5-186E64077B95}.Release|Any CPU.Build.0 = Release|Any CPU
{D2C99D27-0BEF-4319-ADB3-05CBEBA8F69B}.Debug|Any CPU.ActiveCfg = netcoreapp-Debug|Any CPU
{D2C99D27-0BEF-4319-ADB3-05CBEBA8F69B}.Debug|Any CPU.Build.0 = netcoreapp-Debug|Any CPU
{D2C99D27-0BEF-4319-ADB3-05CBEBA8F69B}.Release|Any CPU.ActiveCfg = netcoreapp-Release|Any CPU
@@ -44,6 +53,7 @@ Global
EndGlobalSection
GlobalSection(NestedProjects) = preSolution
{28AE24F8-BEF4-4358-B612-ADD9D587C8E1} = {1A2F9F4A-A032-433E-B914-ADD5992BB178}
{3842BE38-1A99-41B2-81B5-186E64077B95} = {1A2F9F4A-A032-433E-B914-ADD5992BB178}
{D2C99D27-0BEF-4319-ADB3-05CBEBA8F69B} = {E107E9C1-E893-4E87-987E-04EF0DCEAEFD}
{7D5CBF2F-337C-4AEB-B035-A17D33A9BC1F} = {2E666815-2EDB-464B-9DF6-380BF4789AD4}
EndGlobalSection

View File

@@ -13,6 +13,7 @@ namespace System.Numerics
{
[System.CLSCompliantAttribute(false)]
public BigInteger(byte[] value) { throw null; }
public BigInteger(System.ReadOnlySpan<byte> 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 @@ namespace System.Numerics
[System.CLSCompliantAttribute(false)]
public bool Equals(ulong other) { throw null; }
public override int GetHashCode() { throw null; }
public int GetByteCount() { throw null; }
public static System.Numerics.BigInteger GreatestCommonDivisor(System.Numerics.BigInteger left, System.Numerics.BigInteger right) { throw null; }
public static double Log(System.Numerics.BigInteger value) { throw null; }
public static double Log(System.Numerics.BigInteger value, double baseValue) { throw null; }
@@ -146,6 +148,7 @@ namespace System.Numerics
public static System.Numerics.BigInteger Parse(string value, System.Globalization.NumberStyles style) { throw null; }
public static System.Numerics.BigInteger Parse(string value, System.Globalization.NumberStyles style, System.IFormatProvider provider) { throw null; }
public static System.Numerics.BigInteger Parse(string value, System.IFormatProvider provider) { throw null; }
public static System.Numerics.BigInteger Parse(System.ReadOnlySpan<char> 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 @@ namespace System.Numerics
public string ToString(string format, System.IFormatProvider provider) { throw null; }
public static bool TryParse(string value, System.Globalization.NumberStyles style, System.IFormatProvider provider, out System.Numerics.BigInteger result) { throw null; }
public static bool TryParse(string value, out System.Numerics.BigInteger result) { throw null; }
public static bool TryParse(ReadOnlySpan<char> 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<byte> destination, out int bytesWritten) { throw null; }
}
[System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential)]
public partial struct Complex : System.IEquatable<System.Numerics.Complex>, System.IFormattable

View File

@@ -33,7 +33,7 @@ namespace System.Globalization
[SecurityCritical]
internal static bool TryStringToBigInteger(
string s,
ReadOnlySpan<char> s,
NumberStyles styles,
NumberFormatInfo numberFormatInfo,
StringBuilder receiver, // Receives the decimal digits

View File

@@ -135,10 +135,17 @@ namespace System.Numerics
public BigInteger(double value)
{
if (double.IsInfinity(value))
throw new OverflowException(SR.Overflow_BigIntInfinity);
if (double.IsNaN(value))
throw new OverflowException(SR.Overflow_NotANumber);
if (!double.IsFinite(value))
{
if (double.IsInfinity(value))
{
throw new OverflowException(SR.Overflow_BigIntInfinity);
}
else // NaN
{
throw new OverflowException(SR.Overflow_NotANumber);
}
}
Contract.EndContractBlock();
_sign = 0;
@@ -246,17 +253,32 @@ namespace System.Numerics
/// </summary>
/// <param name="value"></param>
[CLSCompliant(false)]
public BigInteger(byte[] value)
public BigInteger(byte[] value) :
this(new ReadOnlySpan<byte>(value ?? throw new ArgumentNullException(nameof(value))))
{
if (value == null)
throw new ArgumentNullException(nameof(value));
Contract.EndContractBlock();
}
public BigInteger(ReadOnlySpan<byte> value)
{
int byteCount = value.Length;
bool isNegative = byteCount > 0 && ((value[byteCount - 1] & 0x80) == 0x80);
// Try to conserve space as much as possible by checking for wasted leading byte[] entries
while (byteCount > 0 && value[byteCount - 1] == 0) byteCount--;
bool isNegative;
if (byteCount > 0)
{
byte lastByte = value[byteCount - 1];
isNegative = (lastByte & 0x80) != 0;
if (lastByte == 0)
{
// Try to conserve space as much as possible by checking for wasted leading byte[] entries
byteCount -= 2;
while (byteCount >= 0 && value[byteCount] == 0) byteCount--;
byteCount++;
}
}
else
{
isNegative = false;
}
if (byteCount == 0)
{
@@ -269,50 +291,42 @@ namespace System.Numerics
if (byteCount <= 4)
{
if (isNegative)
_sign = unchecked((int)0xffffffff);
else
_sign = 0;
_sign = isNegative ? unchecked((int)0xffffffff) : 0;
for (int i = byteCount - 1; i >= 0; i--)
{
_sign <<= 8;
_sign |= value[i];
_sign = (_sign << 8) | value[i];
}
_bits = null;
_bits = null;
if (_sign < 0 && !isNegative)
{
// Int32 overflow
// Example: Int64 value 2362232011 (0xCB, 0xCC, 0xCC, 0x8C, 0x0)
// can be naively packed into 4 bytes (due to the leading 0x0)
// it overflows into the int32 sign bit
_bits = new uint[1];
_bits[0] = unchecked((uint)_sign);
_bits = new uint[1] { unchecked((uint)_sign) };
_sign = +1;
}
if (_sign == int.MinValue)
{
this = s_bnMinInt;
}
}
else
{
int unalignedBytes = byteCount % 4;
int dwordCount = byteCount / 4 + (unalignedBytes == 0 ? 0 : 1);
bool isZero = true;
uint[] val = new uint[dwordCount];
// Copy all dwords, except but don't do the last one if it's not a full four bytes
int curDword, curByte, byteInDword;
curByte = 3;
int curDword, curByte = 3;
for (curDword = 0; curDword < dwordCount - (unalignedBytes == 0 ? 0 : 1); curDword++)
{
byteInDword = 0;
while (byteInDword < 4)
for (int byteInDword = 0; byteInDword < 4; byteInDword++)
{
if (value[curByte] != 0x00) isZero = false;
val[curDword] <<= 8;
val[curDword] |= value[curByte];
byte curByteValue = value[curByte];
val[curDword] = (val[curDword] << 8) | curByteValue;
curByte--;
byteInDword++;
}
curByte += 8;
}
@@ -323,41 +337,46 @@ namespace System.Numerics
if (isNegative) val[dwordCount - 1] = 0xffffffff;
for (curByte = byteCount - 1; curByte >= byteCount - unalignedBytes; curByte--)
{
if (value[curByte] != 0x00) isZero = false;
val[curDword] <<= 8;
val[curDword] |= value[curByte];
byte curByteValue = value[curByte];
val[curDword] = (val[curDword] << 8) | curByteValue;
}
}
if (isZero)
{
this = s_bnZeroInt;
}
else if (isNegative)
if (isNegative)
{
NumericsHelpers.DangerousMakeTwosComplement(val); // Mutates val
// Pack _bits to remove any wasted space after the twos complement
int len = val.Length;
while (len > 0 && val[len - 1] == 0)
len--;
if (len == 1 && unchecked((int)(val[0])) > 0)
int len = val.Length - 1;
while (len >= 0 && val[len] == 0) len--;
len++;
if (len == 1)
{
if (val[0] == 1 /* abs(-1) */)
switch (val[0])
{
this = s_bnMinusOneInt;
}
else if (val[0] == kuMaskHighBit /* abs(Int32.MinValue) */)
{
this = s_bnMinInt;
}
else
{
_sign = (-1) * ((int)val[0]);
_bits = null;
case 1: // abs(-1)
this = s_bnMinusOneInt;
return;
case kuMaskHighBit: // abs(Int32.MinValue)
this = s_bnMinInt;
return;
default:
if (unchecked((int)val[0]) > 0)
{
_sign = (-1) * ((int)val[0]);
_bits = null;
AssertValid();
return;
}
break;
}
}
else if (len != val.Length)
if (len != val.Length)
{
_sign = -1;
_bits = new uint[len];
@@ -600,6 +619,16 @@ namespace System.Numerics
return BigNumber.TryParseBigInteger(value, style, NumberFormatInfo.GetInstance(provider), out result);
}
public static BigInteger Parse(ReadOnlySpan<char> value, NumberStyles style = NumberStyles.Integer, IFormatProvider provider = null)
{
return BigNumber.ParseBigInteger(value, style, NumberFormatInfo.GetInstance(provider));
}
public static bool TryParse(ReadOnlySpan<char> 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);
@@ -1019,10 +1048,76 @@ namespace System.Numerics
/// <returns></returns>
public byte[] ToByteArray()
{
int ignored = 0;
return TryGetBytes(GetBytesMode.AllocateArray, default(Span<byte>), ref ignored);
}
/// <summary>
/// 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.
/// </summary>
/// <param name="destination">The destination span to which the resulting bytes should be written.</param>
/// <param name="bytesWritten">The number of bytes written to <paramref name="destination"/>.</param>
/// <returns>true if the bytes fit in <see cref="destination"/>; false if not all bytes could be written due to lack of space.</returns>
public bool TryWriteBytes(Span<byte> destination, out int bytesWritten)
{
bytesWritten = 0;
return TryGetBytes(GetBytesMode.Span, destination, ref bytesWritten) != null;
}
/// <summary>Gets the number of bytes that will be output by <see cref="ToByteArray"/> and <see cref="TryWriteBytes(Span{byte}, out int)"/>.</summary>
/// <returns>The number of bytes.</returns>
public int GetByteCount()
{
int count = 0;
TryGetBytes(GetBytesMode.Count, default(Span<byte>), ref count);
return count;
}
/// <summary>Mode used to enable sharing <see cref="TryGetBytes(GetBytesMode, Span{byte}, out byte[], out int)"/> for multiple purposes.</summary>
private enum GetBytesMode { AllocateArray, Count, Span }
/// <summary>Dummy array returned from TryGetBytes to indicate success when in span mode.</summary>
private static readonly byte[] s_success = Array.Empty<byte>();
/// <summary>Shared logic for <see cref="ToByteArray"/>, <see cref="TryWriteBytes(Span{byte}, out int)"/>, and <see cref="GetByteCount"/>.</summary>
/// <param name="mode">Which entry point is being used.</param>
/// <param name="destination">The destination span, if mode is <see cref="GetBytesMode.Span"/>.</param>
/// <param name="bytesWritten">
/// If <paramref name="mode"/>==<see cref="GetBytesMode.AllocateArray"/>, ignored.
/// If <paramref name="mode"/>==<see cref="GetBytesMode.Count"/>, the number of bytes that would be written.
/// If <paramref name="mode"/>==<see cref="GetBytesMode.Span"/>, the number of bytes written to the span.
/// </param>
/// <returns>
/// If <paramref name="mode"/>==<see cref="GetBytesMode.AllocateArray"/>, the result array.
/// If <paramref name="mode"/>==<see cref="GetBytesMode.Count"/>, null.
/// If <paramref name="mode"/>==<see cref="GetBytesMode.Span"/>, non-null if the span was long enough, null if there wasn't enough room.
/// </returns>
private byte[] TryGetBytes(GetBytesMode mode, Span<byte> destination, ref 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.");
int sign = _sign;
if (sign == 0)
{
return new byte[] { 0 };
switch (mode)
{
case GetBytesMode.AllocateArray:
return new byte[] { 0 };
case GetBytesMode.Count:
bytesWritten = 1;
return null;
default: // case GetBytesMode.Span:
if (destination.Length != 0)
{
destination[0] = 0;
bytesWritten = 1;
return s_success;
}
return null;
}
}
byte highByte;
@@ -1091,20 +1186,38 @@ namespace System.Numerics
// Ensure high bit is 0 if positive, 1 if negative
bool needExtraByte = (msb & 0x80) != (highByte & 0x80);
byte[] bytes;
int curByte = 0;
if (bits == null)
int length = msbIndex + 1 + (needExtraByte ? 1 : 0);
if (bits != null)
{
bytes = new byte[msbIndex + 1 + (needExtraByte ? 1 : 0)];
Debug.Assert(bytes.Length <= 4);
length = checked(4 * (bits.Length - 1) + length);
}
else
{
bytes = new byte[checked(4 * (bits.Length - 1) + msbIndex + 1 + (needExtraByte ? 1 : 0))];
byte[] array;
switch (mode)
{
case GetBytesMode.AllocateArray:
destination = array = new byte[length];
break;
case GetBytesMode.Count:
bytesWritten = length;
return null;
default: // case GetBytesMode.Span:
if (destination.Length < length)
{
return null;
}
bytesWritten = length;
array = s_success;
break;
}
int curByte = 0;
if (bits != null)
{
for (int i = 0; i < bits.Length - 1; i++)
{
uint dword = bits[i];
if (sign == -1)
{
dword = ~dword;
@@ -1113,23 +1226,36 @@ namespace System.Numerics
dword = unchecked(dword + 1U);
}
}
for (int j = 0; j < 4; j++)
destination[curByte++] = unchecked((byte)dword);
destination[curByte++] = unchecked((byte)(dword >> 8));
destination[curByte++] = unchecked((byte)(dword >> 16));
destination[curByte++] = unchecked((byte)(dword >> 24));
}
}
Debug.Assert(msbIndex >= 0 && msbIndex <= 3);
destination[curByte] = unchecked((byte)highDword);
if (msbIndex != 0)
{
destination[++curByte] = unchecked((byte)(highDword >> 8));
if (msbIndex != 1)
{
destination[++curByte] = unchecked((byte)(highDword >> 16));
if (msbIndex != 2)
{
bytes[curByte++] = unchecked((byte)dword);
dword >>= 8;
destination[++curByte] = unchecked((byte)(highDword >> 24));
}
}
}
for (int j = 0; j <= msbIndex; j++)
{
bytes[curByte++] = unchecked((byte)highDword);
highDword >>= 8;
}
Debug.Assert((!needExtraByte && curByte == length - 1) || (needExtraByte && curByte == length - 2));
if (needExtraByte)
{
bytes[bytes.Length - 1] = highByte;
destination[length - 1] = highByte;
}
return bytes;
return array;
}
/// <summary>

View File

@@ -324,6 +324,18 @@ namespace System.Numerics
[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<char> value, NumberStyles style, NumberFormatInfo info, out BigInteger result)
{
unsafe
{
@@ -357,8 +369,26 @@ namespace System.Numerics
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<char> AsReadOnlySpan(string s)
{
fixed (char* c = s)
{
return new ReadOnlySpan<char>(c, s.Length);
}
}
internal static BigInteger ParseBigInteger(ReadOnlySpan<char> value, NumberStyles style, NumberFormatInfo info)
{
ArgumentException e;
if (!TryValidateParseStyleInteger(style, out e))
throw e;

File diff suppressed because one or more lines are too long

View File

@@ -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]
[MemberData(nameof(FromStringTests_MemberData))]
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);
Validate(new byte[expectedBytes.Length]); // make sure it works with a span just long enough
Validate(new byte[expectedBytes.Length + 1]); // make sure it also works with a longer span
void Validate(Span<byte> destination)
{
// Fails if the span is too small
int bytesWritten;
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<byte>(expectedBytes, destination.Slice(0, bytesWritten).ToArray());
}
}
}
}

View File

@@ -6,7 +6,7 @@ using Xunit;
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);
@@ -891,6 +891,10 @@ namespace System.Numerics.Tests
// ctor(byte[]): array is UInt32.MaxValue + 1
VerifyCtorByteArray(new byte[] { 0, 0, 0, 0, 1 }, (UInt64)UInt32.MaxValue + 1);
// ctor(byte[]): array is Int32.MinValue with overlong representation.
VerifyCtorByteArray(new byte[] {0, 0, 0, 0x80, 0xFF});
Assert.Equal(new BigInteger(new byte[] { 0, 0, 0, 0x80, 0xFF, 0xFF, 0xFF }), int.MinValue);
// ctor(byte[]): array is UInt64.MaxValue
VerifyCtorByteArray(new byte[] { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0 }, UInt64.MaxValue);
@@ -953,6 +957,7 @@ namespace System.Numerics.Tests
VerifyCtorByteArray(value);
}
static partial void VerifyCtorByteSpan(byte[] value);
private static void VerifyCtorByteArray(byte[] value)
{
@@ -961,6 +966,7 @@ namespace System.Numerics.Tests
bool isZero = MyBigIntImp.IsZero(value);
bigInteger = new BigInteger(value);
VerifyCtorByteSpan(value);
roundTrippedByteArray = bigInteger.ToByteArray();

View File

@@ -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<byte>(value)));
}
}

View File

@@ -9,7 +9,7 @@ using Xunit;
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 @@ namespace System.Numerics.Tests
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 @@ namespace System.Numerics.Tests
}
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 @@ namespace System.Numerics.Tests
Assert.Throws<FormatException>(() => { 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 @@ namespace System.Numerics.Tests
Assert.Throws<FormatException>(() => { 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)

View File

@@ -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<FormatException>(() => { 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<FormatException>(() => { 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<FormatException>(() => { 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));
}
}
}
}

View File

@@ -3,6 +3,7 @@
<PropertyGroup>
<BuildConfigurations>
netstandard;
netcoreapp;
</BuildConfigurations>
</PropertyGroup>
</Project>

View File

@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<BuildConfigurations>
netcoreapp;
</BuildConfigurations>
</PropertyGroup>
</Project>

View File

@@ -0,0 +1,72 @@
// 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.Linq;
using Microsoft.Xunit.Performance;
using Xunit;
namespace System.Numerics.Tests
{
public partial class Perf_BigInteger
{
public static IEnumerable<object[]> NumberStrings()
{
yield return new object[] { "123" };
yield return new object[] { int.MinValue.ToString() };
yield return new object[] { string.Concat(Enumerable.Repeat("1234567890", 20)) };
}
// TODO #18249: Port disabled perf tests from tests\BigInteger\PerformanceTests.cs
[Benchmark]
[MemberData(nameof(NumberStrings))]
public void Ctor_ByteArray(string numberString)
{
byte[] input = BigInteger.Parse(numberString).ToByteArray();
foreach (var iteration in Benchmark.Iterations)
{
using (iteration.StartMeasurement())
{
for (int i = 0; i < 1000000; i++)
{
var bi = new BigInteger(input);
}
}
}
}
[Benchmark]
[MemberData(nameof(NumberStrings))]
public void ToByteArray(string numberString)
{
BigInteger bi = BigInteger.Parse(numberString);
foreach (var iteration in Benchmark.Iterations)
{
using (iteration.StartMeasurement())
{
for (int i = 0; i < 1000000; i++)
{
bi.ToByteArray();
}
}
}
}
[Benchmark]
[MemberData(nameof(NumberStrings))]
public void Parse(string numberString)
{
foreach (var iteration in Benchmark.Iterations)
{
using (iteration.StartMeasurement())
{
for (int i = 0; i < 100000; i++)
{
BigInteger.Parse(numberString);
}
}
}
}
}
}

View File

@@ -0,0 +1,49 @@
// 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.Linq;
using Microsoft.Xunit.Performance;
using Xunit;
namespace System.Numerics.Tests
{
public partial class Perf_BigInteger
{
[Benchmark]
[MemberData(nameof(NumberStrings))]
public void Ctor_ByteSpan(string numberString)
{
Span<byte> input = BigInteger.Parse(numberString).ToByteArray();
foreach (var iteration in Benchmark.Iterations)
{
using (iteration.StartMeasurement())
{
for (int i = 0; i < 1000000; i++)
{
var bi = new BigInteger(input);
}
}
}
}
[Benchmark]
[MemberData(nameof(NumberStrings))]
public void TryWriteBytes(string numberString)
{
BigInteger bi = BigInteger.Parse(numberString);
Span<byte> destination = new byte[bi.GetByteCount()];
foreach (var iteration in Benchmark.Iterations)
{
using (iteration.StartMeasurement())
{
for (int i = 0; i < 1000000; i++)
{
bi.TryWriteBytes(destination, out int bytesWritten);
}
}
}
}
}
}

View File

@@ -0,0 +1,26 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.props))\dir.props" />
<PropertyGroup>
<IncludePerformanceTests>true</IncludePerformanceTests>
<ProjectGuid>{3842BE38-1A99-41B2-81B5-186E64077B95}</ProjectGuid>
<DisableTests Condition="'$(TargetGroup)' == 'uap' AND ('$(ArchGroup)' == 'arm' OR '$(ArchGroup)' == 'arm64')">true</DisableTests>
</PropertyGroup>
<!-- Default configurations to help VS understand the configurations -->
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' " />
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' " />
<ItemGroup Condition="'$(DisableTests)' != 'true'">
<Compile Include="Perf.BigInteger.cs" />
<Compile Include="Perf.BigInteger.netcoreapp.cs" Condition="'$(TargetGroup)' == 'netcoreapp'" />
<Compile Include="$(CommonTestPath)\System\PerfUtils.cs">
<Link>Common\System\PerfUtils.cs</Link>
</Compile>
</ItemGroup>
<ItemGroup Condition="'$(DisableTests)' != 'true'">
<ProjectReference Include="$(CommonPath)\..\perf\PerfRunner\PerfRunner.csproj">
<Project>{69e46a6f-9966-45a5-8945-2559fe337827}</Project>
<Name>PerfRunner</Name>
</ProjectReference>
</ItemGroup>
<Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
</Project>

View File

@@ -7,6 +7,8 @@
<!-- Default configurations to help VS understand the configurations -->
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'netstandard-Debug|AnyCPU'" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'netstandard-Release|AnyCPU'" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'netcoreapp-Debug|AnyCPU'" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'netcoreapp-Release|AnyCPU'" />
<ItemGroup>
<Compile Include="BigInteger\absolutevalue.cs" />
<Compile Include="BigInteger\BigIntegerToStringTests.cs" />
@@ -17,6 +19,7 @@
<Compile Include="BigInteger\cast_to.cs" />
<Compile Include="BigInteger\Comparison.cs" />
<Compile Include="BigInteger\ctor.cs" />
<Compile Include="BigInteger\ctor.netcoreapp.cs" Condition="'$(TargetGroup)' == 'netcoreapp'" />
<Compile Include="BigInteger\divide.cs" />
<Compile Include="BigInteger\divrem.cs" />
<Compile Include="BigInteger\Driver.cs" />
@@ -45,6 +48,7 @@
<Compile Include="BigInteger\op_rightshift.cs" />
<Compile Include="BigInteger\op_xor.cs" />
<Compile Include="BigInteger\parse.cs" />
<Compile Include="BigInteger\parse.netcoreapp.cs" Condition="'$(TargetGroup)' == 'netcoreapp'" />
<Compile Include="BigInteger\PerformanceTests.cs" />
<Compile Include="BigInteger\pow.cs" />
<Compile Include="BigInteger\properties.cs" />
@@ -52,10 +56,8 @@
<Compile Include="BigInteger\sign.cs" />
<Compile Include="BigInteger\stackcalculator.cs" />
<Compile Include="BigInteger\ToByteArray.cs" />
<Compile Include="BigInteger\TryWriteBytes.cs" Condition="'$(TargetGroup)' == 'netcoreapp'" />
<Compile Include="ComplexTests.cs" />
<Compile Include="$(CommonTestPath)\System\PlatformDetection.cs">
<Link>Common\System\PlatformDetection.cs</Link>
</Compile>
</ItemGroup>
<Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
</Project>
</Project>