File: Utilities\BitUtils.cs
Web Access
Project: src\src\Microsoft.ML.Core\Microsoft.ML.Core.csproj (Microsoft.ML.Core)
// 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.Runtime.CompilerServices;
using Microsoft.ML.Runtime;
 
namespace Microsoft.ML.Internal.Utilities
{
    internal static partial class Utils
    {
        private const int CbitUint = 32;
        private const int CbitUlong = 64;
 
        // Various bit/byte manipulation methods.
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public static ulong MakeUlong(uint uHi, uint uLo)
        {
            return ((ulong)uHi << CbitUint) | uLo;
        }
 
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public static uint GetLo(ulong uu)
        {
            return (uint)uu;
        }
 
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public static uint GetHi(ulong uu)
        {
            return (uint)(uu >> CbitUint);
        }
 
        public static uint Abs(int a)
        {
            uint mask = (uint)(a >> 31);
            return ((uint)a ^ mask) - mask;
        }
 
        public static ulong Abs(long a)
        {
            ulong mask = (ulong)(a >> 63);
            return ((ulong)a ^ mask) - mask;
        }
 
        public static int CbitHighZero(uint u)
        {
            if (u == 0)
                return 32;
 
            int cbit = 0;
            if ((u & 0xFFFF0000) == 0)
            {
                cbit += 16;
                u <<= 16;
            }
            if ((u & 0xFF000000) == 0)
            {
                cbit += 8;
                u <<= 8;
            }
            if ((u & 0xF0000000) == 0)
            {
                cbit += 4;
                u <<= 4;
            }
            if ((u & 0xC0000000) == 0)
            {
                cbit += 2;
                u <<= 2;
            }
            if ((u & 0x80000000) == 0)
                cbit += 1;
            return cbit;
        }
 
        public static int IbitHigh(uint u)
        {
            if (u == 0)
                return -1;
 
            int ibit = 31;
            if ((u & 0xFFFF0000) == 0)
            {
                ibit -= 16;
                u <<= 16;
            }
            if ((u & 0xFF000000) == 0)
            {
                ibit -= 8;
                u <<= 8;
            }
            if ((u & 0xF0000000) == 0)
            {
                ibit -= 4;
                u <<= 4;
            }
            if ((u & 0xC0000000) == 0)
            {
                ibit -= 2;
                u <<= 2;
            }
            if ((u & 0x80000000) == 0)
                ibit -= 1;
            return ibit;
        }
 
        public static int CbitLowZero(uint u)
        {
            if (u == 0)
                return 32;
 
            int cbit = 0;
            if ((u & 0x0000FFFF) == 0)
            {
                cbit += 16;
                u >>= 16;
            }
            if ((u & 0x000000FF) == 0)
            {
                cbit += 8;
                u >>= 8;
            }
            if ((u & 0x0000000F) == 0)
            {
                cbit += 4;
                u >>= 4;
            }
            if ((u & 0x00000003) == 0)
            {
                cbit += 2;
                u >>= 2;
            }
            if ((u & 0x00000001) == 0)
                cbit += 1;
            return cbit;
        }
 
        public static int CbitHighZero(ulong uu)
        {
            if ((uu & 0xFFFFFFFF00000000) == 0)
                return 32 + CbitHighZero(GetLo(uu));
            return CbitHighZero(GetHi(uu));
        }
 
        public static int CbitLowZero(ulong uu)
        {
            uint u = GetLo(uu);
            if (u == 0)
                return 32 + CbitLowZero(GetHi(uu));
            return CbitLowZero(u);
        }
 
        public static int Cbit(uint u)
        {
            u = (u & 0x55555555) + ((u >> 1) & 0x55555555);
            u = (u & 0x33333333) + ((u >> 2) & 0x33333333);
            u = (u & 0x0F0F0F0F) + ((u >> 4) & 0x0F0F0F0F);
            u = (u & 0x00FF00FF) + ((u >> 8) & 0x00FF00FF);
            return (int)((ushort)u + (ushort)(u >> 16));
        }
 
        public static int Cbit(ulong uu)
        {
            uu = (uu & 0x5555555555555555) + ((uu >> 1) & 0x5555555555555555);
            uu = (uu & 0x3333333333333333) + ((uu >> 2) & 0x3333333333333333);
            uu = (uu & 0x0F0F0F0F0F0F0F0F) + ((uu >> 4) & 0x0F0F0F0F0F0F0F0F);
            uu = (uu & 0x00FF00FF00FF00FF) + ((uu >> 8) & 0x00FF00FF00FF00FF);
            uu = (uu & 0x0000FFFF0000FFFF) + ((uu >> 16) & 0x0000FFFF0000FFFF);
            return (int)(GetLo(uu) + GetHi(uu));
        }
 
        // Builds a mask with bits below ibit all set. Only works for 0 <= ibit < 32.
        // Use MaskBelowEx to extend to 0 <= ibit < 64, in particular, for 32.
        public static uint UMaskBelow(int ibit)
        {
            Contracts.Assert(0 <= ibit && ibit < CbitUint, "UMaskBelow is designed to work for 0 <= ibit < 32");
            return (uint)(1U << ibit) - 1;
        }
 
        // Builds a mask with bits below ibit all set. Only works for 0 <= ibit < 64.
        public static uint UMaskBelowEx(int ibit)
        {
            Contracts.Assert(0 <= ibit && ibit < CbitUlong, "UMaskBelowEx is designed to work for 0 <= ibit < 64");
            // To handle 32 <= ibit < 64 properly, we have to start with 1LU, since otherwise the C# compiler only shifts
            // by the low 5 bits of ibit.
            return (uint)(1LU << ibit) - 1;
        }
 
        // Builds a mask with bits below ibit all set. Only works for 0 <= ibit < 64.
        public static ulong UuMaskBelow(int ibit)
        {
            Contracts.Assert(0 <= ibit && ibit < CbitUlong, "UuMaskBelow is designed to work for 0 <= ibit < 64");
            return (1LU << ibit) - 1;
        }
 
        public static bool IsPowerOfTwo(int x)
        {
            return (x & (x - 1)) == 0;
        }
 
        public static bool IsPowerOfTwo(uint x)
        {
            return (x & (x - 1)) == 0;
        }
 
        public static bool IsPowerOfTwo(long x)
        {
            return (x & (x - 1)) == 0;
        }
 
        public static bool IsPowerOfTwo(ulong x)
        {
            return (x & (x - 1)) == 0;
        }
    }
}