// 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; using System.Diagnostics.CodeAnalysis; namespace Microsoft.CodeAnalysis.Shared.Utilities; internal static class IntegerUtilities { public static int CountOfBitsSet(long v) { // http://graphics.stanford.edu/~seander/bithacks.htm var c = 0; while (v != 0) { // clear the least significant bit set v &= unchecked(v - 1); c++; } return c; } public static bool HasOneBitSet(IComparable value) { switch (value) { case long v: return HasOneBitSet(v); case ulong v: return HasOneBitSet(unchecked((long)v)); case int v: return HasOneBitSet(v); case uint v: return HasOneBitSet(v); case short v: return HasOneBitSet(v); case ushort v: return HasOneBitSet(v); case sbyte v: return HasOneBitSet(v); case byte v: return HasOneBitSet(v); default: return false; } } public static bool HasOneBitSet(long v) => CountOfBitsSet(v) == 1; public static int LogBase2(long v) { var log = 0; while ((v >>= 1) != 0) { log++; } return log; } /// <summary> /// Helper as VB's CType doesn't work without arithmetic overflow. /// </summary> public static long Convert(long v, SpecialType type) => type switch { SpecialType.System_SByte => unchecked((sbyte)v), SpecialType.System_Byte => unchecked((byte)v), SpecialType.System_Int16 => unchecked((short)v), SpecialType.System_UInt16 => unchecked((ushort)v), SpecialType.System_Int32 => unchecked((int)v), SpecialType.System_UInt32 => unchecked((uint)v), _ => v, }; public static ulong ToUnsigned(long v) => unchecked((ulong)v); public static ulong ToUInt64(object? o) => o is ulong ? (ulong)o : unchecked((ulong)System.Convert.ToInt64(o)); public static long ToInt64(object? o) => o is ulong ul ? unchecked((long)ul) : System.Convert.ToInt64(o); public static bool IsIntegral([NotNullWhen(true)] object? value) => value switch { sbyte _ => true, byte _ => true, short _ => true, ushort _ => true, int _ => true, uint _ => true, long _ => true, ulong _ => true, _ => false, }; } |