RotateMe

CSharp · Console

/Program.cs

using System;
using System.Numerics;

public static class BinaryIntegerConstants<T>
	where T : IBinaryInteger<T>
{
	public static T Log2Size { get; }

	public static T Nine { get; }

	public static T Size { get; }

	public static T Ten { get; }

	static BinaryIntegerConstants()
	{
		var size = T.PopCount(value: T.AllBitsSet);
		Log2Size = T.Log2(value: size);
		Nine = T.CreateChecked(value: 9U);
		Size = size;
		Ten = T.CreateChecked(value: 10U);
	}
}

public static class BinaryIntegerFunctions
{
	public static T Exponentiate<T>(this T value, T exponent)
		where T : IBinaryInteger<T>
	{
		var result = T.One;
		do
		{
			if (T.IsOddInteger(value: exponent))
			{
				result *= value;
			}

			exponent >>= 1;
			value *= value;
		}
		while (T.Zero < exponent);
		return result;
	}

	public static T LogarithmBase10<T>(this T value)
		where T : IBinaryInteger<T>
	{
		var bitCount = int.CreateChecked(value: BinaryIntegerConstants<T>.Size);
		value = T.Abs(value: value);
		return bitCount switch
		{
#if !FORCE_SOFTWARE_LOG10
			8 => (T.CreateTruncating(value: ((uint)MathF.Log10(x: uint.CreateTruncating(value: value)))) + T.One),
			16 => (T.CreateTruncating(value: ((uint)MathF.Log10(x: uint.CreateTruncating(value: value)))) + T.One),
			32 => (T.CreateTruncating(value: ((uint)Math.Log10(d: uint.CreateTruncating(value: value)))) + T.One),
#endif
			_ => SoftwareImplementation(value: value),
		};
		static T SoftwareImplementation(T value)
		{
			var quotient = value;
			var result = T.Zero;
			do
			{
				quotient /= BinaryIntegerConstants<T>.Ten;
				++result;
			}
			while (T.Zero < quotient);
			return result;
		}
	}
}

public static class MyExtensions
{
	public static T RotateDigitsLeft<T>(this T value, int count)
		where T : IBinaryInteger<T>
	{
		var absoluteValue = T.Abs(value: value);
		var countAsT = T.CreateTruncating(value: count);
		var digitCount = absoluteValue.LogarithmBase10();
		// This is the one small change.
		if (count < 0)
			countAsT += digitCount;
		var factor = BinaryIntegerConstants<T>.Ten.Exponentiate(exponent: (digitCount - countAsT));
		var endDigits = (absoluteValue / factor);
		var startDigits = (absoluteValue - (endDigits * factor));
		return T.CopySign(sign: value, value: ((startDigits * BinaryIntegerConstants<T>.Ten.Exponentiate(exponent: countAsT)) + endDigits));
	}
}

public class Program
{
	public static void Main()
	{
		int value = -12345;
		int resultLeft = value.RotateDigitsLeft(1);
		int resultRight = value.RotateDigitsLeft(-1);
		Console.WriteLine($"{value} : {resultLeft} : {resultRight}");
	}
}
;