1
0
mirror of https://github.com/oliverbooth/X10D synced 2024-11-22 19:48:46 +00:00

Add RoundUpToPowerOf2

This commit is contained in:
Oliver Booth 2022-05-18 11:55:47 +01:00
parent 5aea71465a
commit 683e02cc2a
No known key found for this signature in database
GPG Key ID: 32A00B35503AF634
17 changed files with 376 additions and 0 deletions

View File

@ -2,6 +2,7 @@
## 3.2.0
### Added
- X10D: Added `RoundUpToPowerOf2()` for built-in integer types
- X10D: Added `Vector2.Deconstruct()`
- X10D: Added `Vector3.Deconstruct()`
- X10D: Added `Vector4.Deconstruct()`

View File

@ -39,4 +39,29 @@ public class ByteTests
const byte value = 181; // 10110101
Assert.AreEqual(value, value.RotateRight(8));
}
[TestMethod]
public void RoundUpToPowerOf2_ShouldReturnRoundedValue_GivenValue()
{
Assert.AreEqual(4, ((byte)3).RoundUpToPowerOf2());
Assert.AreEqual(8, ((byte)5).RoundUpToPowerOf2());
Assert.AreEqual(8, ((byte)6).RoundUpToPowerOf2());
Assert.AreEqual(8, ((byte)7).RoundUpToPowerOf2());
}
[TestMethod]
public void RoundUpToPowerOf2_ShouldReturnSameValue_GivenPowerOf2()
{
for (var i = 0; i < 8; i++)
{
var value = (byte)System.Math.Pow(2, i);
Assert.AreEqual(value, value.RoundUpToPowerOf2());
}
}
[TestMethod]
public void RoundUpToPowerOf2_ShouldReturn0_Given0()
{
Assert.AreEqual(0, ((byte)0).RoundUpToPowerOf2());
}
}

View File

@ -41,4 +41,29 @@ public class Int16Tests
const short value = 2896; // 00001011 01010000
Assert.AreEqual(value, value.RotateRight(16));
}
[TestMethod]
public void RoundUpToPowerOf2_ShouldReturnRoundedValue_GivenValue()
{
Assert.AreEqual(4, ((short)3).RoundUpToPowerOf2());
Assert.AreEqual(8, ((short)5).RoundUpToPowerOf2());
Assert.AreEqual(8, ((short)6).RoundUpToPowerOf2());
Assert.AreEqual(8, ((short)7).RoundUpToPowerOf2());
}
[TestMethod]
public void RoundUpToPowerOf2_ShouldReturnSameValue_GivenPowerOf2()
{
for (var i = 0; i < 8; i++)
{
var value = (short) System.Math.Pow(2, i);
Assert.AreEqual(value, value.RoundUpToPowerOf2());
}
}
[TestMethod]
public void RoundUpToPowerOf2_ShouldReturn0_Given0()
{
Assert.AreEqual(0, ((short)0).RoundUpToPowerOf2());
}
}

View File

@ -39,4 +39,29 @@ public class Int32Tests
const int value = 284719; // 00000000 00000100 01011000 00101111
Assert.AreEqual(value, value.RotateRight(32));
}
[TestMethod]
public void RoundUpToPowerOf2_ShouldReturnRoundedValue_GivenValue()
{
Assert.AreEqual(4, 3.RoundUpToPowerOf2());
Assert.AreEqual(8, 5.RoundUpToPowerOf2());
Assert.AreEqual(8, 6.RoundUpToPowerOf2());
Assert.AreEqual(8, 7.RoundUpToPowerOf2());
}
[TestMethod]
public void RoundUpToPowerOf2_ShouldReturnSameValue_GivenPowerOf2()
{
for (var i = 0; i < 8; i++)
{
var value = (int)System.Math.Pow(2, i);
Assert.AreEqual(value, value.RoundUpToPowerOf2());
}
}
[TestMethod]
public void RoundUpToPowerOf2_ShouldReturn0_Given0()
{
Assert.AreEqual(0, 0.RoundUpToPowerOf2());
}
}

View File

@ -39,4 +39,29 @@ public class Int64Tests
const long value = 5972019251303316844; // 01010010 11100000 11011111 11011110 00110001 10111010 01111101 01101100
Assert.AreEqual(value, value.RotateRight(64));
}
[TestMethod]
public void RoundUpToPowerOf2_ShouldReturnRoundedValue_GivenValue()
{
Assert.AreEqual(4L, 3L.RoundUpToPowerOf2());
Assert.AreEqual(8L, 5L.RoundUpToPowerOf2());
Assert.AreEqual(8L, 6L.RoundUpToPowerOf2());
Assert.AreEqual(8L, 7L.RoundUpToPowerOf2());
}
[TestMethod]
public void RoundUpToPowerOf2_ShouldReturnSameValue_GivenPowerOf2()
{
for (var i = 0; i < 8; i++)
{
var value = (long)System.Math.Pow(2, i);
Assert.AreEqual(value, value.RoundUpToPowerOf2());
}
}
[TestMethod]
public void RoundUpToPowerOf2_ShouldReturn0_Given0()
{
Assert.AreEqual(0L, 0L.RoundUpToPowerOf2());
}
}

View File

@ -40,4 +40,29 @@ public class SByteTests
const sbyte value = 117; // 01110101
Assert.AreEqual(value, value.RotateRight(8));
}
[TestMethod]
public void RoundUpToPowerOf2_ShouldReturnRoundedValue_GivenValue()
{
Assert.AreEqual(4, ((sbyte)3).RoundUpToPowerOf2());
Assert.AreEqual(8, ((sbyte)5).RoundUpToPowerOf2());
Assert.AreEqual(8, ((sbyte)6).RoundUpToPowerOf2());
Assert.AreEqual(8, ((sbyte)7).RoundUpToPowerOf2());
}
[TestMethod]
public void RoundUpToPowerOf2_ShouldReturnSameValue_GivenPowerOf2()
{
for (var i = 0; i < 7; i++)
{
var value = (sbyte)System.Math.Pow(2, i);
Assert.AreEqual(value, value.RoundUpToPowerOf2());
}
}
[TestMethod]
public void RoundUpToPowerOf2_ShouldReturn0_Given0()
{
Assert.AreEqual(0, ((sbyte)0).RoundUpToPowerOf2());
}
}

View File

@ -42,4 +42,29 @@ public class UInt16Tests
const ushort value = 2896; // 00001011 01010000
Assert.AreEqual(value, value.RotateRight(16));
}
[TestMethod]
public void RoundUpToPowerOf2_ShouldReturnRoundedValue_GivenValue()
{
Assert.AreEqual(4U, ((ushort)3).RoundUpToPowerOf2());
Assert.AreEqual(8U, ((ushort)5).RoundUpToPowerOf2());
Assert.AreEqual(8U, ((ushort)6).RoundUpToPowerOf2());
Assert.AreEqual(8U, ((ushort)7).RoundUpToPowerOf2());
}
[TestMethod]
public void RoundUpToPowerOf2_ShouldReturnSameValue_GivenPowerOf2()
{
for (var i = 0; i < 8; i++)
{
var value = (ushort)System.Math.Pow(2, i);
Assert.AreEqual(value, value.RoundUpToPowerOf2());
}
}
[TestMethod]
public void RoundUpToPowerOf2_ShouldReturn0_Given0()
{
Assert.AreEqual(0U, ((ushort)0).RoundUpToPowerOf2());
}
}

View File

@ -39,5 +39,28 @@ public class UInt32Tests
{
const uint value = 284719; // 00000000 00000100 01011000 00101111
Assert.AreEqual(value, value.RotateRight(32));
} [TestMethod]
public void RoundUpToPowerOf2_ShouldReturnRoundedValue_GivenValue()
{
Assert.AreEqual(4U, 3U.RoundUpToPowerOf2());
Assert.AreEqual(8U, 5U.RoundUpToPowerOf2());
Assert.AreEqual(8U, 6U.RoundUpToPowerOf2());
Assert.AreEqual(8U, 7U.RoundUpToPowerOf2());
}
[TestMethod]
public void RoundUpToPowerOf2_ShouldReturnSameValue_GivenPowerOf2()
{
for (var i = 0; i < 8; i++)
{
var value = (uint)System.Math.Pow(2, i);
Assert.AreEqual(value, value.RoundUpToPowerOf2());
}
}
[TestMethod]
public void RoundUpToPowerOf2_ShouldReturn0_Given0()
{
Assert.AreEqual(0U, 0U.RoundUpToPowerOf2());
}
}

View File

@ -40,4 +40,29 @@ public class UInt64Tests
const ulong value = 5972019251303316844; // 01010010 11100000 11011111 11011110 00110001 10111010 01111101 01101100
Assert.AreEqual(value, value.RotateRight(64));
}
[TestMethod]
public void RoundUpToPowerOf2_ShouldReturnRoundedValue_GivenValue()
{
Assert.AreEqual(4UL, 3UL.RoundUpToPowerOf2());
Assert.AreEqual(8UL, 5UL.RoundUpToPowerOf2());
Assert.AreEqual(8UL, 6UL.RoundUpToPowerOf2());
Assert.AreEqual(8UL, 7UL.RoundUpToPowerOf2());
}
[TestMethod]
public void RoundUpToPowerOf2_ShouldReturnSameValue_GivenPowerOf2()
{
for (var i = 0; i < 8; i++)
{
var value = (ulong)System.Math.Pow(2, i);
Assert.AreEqual(value, value.RoundUpToPowerOf2());
}
}
[TestMethod]
public void RoundUpToPowerOf2_ShouldReturn0_Given0()
{
Assert.AreEqual(0UL, 0UL.RoundUpToPowerOf2());
}
}

View File

@ -48,4 +48,23 @@ public static class ByteExtensions
count = count.Mod(8);
return (byte)((value >> count) | (value << (8 - count)));
}
/// <summary>
/// Rounds the current value up to a power of two.
/// </summary>
/// <param name="value">The value to round.</param>
/// <returns>
/// The smallest power of two that's greater than or equal to <paramref name="value" />, or 0 if <paramref name="value" />
/// is 0 or the result overflows.
/// </returns>
[Pure]
#if NETSTANDARD2_1
[MethodImpl(MethodImplOptions.AggressiveInlining)]
#else
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
#endif
public static byte RoundUpToPowerOf2(this byte value)
{
return (byte)((uint)value).RoundUpToPowerOf2();
}
}

View File

@ -47,4 +47,23 @@ public static class Int16Extensions
var unsigned = unchecked((ushort)value);
return unchecked((short)unsigned.RotateRight(count));
}
/// <summary>
/// Rounds the current value up to a power of two.
/// </summary>
/// <param name="value">The value to round.</param>
/// <returns>
/// The smallest power of two that's greater than or equal to <paramref name="value" />, or 0 if <paramref name="value" />
/// is 0 or the result overflows.
/// </returns>
[Pure]
#if NETSTANDARD2_1
[MethodImpl(MethodImplOptions.AggressiveInlining)]
#else
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
#endif
public static short RoundUpToPowerOf2(this short value)
{
return (short)((uint)value).RoundUpToPowerOf2();
}
}

View File

@ -47,4 +47,23 @@ public static class Int32Extensions
var unsigned = unchecked((uint)value);
return unchecked((int)unsigned.RotateRight(count));
}
/// <summary>
/// Rounds the current value up to a power of two.
/// </summary>
/// <param name="value">The value to round.</param>
/// <returns>
/// The smallest power of two that's greater than or equal to <paramref name="value" />, or 0 if <paramref name="value" />
/// is 0 or the result overflows.
/// </returns>
[Pure]
#if NETSTANDARD2_1
[MethodImpl(MethodImplOptions.AggressiveInlining)]
#else
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
#endif
public static int RoundUpToPowerOf2(this int value)
{
return (int)((uint)value).RoundUpToPowerOf2();
}
}

View File

@ -47,4 +47,23 @@ public static class Int64Extensions
var unsigned = unchecked((ulong)value);
return unchecked((long)unsigned.RotateRight(count));
}
/// <summary>
/// Rounds the current value up to a power of two.
/// </summary>
/// <param name="value">The value to round.</param>
/// <returns>
/// The smallest power of two that's greater than or equal to <paramref name="value" />, or 0 if <paramref name="value" />
/// is 0 or the result overflows.
/// </returns>
[Pure]
#if NETSTANDARD2_1
[MethodImpl(MethodImplOptions.AggressiveInlining)]
#else
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
#endif
public static long RoundUpToPowerOf2(this long value)
{
return (long)((ulong)value).RoundUpToPowerOf2();
}
}

View File

@ -48,4 +48,23 @@ public static class SByteExtensions
var signed = unchecked((byte)value);
return unchecked((sbyte)signed.RotateRight(count));
}
/// <summary>
/// Rounds the current value up to a power of two.
/// </summary>
/// <param name="value">The value to round.</param>
/// <returns>
/// The smallest power of two that's greater than or equal to <paramref name="value" />, or 0 if <paramref name="value" />
/// is 0 or the result overflows.
/// </returns>
[Pure]
#if NETSTANDARD2_1
[MethodImpl(MethodImplOptions.AggressiveInlining)]
#else
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
#endif
public static sbyte RoundUpToPowerOf2(this sbyte value)
{
return (sbyte)((uint)value).RoundUpToPowerOf2();
}
}

View File

@ -46,4 +46,23 @@ public static class UInt16Extensions
{
return (ushort)((ushort)(value >> count) | (ushort)(value << (16 - count)));
}
/// <summary>
/// Rounds the current value up to a power of two.
/// </summary>
/// <param name="value">The value to round.</param>
/// <returns>
/// The smallest power of two that's greater than or equal to <paramref name="value" />, or 0 if <paramref name="value" />
/// is 0 or the result overflows.
/// </returns>
[Pure]
#if NETSTANDARD2_1
[MethodImpl(MethodImplOptions.AggressiveInlining)]
#else
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
#endif
public static ushort RoundUpToPowerOf2(this ushort value)
{
return (ushort)((uint)value).RoundUpToPowerOf2();
}
}

View File

@ -1,4 +1,5 @@
using System.Diagnostics.Contracts;
using System.Numerics;
using System.Runtime.CompilerServices;
namespace X10D.Numerics;
@ -46,4 +47,34 @@ public static class UInt32Extensions
{
return (value >> count) | (value << (32 - count));
}
/// <summary>
/// Rounds the current value up to a power of two.
/// </summary>
/// <param name="value">The value to round.</param>
/// <returns>
/// The smallest power of two that's greater than or equal to <paramref name="value" />, or 0 if <paramref name="value" />
/// is 0 or the result overflows.
/// </returns>
[Pure]
#if NETSTANDARD2_1
[MethodImpl(MethodImplOptions.AggressiveInlining)]
#else
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
#endif
public static uint RoundUpToPowerOf2(this uint value)
{
#if NET6_0_OR_GREATER
return BitOperations.RoundUpToPowerOf2(value);
#else
// Based on https://graphics.stanford.edu/~seander/bithacks.html#RoundUpPowerOf2
--value;
value |= value >> 1;
value |= value >> 2;
value |= value >> 4;
value |= value >> 8;
value |= value >> 16;
return value + 1;
#endif
}
}

View File

@ -1,4 +1,5 @@
using System.Diagnostics.Contracts;
using System.Numerics;
using System.Runtime.CompilerServices;
namespace X10D.Numerics;
@ -46,4 +47,35 @@ public static class UInt64Extensions
{
return (value >> count) | (value << (64 - count));
}
/// <summary>
/// Rounds the current value up to a power of two.
/// </summary>
/// <param name="value">The value to round.</param>
/// <returns>
/// The smallest power of two that's greater than or equal to <paramref name="value" />, or 0 if <paramref name="value" />
/// is 0 or the result overflows.
/// </returns>
[Pure]
#if NETSTANDARD2_1
[MethodImpl(MethodImplOptions.AggressiveInlining)]
#else
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
#endif
public static ulong RoundUpToPowerOf2(this ulong value)
{
#if NET6_0_OR_GREATER
return BitOperations.RoundUpToPowerOf2(value);
#else
// Based on https://graphics.stanford.edu/~seander/bithacks.html#RoundUpPowerOf2
--value;
value |= value >> 1;
value |= value >> 2;
value |= value >> 4;
value |= value >> 8;
value |= value >> 16;
value |= value >> 32;
return value + 1;
#endif
}
}