File: IntUtils.cs
Web Access
Project: src\src\Microsoft.ML.CpuMath\Microsoft.ML.CpuMath.csproj (Microsoft.ML.CpuMath)
// 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 System.Runtime.InteropServices;
using System.Security;
using Microsoft.ML.Internal.CpuMath.Core;
 
namespace Microsoft.ML.Internal.CpuMath
{
    [BestFriend]
    internal static class IntUtils
    {
        /// <summary>
        /// Add src to the 128 bits contained in dst. Ignores overflow, that is, the addition is done modulo 2^128.
        /// </summary>
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public static void Add(ref ulong dstHi, ref ulong dstLo, ulong src)
        {
            if ((dstLo += src) < src)
                dstHi++;
        }
 
        /// <summary>
        /// Add src to dst. Ignores overflow, that is, the addition is done modulo 2^128.
        /// </summary>
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public static void Add(ref ulong dstHi, ref ulong dstLo, ulong srcHi, ulong srcLo)
        {
            if ((dstLo += srcLo) < srcLo)
                dstHi++;
            dstHi += srcHi;
        }
 
        /// <summary>
        /// Subtract src from the 128 bits contained in dst. Ignores overflow, that is, the subtraction is
        /// done modulo 2^128.
        /// </summary>
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public static void Sub(ref ulong dstHi, ref ulong dstLo, ulong src)
        {
            if (dstLo < src)
                dstHi--;
            dstLo -= src;
        }
 
        /// <summary>
        /// Subtract src from dst. Ignores overflow, that is, the subtraction is done modulo 2^128.
        /// </summary>
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public static void Sub(ref ulong dstHi, ref ulong dstLo, ulong srcHi, ulong srcLo)
        {
            dstHi -= srcHi;
            if (dstLo < srcLo)
                dstHi--;
            dstLo -= srcLo;
        }
 
        /// <summary>
        /// Return true if a is less than b.
        /// </summary>
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public static bool LessThan(ulong a1, ulong a0, ulong b1, ulong b0)
        {
            return a1 < b1 || a1 == b1 && a0 < b0;
        }
 
        /// <summary>
        /// Multiple the two 64-bit values to produce 128 bit result.
        /// </summary>
        [DllImport(Thunk.NativePath), SuppressUnmanagedCodeSecurity]
        private static extern ulong Mul64(ulong a, ulong b, out ulong hi);
 
        /// <summary>
        /// Return the number of zero bits on the high end.
        /// </summary>
        private static int CbitHighZero(ulong u)
        {
            if (u == 0)
                return 64;
 
            int cbit = 0;
            if ((u & 0xFFFFFFFF00000000) == 0)
            {
                cbit += 32;
                u <<= 32;
            }
            if ((u & 0xFFFF000000000000) == 0)
            {
                cbit += 16;
                u <<= 16;
            }
            if ((u & 0xFF00000000000000) == 0)
            {
                cbit += 8;
                u <<= 8;
            }
            if ((u & 0xF000000000000000) == 0)
            {
                cbit += 4;
                u <<= 4;
            }
            if ((u & 0xC000000000000000) == 0)
            {
                cbit += 2;
                u <<= 2;
            }
            if ((u & 0x8000000000000000) == 0)
                cbit += 1;
            return cbit;
        }
    }
}