From 11031c4171b5a46eedcae777fe805e7d29a94411 Mon Sep 17 00:00:00 2001 From: kzrnm Date: Thu, 5 Dec 2024 04:03:05 +0900 Subject: [PATCH] Avoid an allocation in BigInteger.Parse("-2147483648") (#104666) Co-authored-by: Dan Moseley --- .../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 b3355ff68678c..3832028c2dd4a 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 c8adf62e278e0..97e3d7cd3bdb1 100644 --- a/src/libraries/System.Runtime.Numerics/tests/BigInteger/parse.cs +++ b/src/libraries/System.Runtime.Numerics/tests/BigInteger/parse.cs @@ -233,10 +233,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++)