mirror of
https://github.com/Thealexbarney/LibHac.git
synced 2024-11-14 10:49:41 +01:00
Use generic math in Util.BitUtil
This commit is contained in:
parent
4108a6c149
commit
7fce26e899
2 changed files with 98 additions and 30 deletions
|
@ -5,47 +5,28 @@ namespace LibHac.Util;
|
|||
|
||||
public static class BitUtil
|
||||
{
|
||||
public static bool IsPowerOfTwo(int value)
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static bool IsPowerOfTwo<T>(T value) where T : IBitwiseOperators<T, T, T>, INumberBase<T>
|
||||
{
|
||||
return value > 0 && ResetLeastSignificantOneBit(value) == 0;
|
||||
return !T.IsNegative(value) && !T.IsZero(value) && T.IsZero(ResetLeastSignificantOneBit(value));
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static bool IsPowerOfTwo(long value)
|
||||
public static T ResetLeastSignificantOneBit<T>(T value) where T : IBitwiseOperators<T, T, T>, INumberBase<T>
|
||||
{
|
||||
return value > 0 && ResetLeastSignificantOneBit(value) == 0;
|
||||
return value & unchecked(value - T.One);
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static bool IsPowerOfTwo(ulong value)
|
||||
public static int CountLeadingZeros<T>(T value) where T : IBinaryInteger<T>
|
||||
{
|
||||
return value > 0 && ResetLeastSignificantOneBit(value) == 0;
|
||||
return int.CreateTruncating(T.LeadingZeroCount(value));
|
||||
}
|
||||
|
||||
private static int ResetLeastSignificantOneBit(int value)
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static T DivideUp<T>(T value, T divisor) where T : INumberBase<T>
|
||||
{
|
||||
return value & (value - 1);
|
||||
return unchecked(value + divisor - T.One) / divisor;
|
||||
}
|
||||
|
||||
private static long ResetLeastSignificantOneBit(long value)
|
||||
{
|
||||
return value & (value - 1);
|
||||
}
|
||||
|
||||
private static ulong ResetLeastSignificantOneBit(ulong value)
|
||||
{
|
||||
return value & (value - 1);
|
||||
}
|
||||
|
||||
public static int CountLeadingZeros(uint value)
|
||||
{
|
||||
return BitOperations.LeadingZeroCount(value);
|
||||
}
|
||||
|
||||
// DivideUp comes from a C++ template that always casts to unsigned types
|
||||
public static uint DivideUp(uint value, uint divisor) => (value + divisor - 1) / divisor;
|
||||
public static ulong DivideUp(ulong value, ulong divisor) => (value + divisor - 1) / divisor;
|
||||
|
||||
public static int DivideUp(int value, int divisor) => (int)DivideUp((uint)value, (uint)divisor);
|
||||
public static long DivideUp(long value, long divisor) => (long)DivideUp((ulong)value, (ulong)divisor);
|
||||
}
|
87
tests/LibHac.Tests/Util/BitUtilTests.cs
Normal file
87
tests/LibHac.Tests/Util/BitUtilTests.cs
Normal file
|
@ -0,0 +1,87 @@
|
|||
using LibHac.Util;
|
||||
using Xunit;
|
||||
|
||||
namespace LibHac.Tests.Util;
|
||||
|
||||
public class BitUtilTests
|
||||
{
|
||||
[Theory]
|
||||
[InlineData(0x80, 0)]
|
||||
[InlineData(0x00, 8)]
|
||||
public void CountLeadingZeros_Byte(byte value, int expectedValue)
|
||||
{
|
||||
Assert.Equal(expectedValue, BitUtil.CountLeadingZeros(value));
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(0x0080, 8)]
|
||||
[InlineData(0x0000, 16)]
|
||||
public void CountLeadingZeros_Short(short value, int expectedValue)
|
||||
{
|
||||
Assert.Equal(expectedValue, BitUtil.CountLeadingZeros(value));
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(0b0000_1000_0110_0000, 0b0000_1000_0100_0000)]
|
||||
[InlineData(0b0000_1000_0110_1111, 0b0000_1000_0110_1110)]
|
||||
[InlineData(unchecked((short)0b1000_0000_0000_0000), 0b0000_0000_0000_0000)]
|
||||
[InlineData(0, 0)]
|
||||
public void ResetLeastSignificantOneBit_Short(short value, short expectedValue)
|
||||
{
|
||||
Assert.Equal(expectedValue, BitUtil.ResetLeastSignificantOneBit(value));
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(0b0101_0000_0000_0000_0000, 0b0100_0000_0000_0000_0000)]
|
||||
[InlineData(0b1111_0000_1000_0110_1111, 0b1111_0000_1000_0110_1110)]
|
||||
[InlineData(0b0100_1000_0000_0000_0000, 0b0100_0000_0000_0000_0000)]
|
||||
[InlineData(0, 0)]
|
||||
public void ResetLeastSignificantOneBit_Uint(uint value, uint expectedValue)
|
||||
{
|
||||
Assert.Equal(expectedValue, BitUtil.ResetLeastSignificantOneBit(value));
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(0x80, true)]
|
||||
[InlineData(0x81, false)]
|
||||
[InlineData(0, false)]
|
||||
[InlineData(short.MinValue, false)]
|
||||
public void IsPowerOfTwo_Short(short value, bool expectedValue)
|
||||
{
|
||||
Assert.Equal(expectedValue, BitUtil.IsPowerOfTwo(value));
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(0x0000100000000000, true)]
|
||||
[InlineData(0x0000100000004000, false)]
|
||||
[InlineData(0, false)]
|
||||
public void IsPowerOfTwo_Ulong(ulong value, bool expectedValue)
|
||||
{
|
||||
Assert.Equal(expectedValue, BitUtil.IsPowerOfTwo(value));
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(-55, -2, 29)]
|
||||
[InlineData(-55, 2, -27)]
|
||||
[InlineData(0, 26, 0)]
|
||||
[InlineData(-55, -26, 3)]
|
||||
[InlineData(55, -26, -1)]
|
||||
[InlineData(int.MinValue, -26, -82595523)]
|
||||
public void DivideUp_Int(int value, int divisor, int expectedValue)
|
||||
{
|
||||
Assert.Equal(expectedValue, BitUtil.DivideUp(value, divisor));
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(55, 2, 28)]
|
||||
[InlineData(0, 26, 0)]
|
||||
[InlineData(1127, 24, 47)]
|
||||
[InlineData(1128, 24, 47)]
|
||||
[InlineData(1129, 24, 48)]
|
||||
[InlineData(567, 987, 1)]
|
||||
[InlineData(int.MaxValue, 26, 82595525)]
|
||||
public void DivideUp_Uint(uint value, uint divisor, uint expectedValue)
|
||||
{
|
||||
Assert.Equal(expectedValue, BitUtil.DivideUp(value, divisor));
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue