CSharp · Console
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}");
}
}