// Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT license. using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Runtime.InteropServices; using System.Security; using System.IO; using System.Runtime.CompilerServices; using Microsoft.Win32.SafeHandles; using System.Diagnostics; using System.Threading; namespace FASTER.core { /// /// Empty type /// public struct Empty { /// /// Default /// public static readonly Empty Default = default(Empty); } /// /// FASTER utility functions /// public static class Utility { /// /// Get size of type /// /// /// /// internal static unsafe int GetSize(this T value) { T[] arr = new T[2]; return (int)((long)Unsafe.AsPointer(ref arr[1]) - (long)Unsafe.AsPointer(ref arr[0])); } /// /// Is type blittable /// /// /// internal static bool IsBlittable() { if (default(T) == null) return false; try { var tmp = new T[1]; var h = GCHandle.Alloc(tmp, GCHandleType.Pinned); h.Free(); } catch (Exception) { return false; } return true; } /// /// Check if two byte arrays of given length are equal /// /// /// /// /// [MethodImpl(MethodImplOptions.AggressiveInlining)] public unsafe static bool IsEqual(byte* src, byte* dst, int length) { for (int i = 0; i < length; i++) { if (*(src + i) != *(dst + i)) { return false; } } return true; } /// /// Copy numBytes bytes from src to dest /// /// /// /// public unsafe static void Copy(byte* src, byte* dest, int numBytes) { for(int i = 0; i < numBytes; i++) { *(dest + i) = *(src + i); } } /// /// Get 64-bit hash code for a long value /// /// /// [MethodImpl(MethodImplOptions.AggressiveInlining)] public static long GetHashCode(long input) { long local_rand = input; long local_rand_hash = 8; local_rand_hash = 40343 * local_rand_hash + ((local_rand) & 0xFFFF); local_rand_hash = 40343 * local_rand_hash + ((local_rand >> 16) & 0xFFFF); local_rand_hash = 40343 * local_rand_hash + ((local_rand >> 32) & 0xFFFF); local_rand_hash = 40343 * local_rand_hash + (local_rand >> 48); local_rand_hash = 40343 * local_rand_hash; return (long)Rotr64((ulong)local_rand_hash, 45); } /// /// Get 64-bit hash code for a byte array /// /// /// /// [MethodImpl(MethodImplOptions.AggressiveInlining)] public static unsafe long HashBytes(byte* pbString, int len) { const long magicno = 40343; char* pwString = (char*)pbString; int cbBuf = len / 2; ulong hashState = (ulong)len; for (int i = 0; i < cbBuf; i++, pwString++) hashState = magicno * hashState + *pwString; if ((len & 1) > 0) { byte* pC = (byte*)pwString; hashState = magicno * hashState + *pC; } return (long)Rotr64(magicno * hashState, 4); } /// /// Compute XOR of all provided bytes /// /// /// /// [MethodImpl(MethodImplOptions.AggressiveInlining)] public static unsafe ulong XorBytes(byte* src, int length) { ulong result = 0; byte* curr = src; byte* end = src + length; while (curr + 4 * sizeof(ulong) <= end) { result ^= *(ulong*)curr; result ^= *(1 + (ulong*)curr); result ^= *(2 + (ulong*)curr); result ^= *(3 + (ulong*)curr); curr += 4 * sizeof(ulong); } while (curr + sizeof(ulong) <= end) { result ^= *(ulong*)curr; curr += sizeof(ulong); } while (curr + 1 <= end) { result ^= *curr; curr++; } return result; } [MethodImpl(MethodImplOptions.AggressiveInlining)] internal static ulong Rotr64(ulong x, int n) { return (((x) >> n) | ((x) << (64 - n))); } /// /// Is power of 2 /// /// /// [MethodImpl(MethodImplOptions.AggressiveInlining)] public static bool IsPowerOfTwo(long x) { return (x > 0) && ((x & (x - 1)) == 0); } internal static readonly int[] MultiplyDeBruijnBitPosition2 = new int[32] { 0, 1, 28, 2, 29, 14, 24, 3, 30, 22, 20, 15, 25, 17, 4, 8, 31, 27, 13, 23, 21, 19, 16, 7, 26, 12, 18, 6, 11, 5, 10, 9 }; /// /// Get log base 2 /// /// /// [MethodImpl(MethodImplOptions.AggressiveInlining)] public static int GetLogBase2(int x) { return MultiplyDeBruijnBitPosition2[(uint)(x * 0x077CB531U) >> 27]; } /// /// Get log base 2 /// /// /// public static int GetLogBase2(ulong value) { int i; for (i = -1; value != 0; i++) value >>= 1; return (i == -1) ? 0 : i; } /// /// Check if power of two /// /// /// [MethodImpl(MethodImplOptions.AggressiveInlining)] public static bool Is32Bit(long x) { return ((ulong)x < 4294967295ul); } /// /// A 32-bit murmur3 implementation. /// /// /// internal static int Murmur3(int h) { uint a = (uint)h; a ^= a >> 16; a *= 0x85ebca6b; a ^= a >> 13; a *= 0xc2b2ae35; a ^= a >> 16; return (int)a; } /// /// Updates the variable to newValue only if the current value is smaller than the new value. /// /// The variable to possibly replace /// The value that replaces the variable if successful /// The orignal value in the variable /// if oldValue less than newValue public static bool MonotonicUpdate(ref long variable, long newValue, out long oldValue) { do { oldValue = variable; if (oldValue >= newValue) return false; } while (Interlocked.CompareExchange(ref variable, newValue, oldValue) != oldValue); return true; } /// /// Updates the variable to newValue only if the current value is smaller than the new value. /// /// The variable to possibly replace /// The value that replaces the variable if successful /// The orignal value in the variable /// if oldValue less than or equal to newValue public static bool MonotonicUpdate(ref int variable, int newValue, out int oldValue) { do { oldValue = variable; if (oldValue >= newValue) return false; } while (Interlocked.CompareExchange(ref variable, newValue, oldValue) != oldValue); return true; } } }