diff options
Diffstat (limited to 'src/System.Private.CoreLib/shared/System/Buffers/Text/FormattingHelpers.CountDigits.cs')
-rw-r--r-- | src/System.Private.CoreLib/shared/System/Buffers/Text/FormattingHelpers.CountDigits.cs | 161 |
1 files changed, 161 insertions, 0 deletions
diff --git a/src/System.Private.CoreLib/shared/System/Buffers/Text/FormattingHelpers.CountDigits.cs b/src/System.Private.CoreLib/shared/System/Buffers/Text/FormattingHelpers.CountDigits.cs new file mode 100644 index 000000000..b6140adba --- /dev/null +++ b/src/System.Private.CoreLib/shared/System/Buffers/Text/FormattingHelpers.CountDigits.cs @@ -0,0 +1,161 @@ +// 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.Diagnostics; +using System.Runtime.CompilerServices; + +namespace System.Buffers.Text +{ + internal static partial class FormattingHelpers + { + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static int CountDigits(ulong value) + { + int digits = 1; + uint part; + if (value >= 10000000) + { + if (value >= 100000000000000) + { + part = (uint)(value / 100000000000000); + digits += 14; + } + else + { + part = (uint)(value / 10000000); + digits += 7; + } + } + else + { + part = (uint)value; + } + + if (part < 10) + { + // no-op + } + else if (part < 100) + { + digits += 1; + } + else if (part < 1000) + { + digits += 2; + } + else if (part < 10000) + { + digits += 3; + } + else if (part < 100000) + { + digits += 4; + } + else if (part < 1000000) + { + digits += 5; + } + else + { + Debug.Assert(part < 10000000); + digits += 6; + } + + return digits; + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static int CountDigits(uint value) + { + int digits = 1; + if (value >= 100000) + { + value = value / 100000; + digits += 5; + } + + if (value < 10) + { + // no-op + } + else if (value < 100) + { + digits += 1; + } + else if (value < 1000) + { + digits += 2; + } + else if (value < 10000) + { + digits += 3; + } + else + { + Debug.Assert(value < 100000); + digits += 4; + } + + return digits; + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static int CountHexDigits(ulong value) + { + // TODO: When x86 intrinsic support comes online, experiment with implementing this using lzcnt. + // return 16 - (int)((uint)Lzcnt.LeadingZeroCount(value | 1) >> 3); + + int digits = 1; + + if (value > 0xFFFFFFFF) + { + digits += 8; + value >>= 0x20; + } + if (value > 0xFFFF) + { + digits += 4; + value >>= 0x10; + } + if (value > 0xFF) + { + digits += 2; + value >>= 0x8; + } + if (value > 0xF) + digits++; + + return digits; + } + + + // Counts the number of trailing '0' digits in a decimal number. + // e.g., value = 0 => retVal = 0, valueWithoutTrailingZeros = 0 + // value = 1234 => retVal = 0, valueWithoutTrailingZeros = 1234 + // value = 320900 => retVal = 2, valueWithoutTrailingZeros = 3209 + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static int CountDecimalTrailingZeros(uint value, out uint valueWithoutTrailingZeros) + { + int zeroCount = 0; + + if (value != 0) + { + while (true) + { + uint temp = value / 10; + if (value != (temp * 10)) + { + break; + } + + value = temp; + zeroCount++; + } + } + + valueWithoutTrailingZeros = value; + return zeroCount; + } + } +} |