From e9364f2531073db16c484a3133ce6b6332ec5948 Mon Sep 17 00:00:00 2001 From: kzrnm Date: Wed, 10 Jul 2024 08:53:10 +0900 Subject: [PATCH] Avoid an allocation in BigInteger.Parse("-2147483648") --- .../src/System/Numerics/BigInteger.cs | 17 ++++++++++----- .../tests/BigInteger/parse.cs | 21 +++++++++++++++---- 2 files changed, 29 insertions(+), 9 deletions(-) diff --git a/src/libraries/System.Runtime.Numerics/src/System/Numerics/BigInteger.cs b/src/libraries/System.Runtime.Numerics/src/System/Numerics/BigInteger.cs index e4d8845dd05e8..d4e0144f1adbb 100644 --- a/src/libraries/System.Runtime.Numerics/src/System/Numerics/BigInteger.cs +++ b/src/libraries/System.Runtime.Numerics/src/System/Numerics/BigInteger.cs @@ -511,16 +511,23 @@ internal BigInteger(ReadOnlySpan 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 { diff --git a/src/libraries/System.Runtime.Numerics/tests/BigInteger/parse.cs b/src/libraries/System.Runtime.Numerics/tests/BigInteger/parse.cs index 85a2fcd182af7..c952dde2f339b 100644 --- a/src/libraries/System.Runtime.Numerics/tests/BigInteger/parse.cs +++ b/src/libraries/System.Runtime.Numerics/tests/BigInteger/parse.cs @@ -228,10 +228,23 @@ private static void VerifyDefaultParse(Random random) // BasicTests VerifyFailParseToString(null, typeof(ArgumentNullException)); VerifyFailParseToString(string.Empty, typeof(FormatException)); - VerifyParseToString("0"); - VerifyParseToString("000"); - VerifyParseToString("1"); - VerifyParseToString("001"); + + foreach (var value in new string[] + { + "0", + "000", + "1", + "001", + int.MaxValue.ToString(), + int.MinValue.ToString(), + long.MaxValue.ToString(), + long.MinValue.ToString(), + Int128.MaxValue.ToString(), + Int128.MinValue.ToString(), + }) + { + VerifyParseToString(value); + } // SimpleNumbers - Small for (int i = 0; i < s_samples; i++)