From 858964edbc642178cab454cef4baa5d05338b34f Mon Sep 17 00:00:00 2001 From: mlemanczyk Date: Sun, 26 Mar 2023 23:38:21 +0200 Subject: [PATCH] MathUtils added --- Recyclable.Collections/MathUtils.cs | 42 +++++++++++++++++++ Recyclable.CollectionsTests/MathUtilsTests.cs | 32 ++++++++++++++ 2 files changed, 74 insertions(+) create mode 100644 Recyclable.Collections/MathUtils.cs create mode 100644 Recyclable.CollectionsTests/MathUtilsTests.cs diff --git a/Recyclable.Collections/MathUtils.cs b/Recyclable.Collections/MathUtils.cs new file mode 100644 index 0000000..30e5434 --- /dev/null +++ b/Recyclable.Collections/MathUtils.cs @@ -0,0 +1,42 @@ +using System.Runtime.CompilerServices; + +namespace Recyclable.Collections +{ + public static class MathUtils + { + private static long[] Pow2 = new long[] + { + 1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048, 4096, 8192, 16384, + 32768, 65536, 131072, 262144, 524288, 1048576, 2097152, 4194304, + 8388608, 16777216, 33554432, 67108864, 134217728, 268435456, + 536870912, 1073741824, 2147483648 + }; + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static bool IsPow2(int value) => Array.BinarySearch(Pow2, value) >= 0; + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static int GetPow2Shift(int value) => Array.BinarySearch(Pow2, value); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static long DivMod(long number, int divider, out long remainder) + { + if (number >= divider << 4) + { + return Math.DivRem(number, divider, out remainder); + } + else + { + int result = 0; + remainder = number; + while (remainder >= divider) + { + remainder -= divider; + result++; + } + + return result; + } + } + } +} diff --git a/Recyclable.CollectionsTests/MathUtilsTests.cs b/Recyclable.CollectionsTests/MathUtilsTests.cs new file mode 100644 index 0000000..40c9362 --- /dev/null +++ b/Recyclable.CollectionsTests/MathUtilsTests.cs @@ -0,0 +1,32 @@ +using FluentAssertions; +using Recyclable.Collections; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Recyclable.CollectionsTests +{ + public class MathUtilsTests + { + [Theory] + [InlineData(int.MaxValue / 1024, int.MaxValue / 10 / 1024)] + public void DivMod(long testNumber, int blockSize) + { + for (var testCase = testNumber; testCase >= 0; testCase--) + { + // Prepare + var expectedResult = testCase / blockSize; + var expectedRemainder = testCase % blockSize; + + // Act + var actualResult = MathUtils.DivMod(testCase, blockSize, out long actualRemainder); + + // Validate + _ = actualResult.Should().Be(expectedResult); + _ = actualRemainder.Should().Be(expectedRemainder); + } + } + } +}