您最多选择25个主题
主题必须以中文或者字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符
129 行
5.5 KiB
129 行
5.5 KiB
using System.Runtime.CompilerServices;
|
|
|
|
namespace Unity.Netcode
|
|
{
|
|
/// <summary>
|
|
/// Utility class to count the number of bytes or bits needed to serialize a value.
|
|
/// </summary>
|
|
public static class BitCounter
|
|
{
|
|
// Since we don't have access to BitOperations.LeadingZeroCount() (which would have been the fastest)
|
|
// we use the De Bruijn sequence to do this calculation
|
|
// See https://en.wikipedia.org/wiki/De_Bruijn_sequence and https://www.chessprogramming.org/De_Bruijn_Sequence
|
|
private const ulong k_DeBruijnMagic64 = 0x37E84A99DAE458F;
|
|
private const uint k_DeBruijnMagic32 = 0x06EB14F9;
|
|
|
|
// We're counting bytes, not bits, so these have all had the operation x/8 + 1 applied
|
|
private static readonly int[] k_DeBruijnTableBytes64 =
|
|
{
|
|
0/8+1, 1/8+1, 17/8+1, 2/8+1, 18/8+1, 50/8+1, 3/8+1, 57/8+1,
|
|
47/8+1, 19/8+1, 22/8+1, 51/8+1, 29/8+1, 4/8+1, 33/8+1, 58/8+1,
|
|
15/8+1, 48/8+1, 20/8+1, 27/8+1, 25/8+1, 23/8+1, 52/8+1, 41/8+1,
|
|
54/8+1, 30/8+1, 38/8+1, 5/8+1, 43/8+1, 34/8+1, 59/8+1, 8/8+1,
|
|
63/8+1, 16/8+1, 49/8+1, 56/8+1, 46/8+1, 21/8+1, 28/8+1, 32/8+1,
|
|
14/8+1, 26/8+1, 24/8+1, 40/8+1, 53/8+1, 37/8+1, 42/8+1, 7/8+1,
|
|
62/8+1, 55/8+1, 45/8+1, 31/8+1, 13/8+1, 39/8+1, 36/8+1, 6/8+1,
|
|
61/8+1, 44/8+1, 12/8+1, 35/8+1, 60/8+1, 11/8+1, 10/8+1, 9/8+1,
|
|
};
|
|
|
|
private static readonly int[] k_DeBruijnTableBytes32 =
|
|
{
|
|
0/8+1, 1/8+1, 16/8+1, 2/8+1, 29/8+1, 17/8+1, 3/8+1, 22/8+1,
|
|
30/8+1, 20/8+1, 18/8+1, 11/8+1, 13/8+1, 4/8+1, 7/8+1, 23/8+1,
|
|
31/8+1, 15/8+1, 28/8+1, 21/8+1, 19/8+1, 10/8+1, 12/8+1, 6/8+1,
|
|
14/8+1, 27/8+1, 9/8+1, 5/8+1, 26/8+1, 8/8+1, 25/8+1, 24/8+1,
|
|
};
|
|
|
|
// And here we're counting the number of set bits, not the position of the highest set,
|
|
// so these still have +1 applied - unfortunately 0 and 1 both return the same value.
|
|
private static readonly int[] k_DeBruijnTableBits64 =
|
|
{
|
|
0+1, 1+1, 17+1, 2+1, 18+1, 50+1, 3+1, 57+1,
|
|
47+1, 19+1, 22+1, 51+1, 29+1, 4+1, 33+1, 58+1,
|
|
15+1, 48+1, 20+1, 27+1, 25+1, 23+1, 52+1, 41+1,
|
|
54+1, 30+1, 38+1, 5+1, 43+1, 34+1, 59+1, 8+1,
|
|
63+1, 16+1, 49+1, 56+1, 46+1, 21+1, 28+1, 32+1,
|
|
14+1, 26+1, 24+1, 40+1, 53+1, 37+1, 42+1, 7+1,
|
|
62+1, 55+1, 45+1, 31+1, 13+1, 39+1, 36+1, 6+1,
|
|
61+1, 44+1, 12+1, 35+1, 60+1, 11+1, 10+1, 9+1,
|
|
};
|
|
|
|
private static readonly int[] k_DeBruijnTableBits32 =
|
|
{
|
|
0+1, 1+1, 16+1, 2+1, 29+1, 17+1, 3+1, 22+1,
|
|
30+1, 20+1, 18+1, 11+1, 13+1, 4+1, 7+1, 23+1,
|
|
31+1, 15+1, 28+1, 21+1, 19+1, 10+1, 12+1, 6+1,
|
|
14+1, 27+1, 9+1, 5+1, 26+1, 8+1, 25+1, 24+1,
|
|
};
|
|
|
|
/// <summary>
|
|
/// Get the minimum number of bytes required to represent the given value
|
|
/// </summary>
|
|
/// <param name="value">The value</param>
|
|
/// <returns>The number of bytes required</returns>
|
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
public static int GetUsedByteCount(uint value)
|
|
{
|
|
value |= value >> 1;
|
|
value |= value >> 2;
|
|
value |= value >> 4;
|
|
value |= value >> 8;
|
|
value |= value >> 16;
|
|
value = value & ~(value >> 1);
|
|
return k_DeBruijnTableBytes32[value * k_DeBruijnMagic32 >> 27];
|
|
}
|
|
|
|
/// <summary>
|
|
/// Get the minimum number of bytes required to represent the given value
|
|
/// </summary>
|
|
/// <param name="value">The value</param>
|
|
/// <returns>The number of bytes required</returns>
|
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
public static int GetUsedByteCount(ulong value)
|
|
{
|
|
value |= value >> 1;
|
|
value |= value >> 2;
|
|
value |= value >> 4;
|
|
value |= value >> 8;
|
|
value |= value >> 16;
|
|
value |= value >> 32;
|
|
value = value & ~(value >> 1);
|
|
return k_DeBruijnTableBytes64[value * k_DeBruijnMagic64 >> 58];
|
|
}
|
|
|
|
/// <summary>
|
|
/// Get the minimum number of bits required to represent the given value
|
|
/// </summary>
|
|
/// <param name="value">The value</param>
|
|
/// <returns>The number of bits required</returns>
|
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
public static int GetUsedBitCount(uint value)
|
|
{
|
|
value |= value >> 1;
|
|
value |= value >> 2;
|
|
value |= value >> 4;
|
|
value |= value >> 8;
|
|
value |= value >> 16;
|
|
value = value & ~(value >> 1);
|
|
return k_DeBruijnTableBits32[value * k_DeBruijnMagic32 >> 27];
|
|
}
|
|
|
|
/// <summary>
|
|
/// Get the minimum number of bits required to represent the given value
|
|
/// </summary>
|
|
/// <param name="value">The value</param>
|
|
/// <returns>The number of bits required</returns>
|
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
public static int GetUsedBitCount(ulong value)
|
|
{
|
|
value |= value >> 1;
|
|
value |= value >> 2;
|
|
value |= value >> 4;
|
|
value |= value >> 8;
|
|
value |= value >> 16;
|
|
value |= value >> 32;
|
|
value = value & ~(value >> 1);
|
|
return k_DeBruijnTableBits64[value * k_DeBruijnMagic64 >> 58];
|
|
}
|
|
}
|
|
}
|