-
Notifications
You must be signed in to change notification settings - Fork 5
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Initial code commit, forked from: https://github.com/Konard/LinksPlat…
- Loading branch information
Showing
14 changed files
with
626 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
namespace Platform.Numbers | ||
{ | ||
public static class ArithmeticExtensions | ||
{ | ||
public static T Decrement<T>(this ref T x) where T : struct => x = ArithmeticHelpers<T>.Decrement(x); | ||
public static T Increment<T>(this ref T x) where T : struct => x = ArithmeticHelpers<T>.Increment(x); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
namespace Platform.Numbers | ||
{ | ||
public class ArithmeticHelpers | ||
{ | ||
public static T Add<T>(T x, T y) => ArithmeticHelpers<T>.Add(x, y); | ||
public static T And<T>(T x, T y) => ArithmeticHelpers<T>.And(x, y); | ||
public static T Increment<T>(T x) => ArithmeticHelpers<T>.Increment(x); | ||
public static T Subtract<T>(T x, T y) => ArithmeticHelpers<T>.Subtract(x, y); | ||
public static T Subtract<T>(Integer<T> x, Integer<T> y) => ArithmeticHelpers<T>.Subtract(x, y); | ||
public static T Decrement<T>(T x) => ArithmeticHelpers<T>.Decrement(x); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,70 @@ | ||
using System; | ||
using Platform.Reflection; | ||
using Platform.Reflection.Sigil; | ||
|
||
// ReSharper disable StaticFieldInGenericType | ||
|
||
namespace Platform.Numbers | ||
{ | ||
public class ArithmeticHelpers<T> | ||
{ | ||
public static readonly Func<T, T, T> Add; | ||
public static readonly Func<T, T, T> And; | ||
public static readonly Func<T, T> Increment; | ||
public static readonly Func<T, T, T> Subtract; | ||
public static readonly Func<T, T> Decrement; | ||
|
||
static ArithmeticHelpers() | ||
{ | ||
DelegateHelpers.Compile(out Add, emiter => | ||
{ | ||
if (!CachedTypeInfo<T>.IsNumeric) | ||
throw new NotSupportedException(); | ||
|
||
emiter.LoadArguments(0, 1); | ||
emiter.Add(); | ||
emiter.Return(); | ||
}); | ||
|
||
DelegateHelpers.Compile(out And, emiter => | ||
{ | ||
if (!CachedTypeInfo<T>.IsNumeric) | ||
throw new NotSupportedException(); | ||
|
||
emiter.LoadArguments(0, 1); | ||
emiter.And(); | ||
emiter.Return(); | ||
}); | ||
|
||
DelegateHelpers.Compile(out Increment, emiter => | ||
{ | ||
if (!CachedTypeInfo<T>.IsNumeric) | ||
throw new NotSupportedException(); | ||
|
||
emiter.LoadArgument(0); | ||
emiter.Increment(typeof(T)); | ||
emiter.Return(); | ||
}); | ||
|
||
DelegateHelpers.Compile(out Subtract, emiter => | ||
{ | ||
if (!CachedTypeInfo<T>.IsNumeric) | ||
throw new NotSupportedException(); | ||
|
||
emiter.LoadArguments(0, 1); | ||
emiter.Subtract(); | ||
emiter.Return(); | ||
}); | ||
|
||
DelegateHelpers.Compile(out Decrement, emiter => | ||
{ | ||
if (!CachedTypeInfo<T>.IsNumeric) | ||
throw new NotSupportedException(); | ||
|
||
emiter.LoadArgument(0); | ||
emiter.Decrement(typeof(T)); | ||
emiter.Return(); | ||
}); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
namespace Platform.Numbers | ||
{ | ||
public static class BitwiseExtensions | ||
{ | ||
public static T PartialWrite<T>(this ref T target, T source, int shift, int limit) where T : struct => target = BitwiseHelpers<T>.PartialWrite(target, source, shift, limit); | ||
public static T PartialRead<T>(this T target, int shift, int limit) => BitwiseHelpers<T>.PartialRead(target, shift, limit); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
namespace Platform.Numbers | ||
{ | ||
public static class BitwiseHelpers | ||
{ | ||
public static long CountBits(long x) | ||
{ | ||
long n = 0; | ||
while (x != 0) | ||
{ | ||
n++; | ||
x = x & x - 1; | ||
} | ||
return n; | ||
} | ||
|
||
public static int GetLowestBitPosition(ulong value) | ||
{ | ||
if (value == 0) | ||
return -1; | ||
|
||
var position = 0; | ||
while ((value & 1UL) == 0) | ||
{ | ||
value >>= 1; | ||
++position; | ||
} | ||
return position; | ||
} | ||
|
||
public static T PartialWrite<T>(T target, T source, int shift, int limit) => BitwiseHelpers<T>.PartialWrite(target, source, shift, limit); | ||
|
||
public static T PartialRead<T>(T target, int shift, int limit) => BitwiseHelpers<T>.PartialRead(target, shift, limit); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,168 @@ | ||
using System; | ||
using Platform.Reflection; | ||
using Platform.Reflection.Sigil; | ||
|
||
// ReSharper disable StaticFieldInGenericType | ||
|
||
namespace Platform.Numbers | ||
{ | ||
public static class BitwiseHelpers<T> | ||
{ | ||
public static readonly Func<T, T, int, int, T> PartialWrite; | ||
public static readonly Func<T, int, int, T> PartialRead; | ||
|
||
static BitwiseHelpers() | ||
{ | ||
DelegateHelpers.Compile(out PartialWrite, emiter => | ||
{ | ||
if (!CachedTypeInfo<T>.IsNumeric) | ||
throw new NotSupportedException(); | ||
|
||
var constants = GetConstants<T>(); | ||
var bitsNumber = constants.Item1; | ||
var numberFilledWithOnes = constants.Item2; | ||
|
||
ushort shiftArgument = 2; | ||
ushort limitArgument = 3; | ||
|
||
var checkLimit = emiter.DefineLabel(); | ||
var calculateSourceMask = emiter.DefineLabel(); | ||
|
||
// Check shift | ||
emiter.LoadArgument(shiftArgument); | ||
emiter.LoadConstant(0); | ||
emiter.BranchIfGreaterOrEqual(checkLimit); // Skip fix | ||
|
||
// Fix shift | ||
emiter.LoadConstant(bitsNumber); | ||
emiter.LoadArgument(shiftArgument); | ||
emiter.Add(); | ||
emiter.StoreArgument(shiftArgument); | ||
|
||
emiter.MarkLabel(checkLimit); | ||
// Check limit | ||
emiter.LoadArgument(limitArgument); | ||
emiter.LoadConstant(0); | ||
emiter.BranchIfGreaterOrEqual(calculateSourceMask); // Skip fix | ||
|
||
// Fix limit | ||
emiter.LoadConstant(bitsNumber); | ||
emiter.LoadArgument(limitArgument); | ||
emiter.Add(); | ||
emiter.StoreArgument(limitArgument); | ||
|
||
emiter.MarkLabel(calculateSourceMask); | ||
|
||
using (var sourceMask = emiter.DeclareLocal<T>()) | ||
using (var targetMask = emiter.DeclareLocal<T>()) | ||
{ | ||
emiter.LoadConstant(typeof(T), numberFilledWithOnes); | ||
emiter.LoadArgument(limitArgument); | ||
emiter.ShiftLeft(); | ||
emiter.Not(); | ||
emiter.LoadConstant(typeof(T), numberFilledWithOnes); | ||
emiter.And(); | ||
emiter.StoreLocal(sourceMask); | ||
|
||
emiter.LoadLocal(sourceMask); | ||
emiter.LoadArgument(shiftArgument); | ||
emiter.ShiftLeft(); | ||
emiter.Not(); | ||
emiter.StoreLocal(targetMask); | ||
|
||
emiter.LoadArgument(0); // target | ||
emiter.LoadLocal(targetMask); | ||
emiter.And(); | ||
emiter.LoadArgument(1); // source | ||
emiter.LoadLocal(sourceMask); | ||
emiter.And(); | ||
emiter.LoadArgument(shiftArgument); | ||
emiter.ShiftLeft(); | ||
emiter.Or(); | ||
} | ||
|
||
emiter.Return(); | ||
}); | ||
|
||
DelegateHelpers.Compile(out PartialRead, emiter => | ||
{ | ||
if (!CachedTypeInfo<T>.IsNumeric) | ||
throw new NotSupportedException(); | ||
|
||
var constants = GetConstants<T>(); | ||
var bitsNumber = constants.Item1; | ||
var numberFilledWithOnes = constants.Item2; | ||
|
||
ushort shiftArgument = 1; | ||
ushort limitArgument = 2; | ||
|
||
var checkLimit = emiter.DefineLabel(); | ||
var calculateSourceMask = emiter.DefineLabel(); | ||
|
||
// Check shift | ||
emiter.LoadArgument(shiftArgument); | ||
emiter.LoadConstant(0); | ||
emiter.BranchIfGreaterOrEqual(checkLimit); // Skip fix | ||
|
||
// Fix shift | ||
emiter.LoadConstant(bitsNumber); | ||
emiter.LoadArgument(shiftArgument); | ||
emiter.Add(); | ||
emiter.StoreArgument(shiftArgument); | ||
|
||
emiter.MarkLabel(checkLimit); | ||
// Check limit | ||
emiter.LoadArgument(limitArgument); | ||
emiter.LoadConstant(0); | ||
emiter.BranchIfGreaterOrEqual(calculateSourceMask); // Skip fix | ||
|
||
// Fix limit | ||
emiter.LoadConstant(bitsNumber); | ||
emiter.LoadArgument(limitArgument); | ||
emiter.Add(); | ||
emiter.StoreArgument(limitArgument); | ||
|
||
emiter.MarkLabel(calculateSourceMask); | ||
|
||
using (var sourceMask = emiter.DeclareLocal<T>()) | ||
using (var targetMask = emiter.DeclareLocal<T>()) | ||
{ | ||
emiter.LoadConstant(typeof(T), numberFilledWithOnes); | ||
emiter.LoadArgument(limitArgument); // limit | ||
emiter.ShiftLeft(); | ||
emiter.Not(); | ||
emiter.LoadConstant(typeof(T), numberFilledWithOnes); | ||
emiter.And(); | ||
emiter.StoreLocal(sourceMask); | ||
|
||
emiter.LoadLocal(sourceMask); | ||
emiter.LoadArgument(shiftArgument); | ||
emiter.ShiftLeft(); | ||
emiter.StoreLocal(targetMask); | ||
|
||
emiter.LoadArgument(0); // target | ||
emiter.LoadLocal(targetMask); | ||
emiter.And(); | ||
emiter.LoadArgument(shiftArgument); | ||
emiter.ShiftRight(); | ||
} | ||
|
||
emiter.Return(); | ||
}); | ||
} | ||
|
||
private static Tuple<int, TElement> GetConstants<TElement>() | ||
{ | ||
var type = typeof(T); | ||
if (type == typeof(ulong)) | ||
return new Tuple<int, TElement>(64, (TElement)(object)ulong.MaxValue); | ||
if (type == typeof(uint)) | ||
return new Tuple<int, TElement>(32, (TElement)(object)uint.MaxValue); | ||
if (type == typeof(ushort)) | ||
return new Tuple<int, TElement>(16, (TElement)(object)ushort.MaxValue); | ||
if (type == typeof(byte)) | ||
return new Tuple<int, TElement>(8, (TElement)(object)byte.MaxValue); | ||
throw new NotSupportedException(); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,49 @@ | ||
using Platform.Converters; | ||
|
||
namespace Platform.Numbers | ||
{ | ||
public struct Integer | ||
{ | ||
public readonly ulong Value; | ||
|
||
public Integer(ulong value) => Value = value; | ||
|
||
public static implicit operator Integer(ulong integer) => new Integer(integer); | ||
|
||
public static implicit operator Integer(long integer) => To.UInt64(integer); | ||
|
||
public static implicit operator Integer(uint integer) => new Integer(integer); | ||
|
||
public static implicit operator Integer(int integer) => To.UInt64(integer); | ||
|
||
public static implicit operator Integer(ushort integer) => new Integer(integer); | ||
|
||
public static implicit operator Integer(short integer) => To.UInt64(integer); | ||
|
||
public static implicit operator Integer(byte integer) => new Integer(integer); | ||
|
||
public static implicit operator Integer(sbyte integer) => To.UInt64(integer); | ||
|
||
public static implicit operator Integer(bool integer) => To.UInt64(integer); | ||
|
||
public static implicit operator ulong(Integer integer) => integer.Value; | ||
|
||
public static implicit operator long(Integer integer) => To.Int64(integer.Value); | ||
|
||
public static implicit operator uint(Integer integer) => To.UInt32(integer.Value); | ||
|
||
public static implicit operator int(Integer integer) => To.Int32(integer.Value); | ||
|
||
public static implicit operator ushort(Integer integer) => To.UInt16(integer.Value); | ||
|
||
public static implicit operator short(Integer integer) => To.Int16(integer.Value); | ||
|
||
public static implicit operator byte(Integer integer) => To.Byte(integer.Value); | ||
|
||
public static implicit operator sbyte(Integer integer) => To.SByte(integer.Value); | ||
|
||
public static implicit operator bool(Integer integer) => To.Boolean(integer.Value); | ||
|
||
public override string ToString() => Value.ToString(); | ||
} | ||
} |
Oops, something went wrong.
75fc3a9
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
https://youtu.be/-OX2YZI-MvQ