Number
Represents Generic Math extensions.
using System;
using System.ComponentModel;
using System.Numerics;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Intrinsics;
namespace DotNext.Numerics
{
public static class Number
{
public static TResult FromBits<TResult>(this ReadOnlySpan<bool> bits) where TResult : struct, IBinaryInteger<TResult>
{
TResult val = TResult.get_Zero();
for (int i = 0; i < bits.Length; i++) {
if (bits[i])
val |= TResult.get_One() << i;
}
return val;
}
public unsafe static void GetBits<[IsUnmanaged] T>(this T value, Span<bool> bits) where T : struct, IBinaryInteger<T>
{
int num = sizeof(T) * 8;
ArgumentOutOfRangeException.ThrowIfLessThan<uint>((uint)bits.Length, (uint)num, "bits");
if (Vector256.get_IsHardwareAccelerated() && int.IsEvenInteger(sizeof(T)))
Get16Bits(ref Unsafe.As<T, byte>(ref value), (IntPtr)sizeof(T), ref MemoryMarshal.GetReference(bits));
else if (Vector128.get_IsHardwareAccelerated()) {
Get8Bits(ref Unsafe.As<T, byte>(ref value), (IntPtr)sizeof(T), ref MemoryMarshal.GetReference(bits));
} else {
for (int i = 0; i < num; i++) {
bits[i] = ((value & (T.get_One() << i)) != T.get_Zero());
}
}
}
private unsafe static void Get8Bits(ref byte input, IntPtr length, ref bool output)
{
for (IntPtr intPtr = (IntPtr)0; (long)intPtr < (long)length; intPtr = (IntPtr)(void*)((long)intPtr + 1)) {
Get8Bits(Vector128.Create(Unsafe.Add<byte>(ref input, intPtr)), ref Unsafe.Add<bool>(ref output, (IntPtr)(void*)((long)intPtr * 8)));
}
}
private static void Get8Bits(Vector128<byte> input, ref bool output)
{
Vector128<byte> vector = Vector128.Create((byte)1, (byte)1, (byte)1, (byte)1, (byte)1, (byte)1, (byte)1, (byte)1, (byte)1, (byte)1, (byte)1, (byte)1, (byte)1, (byte)1, (byte)1, (byte)1);
Vector128<byte> vector2 = Vector128.Create(1, 2, 4, 8, 16, 32, 64, 128, 0, 0, 0, 0, 0, 0, 0, 0);
Vector64.StoreUnsafe<byte>(Vector128.Min<byte>(input & vector2, vector).GetLower(), ref Unsafe.As<bool, byte>(ref output));
}
private unsafe static void Get16Bits(ref byte input, IntPtr length, ref bool output)
{
for (IntPtr intPtr = (IntPtr)0; (long)intPtr < (long)length; intPtr = (IntPtr)(void*)((long)intPtr + 2)) {
Get16Bits(Vector256.Create(Unsafe.ReadUnaligned<ushort>(ref Unsafe.Add<byte>(ref input, intPtr))), ref Unsafe.Add<bool>(ref output, (IntPtr)(void*)((long)intPtr * 8)));
}
}
private static void Get16Bits(Vector256<ushort> input, ref bool output)
{
Vector256<ushort> vector = Vector256.Create((ushort)1, (ushort)1, (ushort)1, (ushort)1, (ushort)1, (ushort)1, (ushort)1, (ushort)1, (ushort)1, (ushort)1, (ushort)1, (ushort)1, (ushort)1, (ushort)1, (ushort)1, (ushort)1);
Vector256<ushort> vector2 = Vector256.Create(1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048, 4096, 8192, 16384, 32768);
Vector256<byte> vector3 = Vector256.Create(0, 2, 4, 6, 8, 10, 12, 14, byte.MaxValue, byte.MaxValue, byte.MaxValue, byte.MaxValue, byte.MaxValue, byte.MaxValue, byte.MaxValue, byte.MaxValue, 16, 18, 20, 22, 24, 26, 28, 30, byte.MaxValue, byte.MaxValue, byte.MaxValue, byte.MaxValue, byte.MaxValue, byte.MaxValue, byte.MaxValue, byte.MaxValue);
Vector256<byte> vector4 = Vector256.Shuffle(Vector256.Min<ushort>(input & vector2, vector).AsByte(), vector3);
Vector64.StoreUnsafe<byte>(vector4.GetLower().GetLower(), ref Unsafe.As<bool, byte>(ref output));
Vector64.StoreUnsafe<byte>(vector4.GetUpper().GetLower(), ref Unsafe.Add<byte>(ref Unsafe.As<bool, byte>(ref output), 8));
}
[NullableContext(1)]
public static bool IsSigned<T>() where T : INumberBase<T>
{
return T.IsNegative(-T.get_One());
}
[NullableContext(1)]
public static int GetMaxByteCount<T>() where T : IBinaryInteger<T>
{
if (!typeof(T).IsPrimitive)
return T.get_AllBitsSet().GetByteCount();
return Unsafe.SizeOf<T>();
}
public static TOutput Normalize<TInput, TOutput>(this TInput value, TInput min, TInput max) where TInput : struct, INumberBase<TInput>, IComparisonOperators<TInput, TInput, bool> where TOutput : struct, IFloatingPoint<TOutput>
{
TOutput val = TOutput.CreateChecked<TInput>(value);
TInput val2;
if (value > TInput.get_Zero())
val2 = max;
else {
val2 = min;
val = -val;
}
return val / TOutput.CreateChecked<TInput>(val2);
}
[CLSCompliant(false)]
public static double Normalize(this ulong value)
{
return BitConverter.UInt64BitsToDouble(9007199254740991 & value) / BitConverter.UInt64BitsToDouble(9007199254740992);
}
public static double Normalize(this long value)
{
return ((ulong)value).Normalize();
}
[CLSCompliant(false)]
public static float Normalize(this uint value)
{
return BitConverter.UInt32BitsToSingle(16777215 & value) / BitConverter.UInt32BitsToSingle(16777216);
}
public static float Normalize(this int value)
{
return ((uint)value).Normalize();
}
public static bool IsPrime<T>(T value) where T : struct, IBinaryInteger<T>, ISignedNumber<T>
{
ArgumentOutOfRangeException.ThrowIfNegativeOrZero<T>(value, "value");
if (value == T.get_One())
return false;
T val = T.get_One() << 1;
if ((value & T.get_One()) != T.get_Zero()) {
T val2 = val + T.get_One();
T val3 = <IsPrime>g__Sqrt|13_0(value);
while (val2 <= val3) {
if (value % val2 == T.get_Zero())
return false;
val2 += val;
}
return true;
}
return value == val;
}
[EditorBrowsable(EditorBrowsableState.Never)]
public static T GetPrime<T>(T lowerBound, ReadOnlySpan<T> cachedPrimes = default(ReadOnlySpan<T>)) where T : struct, IBinaryInteger<T>, ISignedNumber<T>, IMinMaxValue<T>
{
ArgumentOutOfRangeException.ThrowIfNegativeOrZero<T>(lowerBound, "lowerBound");
if (<GetPrime>g__TryGetFromTable|14_0(cachedPrimes, lowerBound, out T result))
return result;
result = (lowerBound | T.get_One());
while (result < T.get_MaxValue()) {
if (IsPrime(result))
return result;
result += T.get_One() + T.get_One();
}
throw new OverflowException();
}
}
}