Skip to content

Commit

Permalink
Avoid an allocation in BigInteger.Parse("-2147483648")
Browse files Browse the repository at this point in the history
  • Loading branch information
kzrnm committed Jul 10, 2024
1 parent 812cb93 commit e451786
Show file tree
Hide file tree
Showing 2 changed files with 59 additions and 5 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -511,16 +511,23 @@ internal BigInteger(ReadOnlySpan<uint> value, bool negative)
{
this = default;
}
else if (value.Length == 1 && value[0] < kuMaskHighBit)
else if (value.Length == 1)
{
// Values like (Int32.MaxValue+1) are stored as "0x80000000" and as such cannot be packed into _sign
_sign = negative ? -(int)value[0] : (int)value[0];
_bits = null;
if (_sign == int.MinValue)
if (value[0] < kuMaskHighBit)
{
_sign = negative ? -(int)value[0] : (int)value[0];
_bits = null;
}
else if (negative && value[0] == kuMaskHighBit)
{
// Although Int32.MinValue fits in _sign, we represent this case differently for negate
this = s_bnMinInt;
}
else
{
_sign = negative ? -1 : +1;
_bits = [value[0]];
}
}
else
{
Expand Down
47 changes: 47 additions & 0 deletions src/libraries/System.Runtime.Numerics/tests/BigInteger/parse.cs
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,53 @@ public static void Parse_EmptySubspan_Fails()
Assert.Equal(0, result);
}

[Fact]
public void Parse_Small()
{
BigInteger result;

Assert.True(BigInteger.TryParse("0", out result));
Assert.Equal(0, result);

Assert.True(BigInteger.TryParse("1", out result));
Assert.Equal(1, result);

Assert.True(BigInteger.TryParse("-1", out result));
Assert.Equal(-1, result);

Assert.True(BigInteger.TryParse("-2147483647", out result));
Assert.Equal(-2147483647, result);

Assert.True(BigInteger.TryParse("2147483647", out result));
Assert.Equal(2147483647, result);

Assert.True(BigInteger.TryParse("-2147483648", out result));
Assert.Equal(-2147483648, result);

Assert.True(BigInteger.TryParse("2147483648", out result));
Assert.Equal(2147483648, result);


Assert.True(BigInteger.TryParse("-9223372036854775807", out result));
Assert.Equal(-9223372036854775807, result);

Assert.True(BigInteger.TryParse("9223372036854775807", out result));
Assert.Equal(9223372036854775807, result);

Assert.True(BigInteger.TryParse("-9223372036854775808", out result));
Assert.Equal(-9223372036854775808, result);

Assert.True(BigInteger.TryParse("9223372036854775808", out result));
Assert.Equal(Int128.Parse("9223372036854775808"), result);


Assert.True(BigInteger.TryParse(Int128.MinValue.ToString(), out result));
Assert.Equal(Int128.MinValue, result);

Assert.True(BigInteger.TryParse(Int128.MaxValue.ToString(), out result));
Assert.Equal(Int128.MaxValue, result);
}

[Fact]
public void Parse_Hex32Bits()
{
Expand Down

0 comments on commit e451786

Please sign in to comment.