From bd13c7cad0e722ee8be6a63d4623656c1f993238 Mon Sep 17 00:00:00 2001 From: Hawkynt Date: Wed, 31 Jul 2024 16:32:57 +0200 Subject: [PATCH 1/6] + shifts&rotates --- Corlib.Extensions/System/Math.T4.tt | 51 +++++++++++++++++++++++++++++ 1 file changed, 51 insertions(+) diff --git a/Corlib.Extensions/System/Math.T4.tt b/Corlib.Extensions/System/Math.T4.tt index 412ffee3..c752804a 100644 --- a/Corlib.Extensions/System/Math.T4.tt +++ b/Corlib.Extensions/System/Math.T4.tt @@ -3,6 +3,7 @@ <#@ import namespace="System.Linq" #> <#@ import namespace="System.Text" #> <#@ import namespace="System.Collections.Generic" #> +<#@ import namespace="System.Runtime.InteropServices" #> <#@ output extension=".cs" #> #region (c)2010-2042 Hawkynt @@ -40,6 +41,36 @@ using Guard; namespace System; public static partial class MathEx { + +<#foreach (var type in new[]{"sbyte","short","int","long"}){#> + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static <#=type#> ArithmeticShiftLeft(this <#=type#> @this, byte count) => (<#=type#>)(count >= <#=GetSizeInBits(type)-1#> ? 0 : ((<#=GetUnsignedType(type)#>)@this & 0x<#=(1UL << GetSizeInBits(type) - 1).ToString("X")#>) | (((<#=GetUnsignedType(type)#>)@this << count) & 0x<#=((1UL << GetSizeInBits(type) - 1) - 1).ToString("X")#>)); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static <#=type#> ArithmeticShiftRight(this <#=type#> @this, byte count) => (<#=type#>)(count >= <#=GetSizeInBits(type)-1#> ? 0 : @this >> count); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static <#=type#> LogicalShiftLeft(this <#=type#> @this, byte count) => (<#=type#>)((<#=(type=="sbyte"?"byte":"u"+type)#>)@this << count); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static <#=type#> LogicalShiftRight(this <#=type#> @this, byte count) => (<#=type#>)(@this >>> count); + +<#}#> +<#foreach (var type in new[]{"byte","ushort","uint","ulong"}){#> + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static <#=type#> ArithmeticShiftLeft(this <#=type#> @this, byte count) => (<#=type#>)(count >= <#=GetSizeInBits(type)#> ? 0 : @this << count); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static <#=type#> ArithmeticShiftRight(this <#=type#> @this, byte count) => (<#=type#>)(count >= <#=GetSizeInBits(type)#> ? 0 : @this >> count); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static <#=type#> RotateLeft(this <#=type#> @this, byte count) => (<#=type#>)((@this << count) | (@this >> (<#=GetSizeInBits(type)#> - count))); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static <#=type#> RotateRight(this <#=type#> @this, byte count) => (<#=type#>)((@this >> count) | (@this << (<#=GetSizeInBits(type)#> - count))); + +<#}#> + <#foreach (var type in new[]{"byte","sbyte","ushort","short","uint","int","ulong","long"}){#> [MethodImpl(MethodImplOptions.AggressiveInlining)] @@ -504,4 +535,24 @@ public static partial class MathEx { <#+ private static Tuple T(A a,B b){ return(Tuple.Create(a,b)); } private static Tuple T(A a,B b,C c){ return(Tuple.Create(a,b,c)); } + + private static int GetSizeInBits(string type) => type switch { + "byte" => 8, + "sbyte" => 8, + "ushort" => 16, + "short" => 16, + "uint" => 32, + "int" => 32, + "ulong" => 64, + "long" => 64, + _=>throw new NotSupportedException($"Unknown type: {type}") + }; + + private static string GetUnsignedType(string type) => type switch { + "sbyte" => "byte", + "short" => "ushort", + "int" => "uint", + "long" => "ulong", + _=>throw new NotSupportedException($"Unknown type: {type}") + }; #> \ No newline at end of file From ec16cb0d137482c8a630a1b5b62bd974cdb9082d Mon Sep 17 00:00:00 2001 From: Hawkynt Date: Wed, 31 Jul 2024 16:33:16 +0200 Subject: [PATCH 2/6] + tests for arithmetic shifts --- Tests/Corlib.Tests/System/MathTest.cs | 151 +++++++++++++++++++++++++- 1 file changed, 150 insertions(+), 1 deletion(-) diff --git a/Tests/Corlib.Tests/System/MathTest.cs b/Tests/Corlib.Tests/System/MathTest.cs index eae7b5c3..875d8119 100644 --- a/Tests/Corlib.Tests/System/MathTest.cs +++ b/Tests/Corlib.Tests/System/MathTest.cs @@ -8388,9 +8388,10 @@ public void EnumeratePrimes() { ++i; } + Assert.Pass($"Tested the first {i} primes successful"); } - + private static IEnumerable _MinMaxGenerator() { yield return new(new byte[] { 0 }, 0, 0); yield return new(new byte[] { 0, 0 }, 0, 0); @@ -8409,4 +8410,152 @@ public void MinMax(byte[] values, int minValue, int maxValue) { Assert.AreEqual(maxValue, fastMax); } + [Test] + [TestCase(0b00000001, 0, 0b00000001)] + [TestCase(0b00000001, 1, 0b00000010)] + [TestCase(0b00000001, 7, 0b10000000)] + [TestCase(0b00000001, 8, 0b00000000)] + [TestCase(0b00000001, 16, 0b00000000)] + public void ArithmeticShiftLeftByte(byte inp, byte count, byte expected) => Assert.AreEqual(expected, inp.ArithmeticShiftLeft(count)); + + [Test] + [TestCase((sbyte)0b00000001, 0, 0b00000001)] + [TestCase((sbyte)0b00000001, 1, 0b00000010)] + [TestCase((sbyte)0b01000000, 1, 0b00000000)] + [TestCase((sbyte)-(1U << 7), 1, (sbyte)-(1U << 7))] + [TestCase((sbyte)0b00000001, 7, 0b00000000)] + [TestCase((sbyte)0b00000001, 8, 0b00000000)] + [TestCase((sbyte)0b00000001, 16, 0b00000000)] + public void ArithmeticShiftLeftSByte(sbyte inp, byte count, sbyte expected) => Assert.AreEqual(expected, inp.ArithmeticShiftLeft(count)); + + [Test] + [TestCase((ushort)0b0000000000000001, 0, (ushort)0b0000000000000001)] + [TestCase((ushort)0b0000000000000001, 1, (ushort)0b0000000000000010)] + [TestCase((ushort)0b0000000000000001, 15, (ushort)0b1000000000000000)] + [TestCase((ushort)0b0000000000000001, 16, (ushort)0b0000000000000000)] + [TestCase((ushort)0b0000000000000001, 32, (ushort)0b0000000000000000)] + public void ArithmeticShiftLeftWord(ushort inp, byte count, ushort expected) => Assert.AreEqual(expected, inp.ArithmeticShiftLeft(count)); + + [Test] + [TestCase((short)0b0000000000000001, 0, 0b0000000000000001)] + [TestCase((short)0b0000000000000001, 1, 0b0000000000000010)] + [TestCase((short)0b0100000000000000, 1, 0b0000000000000000)] + [TestCase((short)-(1U << 15), 1, (short)-(1U << 15))] + [TestCase((short)0b0000000000000001, 15, 0b0000000000000000)] + [TestCase((short)0b0000000000000001, 16, 0b0000000000000000)] + [TestCase((short)0b0000000000000001, 32, 0b0000000000000000)] + public void ArithmeticShiftLeftShort(short inp, byte count, short expected) => Assert.AreEqual(expected, inp.ArithmeticShiftLeft(count)); + + [Test] + [TestCase((uint)0b00000000000000000000000000000001, 0, (uint)0b00000000000000000000000000000001)] + [TestCase((uint)0b00000000000000000000000000000001, 1, (uint)0b00000000000000000000000000000010)] + [TestCase((uint)0b00000000000000000000000000000001, 31, (uint)0b10000000000000000000000000000000)] + [TestCase((uint)0b00000000000000000000000000000001, 32, (uint)0b00000000000000000000000000000000)] + [TestCase((uint)0b00000000000000000000000000000001, 64, (uint)0b00000000000000000000000000000000)] + public void ArithmeticShiftLeftDWord(uint inp, byte count, uint expected) => Assert.AreEqual(expected, inp.ArithmeticShiftLeft(count)); + + [Test] + [TestCase((int)0b00000000000000000000000000000001, 0, 0b00000000000000000000000000000001)] + [TestCase((int)0b00000000000000000000000000000001, 1, 0b00000000000000000000000000000010)] + [TestCase((int)0b01000000000000000000000000000000, 1, 0b00000000000000000000000000000000)] + [TestCase((int)-(1U << 31), 1, (int)-(1U << 31))] + [TestCase((int)0b00000000000000000000000000000001, 31, 0b00000000000000000000000000000000)] + [TestCase((int)0b00000000000000000000000000000001, 32, 0b00000000000000000000000000000000)] + [TestCase((int)0b00000000000000000000000000000001, 64, 0b00000000000000000000000000000000)] + public void ArithmeticShiftLeftInt(int inp, byte count, int expected) => Assert.AreEqual(expected, inp.ArithmeticShiftLeft(count)); + + [Test] + [TestCase((ulong)0b0000000000000000000000000000000000000000000000000000000000000001, 0, (ulong)0b0000000000000000000000000000000000000000000000000000000000000001)] + [TestCase((ulong)0b0000000000000000000000000000000000000000000000000000000000000001, 1, (ulong)0b0000000000000000000000000000000000000000000000000000000000000010)] + [TestCase((ulong)0b0000000000000000000000000000000000000000000000000000000000000001, 63, (ulong)0b1000000000000000000000000000000000000000000000000000000000000000)] + [TestCase((ulong)0b0000000000000000000000000000000000000000000000000000000000000001, 64, (ulong)0b0000000000000000000000000000000000000000000000000000000000000000)] + [TestCase((ulong)0b0000000000000000000000000000000000000000000000000000000000000001, 128, (ulong)0b0000000000000000000000000000000000000000000000000000000000000000)] + public void ArithmeticShiftLeftQWord(ulong inp, byte count, ulong expected) => Assert.AreEqual(expected, inp.ArithmeticShiftLeft(count)); + + [Test] + [TestCase((long)0b0000000000000000000000000000000000000000000000000000000000000001, 0, 0b0000000000000000000000000000000000000000000000000000000000000001)] + [TestCase((long)0b0000000000000000000000000000000000000000000000000000000000000001, 1, 0b0000000000000000000000000000000000000000000000000000000000000010)] + [TestCase((long)0b0100000000000000000000000000000000000000000000000000000000000000, 1, 0b0000000000000000000000000000000000000000000000000000000000000000)] + [TestCase(unchecked((long)0x8000000000000000L), 1, (unchecked((long)0x8000000000000000L)))] + [TestCase((long)0b00000000000000000000000000000001, 63, 0b0000000000000000000000000000000000000000000000000000000000000000)] + [TestCase((long)0b00000000000000000000000000000001, 64, 0b0000000000000000000000000000000000000000000000000000000000000000)] + [TestCase((long)0b00000000000000000000000000000001, 128, 0b0000000000000000000000000000000000000000000000000000000000000000)] + public void ArithmeticShiftLeftLong(long inp, byte count, long expected) => Assert.AreEqual(expected, inp.ArithmeticShiftLeft(count)); + + [Test] + [TestCase(0b00000001, 0, 0b00000001)] + [TestCase(0b00000010, 1, 0b00000001)] + [TestCase(0b10000000, 7, 0b00000001)] + [TestCase(0b10000000, 8, 0b00000000)] + [TestCase(0b10000000, 16, 0b00000000)] + public void ArithmeticShiftRightByte(byte inp, byte count, byte expected) => Assert.AreEqual(expected, inp.ArithmeticShiftRight(count)); + + [Test] + [TestCase((sbyte)0b00000001, 0, 0b00000001)] + [TestCase((sbyte)0b00000010, 1, 0b00000001)] + [TestCase((sbyte)-(1U << 7), 1, (sbyte)-(1U << 6))] + [TestCase((sbyte)-(1U << 7), 7, 0b00000000)] + [TestCase((sbyte)0b01000000, 6, 0b00000001)] + [TestCase((sbyte)0b01000000, 7, 0b00000000)] + [TestCase((sbyte)0b01000000, 16, 0b00000000)] + public void ArithmeticShiftRightSByte(sbyte inp, byte count, sbyte expected) => Assert.AreEqual(expected, inp.ArithmeticShiftRight(count)); + + [Test] + [TestCase((ushort)0b0000000000000001, 0, (ushort)0b0000000000000001)] + [TestCase((ushort)0b0000000000000010, 1, (ushort)0b0000000000000001)] + [TestCase((ushort)0b1000000000000000, 15, (ushort)0b0000000000000001)] + [TestCase((ushort)0b1000000000000000, 16, (ushort)0b0000000000000000)] + [TestCase((ushort)0b1000000000000000, 32, (ushort)0b0000000000000000)] + public void ArithmeticShiftRightWord(ushort inp, byte count, ushort expected) => Assert.AreEqual(expected, inp.ArithmeticShiftRight(count)); + + [Test] + [TestCase((short)0b0000000000000001, 0, 0b0000000000000001)] + [TestCase((short)0b0000000000000010, 1, 0b0000000000000001)] + [TestCase((short)-(1 << 15), 1, (short)-(1 << 14))] + [TestCase((short)-(1 << 15), 15, 0b0000000000000000)] + [TestCase((short)0b0100000000000000, 14, 0b0000000000000001)] + [TestCase((short)0b0100000000000000, 15, 0b0000000000000000)] + [TestCase((short)0b0100000000000000, 32, 0b0000000000000000)] + public void ArithmeticShiftRightShort(short inp, byte count, short expected) => Assert.AreEqual(expected, inp.ArithmeticShiftRight(count)); + + [Test] + [TestCase((uint)0b00000000000000000000000000000001, 0, (uint)0b00000000000000000000000000000001)] + [TestCase((uint)0b00000000000000000000000000000010, 1, (uint)0b00000000000000000000000000000001)] + [TestCase((uint)0b10000000000000000000000000000000, 31, (uint)0b00000000000000000000000000000001)] + [TestCase((uint)0b10000000000000000000000000000000, 32, (uint)0b00000000000000000000000000000000)] + [TestCase((uint)0b10000000000000000000000000000000, 64, (uint)0b00000000000000000000000000000000)] + public void ArithmeticShiftRightDWord(uint inp, byte count, uint expected) => Assert.AreEqual(expected, inp.ArithmeticShiftRight(count)); + + [Test] + [TestCase((int)0b00000000000000000000000000000001, 0, 0b00000000000000000000000000000001)] + [TestCase((int)0b00000000000000000000000000000010, 1, 0b00000000000000000000000000000001)] + [TestCase((int)-(1U << 31), 1, (int)-(1 << 30))] + [TestCase((int)-(1U << 31), 31, 0b00000000000000000000000000000000)] + [TestCase((int)0b01000000000000000000000000000000, 30, 0b00000000000000000000000000000001)] + [TestCase((int)0b01000000000000000000000000000000, 31, 0b00000000000000000000000000000000)] + [TestCase((int)0b01000000000000000000000000000000, 64, 0b00000000000000000000000000000000)] + public void ArithmeticShiftRightInt(int inp, byte count, int expected) => Assert.AreEqual(expected, inp.ArithmeticShiftRight(count)); + + [Test] + [TestCase((ulong)0b0000000000000000000000000000000000000000000000000000000000000001, 0, (ulong)0b0000000000000000000000000000000000000000000000000000000000000001)] + [TestCase((ulong)0b0000000000000000000000000000000000000000000000000000000000000010, 1, (ulong)0b0000000000000000000000000000000000000000000000000000000000000001)] + [TestCase((ulong)0b1000000000000000000000000000000000000000000000000000000000000000, 63, (ulong)0b0000000000000000000000000000000000000000000000000000000000000001)] + [TestCase((ulong)0b1000000000000000000000000000000000000000000000000000000000000000, 64, (ulong)0b0000000000000000000000000000000000000000000000000000000000000000)] + [TestCase((ulong)0b1000000000000000000000000000000000000000000000000000000000000000, 128, (ulong)0b0000000000000000000000000000000000000000000000000000000000000000)] + public void ArithmeticShiftRightQWord(ulong inp, byte count, ulong expected) => Assert.AreEqual(expected, inp.ArithmeticShiftRight(count)); + + [Test] + [TestCase((long)0b0000000000000000000000000000000000000000000000000000000000000001, 0, 0b0000000000000000000000000000000000000000000000000000000000000001)] + [TestCase((long)0b0000000000000000000000000000000000000000000000000000000000000010, 1, 0b0000000000000000000000000000000000000000000000000000000000000001)] + [TestCase(unchecked((long)0x8000000000000000), 1, unchecked((long)0xC000000000000000))] + [TestCase(unchecked((long)0x4000000000000000), 62, 0b00000000000000000000000000000001)] + [TestCase(unchecked((long)0x4000000000000000), 63, 0b00000000000000000000000000000000)] + [TestCase(unchecked((long)0x4000000000000000), 128, 0b00000000000000000000000000000000)] + public void ArithmeticShiftRightLong(long inp, byte count, long expected) => Assert.AreEqual(expected, inp.ArithmeticShiftRight(count)); + + // TODO: logic left shift + // TODO: logic right shift + // TODO: left rotate + // TODO: right rotate + } \ No newline at end of file From bc01ee4b546416b57ed6866598f253fde500b390 Mon Sep 17 00:00:00 2001 From: Hawkynt Date: Tue, 6 Aug 2024 15:00:33 +0200 Subject: [PATCH 3/6] + left rotation tests --- Corlib.Extensions/System/Math.T4.tt | 10 +++++-- Tests/Corlib.Tests/System/MathTest.cs | 40 +++++++++++++++++++++++++-- 2 files changed, 46 insertions(+), 4 deletions(-) diff --git a/Corlib.Extensions/System/Math.T4.tt b/Corlib.Extensions/System/Math.T4.tt index c752804a..9af4327e 100644 --- a/Corlib.Extensions/System/Math.T4.tt +++ b/Corlib.Extensions/System/Math.T4.tt @@ -64,10 +64,16 @@ public static partial class MathEx { public static <#=type#> ArithmeticShiftRight(this <#=type#> @this, byte count) => (<#=type#>)(count >= <#=GetSizeInBits(type)#> ? 0 : @this >> count); [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static <#=type#> RotateLeft(this <#=type#> @this, byte count) => (<#=type#>)((@this << count) | (@this >> (<#=GetSizeInBits(type)#> - count))); + public static <#=type#> RotateLeft(this <#=type#> @this, byte count) { + count &= <#=GetSizeInBits(type) - 1#>; + return (<#=type#>)((@this << count) | (@this >> (<#=GetSizeInBits(type)#> - count))); + } [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static <#=type#> RotateRight(this <#=type#> @this, byte count) => (<#=type#>)((@this >> count) | (@this << (<#=GetSizeInBits(type)#> - count))); + public static <#=type#> RotateRight(this <#=type#> @this, byte count) { + count &= <#=GetSizeInBits(type) - 1#>; + return (<#=type#>)((@this >> count) | (@this << (<#=GetSizeInBits(type)#> - count))); + } <#}#> diff --git a/Tests/Corlib.Tests/System/MathTest.cs b/Tests/Corlib.Tests/System/MathTest.cs index 875d8119..078a4787 100644 --- a/Tests/Corlib.Tests/System/MathTest.cs +++ b/Tests/Corlib.Tests/System/MathTest.cs @@ -8552,10 +8552,46 @@ public void MinMax(byte[] values, int minValue, int maxValue) { [TestCase(unchecked((long)0x4000000000000000), 63, 0b00000000000000000000000000000000)] [TestCase(unchecked((long)0x4000000000000000), 128, 0b00000000000000000000000000000000)] public void ArithmeticShiftRightLong(long inp, byte count, long expected) => Assert.AreEqual(expected, inp.ArithmeticShiftRight(count)); - + // TODO: logic left shift // TODO: logic right shift - // TODO: left rotate + + [Test] + [TestCase((byte)0b00000001, 0, (byte)0b00000001)] + [TestCase((byte)0b00000001, 1, (byte)0b00000010)] + [TestCase((byte)0b10000001, 1, (byte)0b00000011)] + [TestCase((byte)0b00000001, 7, (byte)0b10000000)] + [TestCase((byte)0b00000001, 8, (byte)0b00000001)] + [TestCase((byte)0b00000001, 16, (byte)0b00000001)] + public void RotateLeftByte(byte inp, byte count, byte expected) => Assert.AreEqual(expected, inp.RotateLeft(count)); + + [Test] + [TestCase((ushort)0b0000000000000001, 0, (ushort)0b0000000000000001)] + [TestCase((ushort)0b0000000000000001, 1, (ushort)0b0000000000000010)] + [TestCase((ushort)0b1000000000000001, 1, (ushort)0b0000000000000011)] + [TestCase((ushort)0b0000000000000001, 15, (ushort)0b1000000000000000)] + [TestCase((ushort)0b0000000000000001, 16, (ushort)0b0000000000000001)] + [TestCase((ushort)0b0000000000000001, 32, (ushort)0b0000000000000001)] + public void RotateLeftWord(ushort inp, byte count, ushort expected) => Assert.AreEqual(expected, inp.RotateLeft(count)); + + [Test] + [TestCase((uint)0b00000000000000000000000000000001, 0, (uint)0b00000000000000000000000000000001)] + [TestCase((uint)0b00000000000000000000000000000001, 1, (uint)0b00000000000000000000000000000010)] + [TestCase((uint)0b10000000000000000000000000000001, 1, (uint)0b00000000000000000000000000000011)] + [TestCase((uint)0b00000000000000000000000000000001, 31, (uint)0b10000000000000000000000000000000)] + [TestCase((uint)0b00000000000000000000000000000001, 32, (uint)0b00000000000000000000000000000001)] + [TestCase((uint)0b00000000000000000000000000000001, 64, (uint)0b00000000000000000000000000000001)] + public void RotateLeftDWord(uint inp, byte count, uint expected) => Assert.AreEqual(expected, inp.RotateLeft(count)); + + [Test] + [TestCase((ulong)0b0000000000000000000000000000000000000000000000000000000000000001, 0, (ulong)0b0000000000000000000000000000000000000000000000000000000000000001)] + [TestCase((ulong)0b0000000000000000000000000000000000000000000000000000000000000001, 1, (ulong)0b0000000000000000000000000000000000000000000000000000000000000010)] + [TestCase((ulong)0b1000000000000000000000000000000000000000000000000000000000000001, 1, (ulong)0b0000000000000000000000000000000000000000000000000000000000000011)] + [TestCase((ulong)0b0000000000000000000000000000000000000000000000000000000000000001, 63, (ulong)0b1000000000000000000000000000000000000000000000000000000000000000)] + [TestCase((ulong)0b0000000000000000000000000000000000000000000000000000000000000001, 64, (ulong)0b0000000000000000000000000000000000000000000000000000000000000001)] + [TestCase((ulong)0b0000000000000000000000000000000000000000000000000000000000000001, 128, (ulong)0b0000000000000000000000000000000000000000000000000000000000000001)] + public void RotateLeftQWord(ulong inp, byte count, ulong expected) => Assert.AreEqual(expected, inp.RotateLeft(count)); + // TODO: right rotate } \ No newline at end of file From 310ac5fdb15dd840b13a8f2d7e6974d6d467d4f1 Mon Sep 17 00:00:00 2001 From: Hawkynt Date: Tue, 6 Aug 2024 15:24:46 +0200 Subject: [PATCH 4/6] + tests for rotate right --- Tests/Corlib.Tests/System/MathTest.cs | 38 +++++++++++++++++++++++++-- 1 file changed, 36 insertions(+), 2 deletions(-) diff --git a/Tests/Corlib.Tests/System/MathTest.cs b/Tests/Corlib.Tests/System/MathTest.cs index 078a4787..e92d7c81 100644 --- a/Tests/Corlib.Tests/System/MathTest.cs +++ b/Tests/Corlib.Tests/System/MathTest.cs @@ -8591,7 +8591,41 @@ public void MinMax(byte[] values, int minValue, int maxValue) { [TestCase((ulong)0b0000000000000000000000000000000000000000000000000000000000000001, 64, (ulong)0b0000000000000000000000000000000000000000000000000000000000000001)] [TestCase((ulong)0b0000000000000000000000000000000000000000000000000000000000000001, 128, (ulong)0b0000000000000000000000000000000000000000000000000000000000000001)] public void RotateLeftQWord(ulong inp, byte count, ulong expected) => Assert.AreEqual(expected, inp.RotateLeft(count)); - - // TODO: right rotate + + [Test] + [TestCase((byte)0b00000001, 0, (byte)0b00000001)] + [TestCase((byte)0b00000010, 1, (byte)0b00000001)] + [TestCase((byte)0b10000001, 1, (byte)0b11000000)] + [TestCase((byte)0b10000000, 7, (byte)0b00000001)] + [TestCase((byte)0b10000000, 8, (byte)0b10000000)] + [TestCase((byte)0b10000000, 16, (byte)0b10000000)] + public void RotateRightByte(byte inp, byte count, byte expected) => Assert.AreEqual(expected, inp.RotateRight(count)); + + [Test] + [TestCase((ushort)0b0000000000000001, 0, (ushort)0b0000000000000001)] + [TestCase((ushort)0b0000000000000010, 1, (ushort)0b0000000000000001)] + [TestCase((ushort)0b1000000000000001, 1, (ushort)0b1100000000000000)] + [TestCase((ushort)0b1000000000000000, 15, (ushort)0b0000000000000001)] + [TestCase((ushort)0b1000000000000000, 16, (ushort)0b1000000000000000)] + [TestCase((ushort)0b1000000000000000, 32, (ushort)0b1000000000000000)] + public void RotateRightWord(ushort inp, byte count, ushort expected) => Assert.AreEqual(expected, inp.RotateRight(count)); + + [Test] + [TestCase((uint)0b00000000000000000000000000000001, 0, (uint)0b00000000000000000000000000000001)] + [TestCase((uint)0b00000000000000000000000000000010, 1, (uint)0b00000000000000000000000000000001)] + [TestCase((uint)0b10000000000000000000000000000001, 1, (uint)0b11000000000000000000000000000000)] + [TestCase((uint)0b10000000000000000000000000000000, 31, (uint)0b00000000000000000000000000000001)] + [TestCase((uint)0b10000000000000000000000000000000, 32, (uint)0b10000000000000000000000000000000)] + [TestCase((uint)0b10000000000000000000000000000000, 64, (uint)0b10000000000000000000000000000000)] + public void RotateRightDWord(uint inp, byte count, uint expected) => Assert.AreEqual(expected, inp.RotateRight(count)); + + [Test] + [TestCase((ulong)0b0000000000000000000000000000000000000000000000000000000000000001, 0, (ulong)0b0000000000000000000000000000000000000000000000000000000000000001)] + [TestCase((ulong)0b0000000000000000000000000000000000000000000000000000000000000010, 1, (ulong)0b0000000000000000000000000000000000000000000000000000000000000001)] + [TestCase((ulong)0b1000000000000000000000000000000000000000000000000000000000000001, 1, (ulong)0b1100000000000000000000000000000000000000000000000000000000000000)] + [TestCase((ulong)0b1000000000000000000000000000000000000000000000000000000000000000, 63, (ulong)0b0000000000000000000000000000000000000000000000000000000000000001)] + [TestCase((ulong)0b1000000000000000000000000000000000000000000000000000000000000000, 64, (ulong)0b1000000000000000000000000000000000000000000000000000000000000000)] + [TestCase((ulong)0b1000000000000000000000000000000000000000000000000000000000000000, 128, (ulong)0b1000000000000000000000000000000000000000000000000000000000000000)] + public void RotateRightQWord(ulong inp, byte count, ulong expected) => Assert.AreEqual(expected, inp.RotateRight(count)); } \ No newline at end of file From 325e01157f5bbb852e5705d969d3f44ba50fcea8 Mon Sep 17 00:00:00 2001 From: Hawkynt Date: Tue, 6 Aug 2024 15:57:56 +0200 Subject: [PATCH 5/6] + logical shift left tests --- Corlib.Extensions/System/Math.T4.tt | 4 +-- Tests/Corlib.Tests/System/MathTest.cs | 37 ++++++++++++++++++++++++++- 2 files changed, 38 insertions(+), 3 deletions(-) diff --git a/Corlib.Extensions/System/Math.T4.tt b/Corlib.Extensions/System/Math.T4.tt index 9af4327e..8c1ca5c1 100644 --- a/Corlib.Extensions/System/Math.T4.tt +++ b/Corlib.Extensions/System/Math.T4.tt @@ -50,10 +50,10 @@ public static partial class MathEx { public static <#=type#> ArithmeticShiftRight(this <#=type#> @this, byte count) => (<#=type#>)(count >= <#=GetSizeInBits(type)-1#> ? 0 : @this >> count); [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static <#=type#> LogicalShiftLeft(this <#=type#> @this, byte count) => (<#=type#>)((<#=(type=="sbyte"?"byte":"u"+type)#>)@this << count); + public static <#=type#> LogicalShiftLeft(this <#=type#> @this, byte count) => (<#=type#>)ArithmeticShiftLeft((<#=(type=="sbyte"?"byte":"u"+type)#>)@this, count); [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static <#=type#> LogicalShiftRight(this <#=type#> @this, byte count) => (<#=type#>)(@this >>> count); + public static <#=type#> LogicalShiftRight(this <#=type#> @this, byte count) => (<#=type#>)ArithmeticShiftRight(@this, count); <#}#> <#foreach (var type in new[]{"byte","ushort","uint","ulong"}){#> diff --git a/Tests/Corlib.Tests/System/MathTest.cs b/Tests/Corlib.Tests/System/MathTest.cs index e92d7c81..ddb44416 100644 --- a/Tests/Corlib.Tests/System/MathTest.cs +++ b/Tests/Corlib.Tests/System/MathTest.cs @@ -8553,7 +8553,42 @@ public void MinMax(byte[] values, int minValue, int maxValue) { [TestCase(unchecked((long)0x4000000000000000), 128, 0b00000000000000000000000000000000)] public void ArithmeticShiftRightLong(long inp, byte count, long expected) => Assert.AreEqual(expected, inp.ArithmeticShiftRight(count)); - // TODO: logic left shift + [Test] + [TestCase(unchecked((sbyte)0b00000001),0, unchecked((sbyte)0b00000001))] + [TestCase(unchecked((sbyte)0b00000001), 1, unchecked((sbyte)0b00000010))] + [TestCase(unchecked((sbyte)0b01000000), 1, unchecked((sbyte)0b10000000))] + [TestCase(unchecked((sbyte)0b01000000), 2, unchecked((sbyte)0b00000000))] + [TestCase(unchecked((sbyte)0b00000001), 8, unchecked((sbyte)0b00000000))] + [TestCase(unchecked((sbyte)0b00000001), 16, unchecked((sbyte)0b00000000))] + public void LogicalShiftLeftSByte(sbyte inp, byte count, sbyte expected) => Assert.AreEqual(expected, inp.LogicalShiftLeft(count)); + + [Test] + [TestCase(unchecked((short)0b0000000000000001), 0, unchecked((short)0b0000000000000001))] + [TestCase(unchecked((short)0b0000000000000001), 1, unchecked((short)0b0000000000000010))] + [TestCase(unchecked((short)0b0100000000000000), 1, unchecked((short)0b1000000000000000))] + [TestCase(unchecked((short)0b0100000000000000), 2, unchecked((short)0b0000000000000000))] + [TestCase(unchecked((short)0b0000000000000001), 16, unchecked((short)0b0000000000000000))] + [TestCase(unchecked((short)0b0000000000000001), 32, unchecked((short)0b0000000000000000))] + public void LogicalShiftLeftShort(short inp, byte count, short expected) => Assert.AreEqual(expected, inp.LogicalShiftLeft(count)); + + [Test] + [TestCase(unchecked((int)0b00000000000000000000000000000001), 0, unchecked((int)0b00000000000000000000000000000001))] + [TestCase(unchecked((int)0b00000000000000000000000000000001), 1, unchecked((int)0b00000000000000000000000000000010))] + [TestCase(unchecked((int)0b01000000000000000000000000000000), 1, unchecked((int)0b10000000000000000000000000000000))] + [TestCase(unchecked((int)0b01000000000000000000000000000000), 2, unchecked((int)0b00000000000000000000000000000000))] + [TestCase(unchecked((int)0b00000000000000000000000000000001), 32, unchecked((int)0b00000000000000000000000000000000))] + [TestCase(unchecked((int)0b00000000000000000000000000000001), 64, unchecked((int)0b00000000000000000000000000000000))] + public void LogicalShiftLeftInt(int inp, byte count, int expected) => Assert.AreEqual(expected, inp.LogicalShiftLeft(count)); + + [Test] + [TestCase(unchecked((long)0b0000000000000000000000000000000000000000000000000000000000000001), 0, unchecked((long)0b0000000000000000000000000000000000000000000000000000000000000001))] + [TestCase(unchecked((long)0b0000000000000000000000000000000000000000000000000000000000000001), 1, unchecked((long)0b0000000000000000000000000000000000000000000000000000000000000010))] + [TestCase(unchecked((long)0b0100000000000000000000000000000000000000000000000000000000000000), 1, unchecked((long)0b1000000000000000000000000000000000000000000000000000000000000000))] + [TestCase(unchecked((long)0b0100000000000000000000000000000000000000000000000000000000000000), 2, unchecked((long)0b0000000000000000000000000000000000000000000000000000000000000000))] + [TestCase(unchecked((long)0b0000000000000000000000000000000000000000000000000000000000000001), 64, unchecked((long)0b0000000000000000000000000000000000000000000000000000000000000000))] + [TestCase(unchecked((long)0b0000000000000000000000000000000000000000000000000000000000000001), 128, unchecked((long)0b0000000000000000000000000000000000000000000000000000000000000000))] + public void LogicalShiftLeftLong(long inp, byte count, long expected) => Assert.AreEqual(expected, inp.LogicalShiftLeft(count)); + // TODO: logic right shift [Test] From eb1fd4b8038d4f0ccbea99e9677c20e8c41890eb Mon Sep 17 00:00:00 2001 From: Hawkynt Date: Fri, 9 Aug 2024 13:34:56 +0200 Subject: [PATCH 6/6] + LSR tests --- Corlib.Extensions/System/Math.T4.tt | 2 +- Tests/Corlib.Tests/System/MathTest.cs | 36 ++++++++++++++++++++++++++- 2 files changed, 36 insertions(+), 2 deletions(-) diff --git a/Corlib.Extensions/System/Math.T4.tt b/Corlib.Extensions/System/Math.T4.tt index 8c1ca5c1..38d5797f 100644 --- a/Corlib.Extensions/System/Math.T4.tt +++ b/Corlib.Extensions/System/Math.T4.tt @@ -53,7 +53,7 @@ public static partial class MathEx { public static <#=type#> LogicalShiftLeft(this <#=type#> @this, byte count) => (<#=type#>)ArithmeticShiftLeft((<#=(type=="sbyte"?"byte":"u"+type)#>)@this, count); [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static <#=type#> LogicalShiftRight(this <#=type#> @this, byte count) => (<#=type#>)ArithmeticShiftRight(@this, count); + public static <#=type#> LogicalShiftRight(this <#=type#> @this, byte count) => (<#=type#>)ArithmeticShiftRight((<#=(type=="sbyte"?"byte":"u"+type)#>)@this, count); <#}#> <#foreach (var type in new[]{"byte","ushort","uint","ulong"}){#> diff --git a/Tests/Corlib.Tests/System/MathTest.cs b/Tests/Corlib.Tests/System/MathTest.cs index ddb44416..09c9232e 100644 --- a/Tests/Corlib.Tests/System/MathTest.cs +++ b/Tests/Corlib.Tests/System/MathTest.cs @@ -8589,7 +8589,41 @@ public void MinMax(byte[] values, int minValue, int maxValue) { [TestCase(unchecked((long)0b0000000000000000000000000000000000000000000000000000000000000001), 128, unchecked((long)0b0000000000000000000000000000000000000000000000000000000000000000))] public void LogicalShiftLeftLong(long inp, byte count, long expected) => Assert.AreEqual(expected, inp.LogicalShiftLeft(count)); - // TODO: logic right shift + [Test] + [TestCase(unchecked((sbyte)0b00000001), 0, unchecked((sbyte)0b00000001))] + [TestCase(unchecked((sbyte)0b00000010), 1, unchecked((sbyte)0b00000001))] + [TestCase(unchecked((sbyte)0b10000000), 1, unchecked((sbyte)0b01000000))] + [TestCase(unchecked((sbyte)0b00000010), 2, unchecked((sbyte)0b00000000))] + [TestCase(unchecked((sbyte)0b10000000), 8, unchecked((sbyte)0b00000000))] + [TestCase(unchecked((sbyte)0b10000000), 16, unchecked((sbyte)0b00000000))] + public void LogicalShiftRightSByte(sbyte inp, byte count, sbyte expected) => Assert.AreEqual(expected, inp.LogicalShiftRight(count)); + + [Test] + [TestCase(unchecked((short)0b0000000000000001), 0, unchecked((short)0b0000000000000001))] + [TestCase(unchecked((short)0b0000000000000010), 1, unchecked((short)0b0000000000000001))] + [TestCase(unchecked((short)0b1000000000000000), 1, unchecked((short)0b0100000000000000))] + [TestCase(unchecked((short)0b0000000000000010), 2, unchecked((short)0b0000000000000000))] + [TestCase(unchecked((short)0b1000000000000000), 16, unchecked((short)0b0000000000000000))] + [TestCase(unchecked((short)0b1000000000000000), 32, unchecked((short)0b0000000000000000))] + public void LogicalShiftRightShort(short inp, byte count, short expected) => Assert.AreEqual(expected, inp.LogicalShiftRight(count)); + + [Test] + [TestCase(unchecked((int)0b00000000000000000000000000000001), 0, unchecked((int)0b00000000000000000000000000000001))] + [TestCase(unchecked((int)0b00000000000000000000000000000010), 1, unchecked((int)0b00000000000000000000000000000001))] + [TestCase(unchecked((int)0b10000000000000000000000000000000), 1, unchecked((int)0b01000000000000000000000000000000))] + [TestCase(unchecked((int)0b00000000000000000000000000000010), 2, unchecked((int)0b00000000000000000000000000000000))] + [TestCase(unchecked((int)0b10000000000000000000000000000000), 32, unchecked((int)0b00000000000000000000000000000000))] + [TestCase(unchecked((int)0b10000000000000000000000000000000), 64, unchecked((int)0b00000000000000000000000000000000))] + public void LogicalShiftRightInt(int inp, byte count, int expected) => Assert.AreEqual(expected, inp.LogicalShiftRight(count)); + + [Test] + [TestCase(unchecked((long)0b0000000000000000000000000000000000000000000000000000000000000001), 0, unchecked((long)0b0000000000000000000000000000000000000000000000000000000000000001))] + [TestCase(unchecked((long)0b0000000000000000000000000000000000000000000000000000000000000010), 1, unchecked((long)0b0000000000000000000000000000000000000000000000000000000000000001))] + [TestCase(unchecked((long)0b1000000000000000000000000000000000000000000000000000000000000000), 1, unchecked((long)0b0100000000000000000000000000000000000000000000000000000000000000))] + [TestCase(unchecked((long)0b0000000000000000000000000000000000000000000000000000000000000010), 2, unchecked((long)0b0000000000000000000000000000000000000000000000000000000000000000))] + [TestCase(unchecked((long)0b1000000000000000000000000000000000000000000000000000000000000000), 64, unchecked((long)0b0000000000000000000000000000000000000000000000000000000000000000))] + [TestCase(unchecked((long)0b1000000000000000000000000000000000000000000000000000000000000000), 128, unchecked((long)0b0000000000000000000000000000000000000000000000000000000000000000))] + public void LogicalShiftRightLong(long inp, byte count, long expected) => Assert.AreEqual(expected, inp.LogicalShiftRight(count)); [Test] [TestCase((byte)0b00000001, 0, (byte)0b00000001)]