diff options
author | Tanner Gooding <tagoo@outlook.com> | 2022-08-24 16:48:54 +0300 |
---|---|---|
committer | github-actions <github-actions@github.com> | 2022-08-25 02:10:22 +0300 |
commit | 995dbf788671385050a5bdb7a648fbd8f346a38e (patch) | |
tree | 6d9baa3e5eaeb921b5d1e2f513dc90064d10de73 | |
parent | 7fac450bbbaf05d694c4ee878815f864a47c4952 (diff) |
Fix FormattingHelpers.CountDigits(UInt128) and add more tests for Int128/UInt128.ToStringbackport/pr-74501-to-release/7.0
3 files changed, 33 insertions, 4 deletions
diff --git a/src/libraries/System.Private.CoreLib/src/System/Buffers/Text/FormattingHelpers.CountDigits.cs b/src/libraries/System.Private.CoreLib/src/System/Buffers/Text/FormattingHelpers.CountDigits.cs index fd6ce30c9e1..22eff2b8b16 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Buffers/Text/FormattingHelpers.CountDigits.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Buffers/Text/FormattingHelpers.CountDigits.cs @@ -14,22 +14,37 @@ namespace System.Buffers.Text { ulong upper = value.Upper; - if (upper < 5) + // 1e19 is 8AC7_2304_89E8_0000 + // 1e20 is 5_6BC7_5E2D_6310_0000 + // 1e21 is 36_35C9_ADC5_DEA0_0000 + + if (upper == 0) { + // We have less than 64-bits, so just return the lower count return CountDigits(value.Lower); } - int digits = 19; + // We have more than 1e19, so we have at least 20 digits + int digits = 20; if (upper > 5) { - digits++; + // ((2^128) - 1) / 1e20 < 34_02_823_669_209_384_635 which + // is 18.5318 digits, meaning the result definitely fits + // into 64-bits and we only need to add the lower digit count + value /= new UInt128(0x5, 0x6BC7_5E2D_6310_0000); // value /= 1e20 + Debug.Assert(value.Upper == 0); + digits += CountDigits(value.Lower); } - else if (value.Lower >= 0x6BC75E2D63100000) + else if ((upper == 5) && (value.Lower >= 0x6BC75E2D63100000)) { + // We're greater than 1e20, but definitely less than 1e21 + // so we have exactly 21 digits + digits++; + Debug.Assert(digits == 21); } return digits; diff --git a/src/libraries/System.Runtime/tests/System/Int128Tests.cs b/src/libraries/System.Runtime/tests/System/Int128Tests.cs index 15f1a39a023..036872f0ddc 100644 --- a/src/libraries/System.Runtime/tests/System/Int128Tests.cs +++ b/src/libraries/System.Runtime/tests/System/Int128Tests.cs @@ -116,6 +116,12 @@ namespace System.Tests yield return new object[] { (Int128)(-4567), defaultSpecifier, defaultFormat, "-4567" }; yield return new object[] { (Int128)0, defaultSpecifier, defaultFormat, "0" }; yield return new object[] { (Int128)4567, defaultSpecifier, defaultFormat, "4567" }; + yield return new object[] { new Int128(0x0000_0000_0000_0001, 0x0000_0000_0000_0003), defaultSpecifier, defaultFormat, "18446744073709551619" }; + yield return new object[] { new Int128(0x0000_0000_0000_0001, 0x0000_0000_0000_000A), defaultSpecifier, defaultFormat, "18446744073709551626" }; + yield return new object[] { new Int128(0x0000_0000_0000_0005, 0x0000_0000_0000_0001), defaultSpecifier, defaultFormat, "92233720368547758081" }; + yield return new object[] { new Int128(0x0000_0000_0000_0005, 0x6BC7_5E2D_6310_0000), defaultSpecifier, defaultFormat, "100000000000000000000" }; + yield return new object[] { new Int128(0x0000_0000_0000_0036, 0x35C9_ADC5_DEA0_0000), defaultSpecifier, defaultFormat, "1000000000000000000000" }; + yield return new object[] { new Int128(0x0013_4261_72C7_4D82, 0x2B87_8FE8_0000_0000), defaultSpecifier, defaultFormat, "100000000000000000000000000000000000" }; yield return new object[] { Int128.MaxValue, defaultSpecifier, defaultFormat, "170141183460469231731687303715884105727" }; } diff --git a/src/libraries/System.Runtime/tests/System/UInt128Tests.cs b/src/libraries/System.Runtime/tests/System/UInt128Tests.cs index a02f205e72f..a255a044496 100644 --- a/src/libraries/System.Runtime/tests/System/UInt128Tests.cs +++ b/src/libraries/System.Runtime/tests/System/UInt128Tests.cs @@ -101,6 +101,14 @@ namespace System.Tests { yield return new object[] { (UInt128)0, defaultSpecifier, defaultFormat, "0" }; yield return new object[] { (UInt128)4567, defaultSpecifier, defaultFormat, "4567" }; + yield return new object[] { new UInt128(0x0000_0000_0000_0001, 0x0000_0000_0000_0003), defaultSpecifier, defaultFormat, "18446744073709551619" }; + yield return new object[] { new UInt128(0x0000_0000_0000_0001, 0x0000_0000_0000_000A), defaultSpecifier, defaultFormat, "18446744073709551626" }; + yield return new object[] { new UInt128(0x0000_0000_0000_0005, 0x0000_0000_0000_0001), defaultSpecifier, defaultFormat, "92233720368547758081" }; + yield return new object[] { new UInt128(0x0000_0000_0000_0005, 0x6BC7_5E2D_6310_0000), defaultSpecifier, defaultFormat, "100000000000000000000" }; + yield return new object[] { new UInt128(0x0000_0000_0000_0036, 0x35C9_ADC5_DEA0_0000), defaultSpecifier, defaultFormat, "1000000000000000000000" }; + yield return new object[] { new UInt128(0x0013_4261_72C7_4D82, 0x2B87_8FE8_0000_0000), defaultSpecifier, defaultFormat, "100000000000000000000000000000000000" }; + yield return new object[] { new UInt128(0x7FFF_FFFF_FFFF_FFFF, 0xFFFF_FFFF_FFFF_FFFF), defaultSpecifier, defaultFormat, "170141183460469231731687303715884105727" }; + yield return new object[] { new UInt128(0x8000_0000_0000_0000, 0x0000_0000_0000_0000), defaultSpecifier, defaultFormat, "170141183460469231731687303715884105728" }; yield return new object[] { UInt128.MaxValue, defaultSpecifier, defaultFormat, "340282366920938463463374607431768211455" }; } |