Created
May 15, 2018 05:25
-
-
Save kameko/0188a2dfd8ccb61658cd5acf9ab19972 to your computer and use it in GitHub Desktop.
A few static generic methods to work on number types
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
using System; | |
namespace Numbers | |
{ | |
public static class GenericNumbers | |
{ | |
[Flags] | |
public enum NumberTypes | |
{ | |
None = 1 << 0, | |
Byte = 1 << 1, | |
SByte = 1 << 2, | |
Int16 = 1 << 3, | |
UInt16 = 1 << 4, | |
Int32 = 1 << 5, | |
UInt32 = 1 << 6, | |
Int64 = 1 << 7, | |
UInt64 = 1 << 8, | |
Single = 1 << 9, | |
Double = 1 << 10, | |
Decimal = 1 << 11, | |
BigInteger = 1 << 12, | |
} | |
public static NumberTypes NumberKind<T>(T obj) | |
{ | |
switch (obj) | |
{ | |
case Byte b: return NumberTypes.Byte; | |
case SByte sb: return NumberTypes.SByte; | |
case Int16 i16: return NumberTypes.Int16; | |
case UInt16 u16: return NumberTypes.UInt16; | |
case Int32 i32: return NumberTypes.Int32; | |
case UInt32 u32: return NumberTypes.UInt32; | |
case Int64 i64: return NumberTypes.Int64; | |
case UInt64 u64: return NumberTypes.UInt64; | |
case Single s: return NumberTypes.Single; | |
case Double d: return NumberTypes.Double; | |
case Decimal dec: return NumberTypes.Decimal; | |
default: return NumberTypes.None; | |
} | |
} | |
public static Boolean IsNumber<T>(T obj) | |
{ | |
return !GenericNumbers.NumberKind<T>(obj).HasFlag(NumberTypes.None); | |
} | |
public static T Add<T>(T x, T y) where T : struct, IConvertible | |
{ | |
switch (x) | |
{ | |
case Byte b: return (T)Convert.ChangeType((b + Convert.ToByte (y)), typeof(T)); | |
case SByte sb: return (T)Convert.ChangeType((sb + Convert.ToSByte (y)), typeof(T)); | |
case Int16 i16: return (T)Convert.ChangeType((i16 + Convert.ToInt16 (y)), typeof(T)); | |
case UInt16 u16: return (T)Convert.ChangeType((u16 + Convert.ToUInt16 (y)), typeof(T)); | |
case Int32 i32: return (T)Convert.ChangeType((i32 + Convert.ToInt32 (y)), typeof(T)); | |
case UInt32 u32: return (T)Convert.ChangeType((u32 + Convert.ToUInt32 (y)), typeof(T)); | |
case Int64 i64: return (T)Convert.ChangeType((i64 + Convert.ToInt64 (y)), typeof(T)); | |
case UInt64 u64: return (T)Convert.ChangeType((u64 + Convert.ToUInt64 (y)), typeof(T)); | |
case Single s: return (T)Convert.ChangeType((s + Convert.ToSingle (y)), typeof(T)); | |
case Double d: return (T)Convert.ChangeType((d + Convert.ToDouble (y)), typeof(T)); | |
case Decimal dec: return (T)Convert.ChangeType((dec + Convert.ToDecimal (y)), typeof(T)); | |
default: return default; | |
} | |
} | |
public static T Subtract<T>(T x, T y) where T : struct, IConvertible | |
{ | |
switch (x) | |
{ | |
case Byte b: return (T)Convert.ChangeType((b - Convert.ToByte (y)), typeof(T)); | |
case SByte sb: return (T)Convert.ChangeType((sb - Convert.ToSByte (y)), typeof(T)); | |
case Int16 i16: return (T)Convert.ChangeType((i16 - Convert.ToInt16 (y)), typeof(T)); | |
case UInt16 u16: return (T)Convert.ChangeType((u16 - Convert.ToUInt16 (y)), typeof(T)); | |
case Int32 i32: return (T)Convert.ChangeType((i32 - Convert.ToInt32 (y)), typeof(T)); | |
case UInt32 u32: return (T)Convert.ChangeType((u32 - Convert.ToUInt32 (y)), typeof(T)); | |
case Int64 i64: return (T)Convert.ChangeType((i64 - Convert.ToInt64 (y)), typeof(T)); | |
case UInt64 u64: return (T)Convert.ChangeType((u64 - Convert.ToUInt64 (y)), typeof(T)); | |
case Single s: return (T)Convert.ChangeType((s - Convert.ToSingle (y)), typeof(T)); | |
case Double d: return (T)Convert.ChangeType((d - Convert.ToDouble (y)), typeof(T)); | |
case Decimal dec: return (T)Convert.ChangeType((dec - Convert.ToDecimal (y)), typeof(T)); | |
default: return default; | |
} | |
} | |
public static T Divide<T>(T x, T y) where T : struct, IConvertible | |
{ | |
switch (x) | |
{ | |
case Byte b: return (T)Convert.ChangeType((b / Convert.ToByte (y)), typeof(T)); | |
case SByte sb: return (T)Convert.ChangeType((sb / Convert.ToSByte (y)), typeof(T)); | |
case Int16 i16: return (T)Convert.ChangeType((i16 / Convert.ToInt16 (y)), typeof(T)); | |
case UInt16 u16: return (T)Convert.ChangeType((u16 / Convert.ToUInt16 (y)), typeof(T)); | |
case Int32 i32: return (T)Convert.ChangeType((i32 / Convert.ToInt32 (y)), typeof(T)); | |
case UInt32 u32: return (T)Convert.ChangeType((u32 / Convert.ToUInt32 (y)), typeof(T)); | |
case Int64 i64: return (T)Convert.ChangeType((i64 / Convert.ToInt64 (y)), typeof(T)); | |
case UInt64 u64: return (T)Convert.ChangeType((u64 / Convert.ToUInt64 (y)), typeof(T)); | |
case Single s: return (T)Convert.ChangeType((s / Convert.ToSingle (y)), typeof(T)); | |
case Double d: return (T)Convert.ChangeType((d / Convert.ToDouble (y)), typeof(T)); | |
case Decimal dec: return (T)Convert.ChangeType((dec / Convert.ToDecimal (y)), typeof(T)); | |
default: return default; | |
} | |
} | |
public static T Multiply<T>(T x, T y) where T : struct, IConvertible | |
{ | |
switch (x) | |
{ | |
case Byte b: return (T)Convert.ChangeType((b * Convert.ToByte (y)), typeof(T)); | |
case SByte sb: return (T)Convert.ChangeType((sb * Convert.ToSByte (y)), typeof(T)); | |
case Int16 i16: return (T)Convert.ChangeType((i16 * Convert.ToInt16 (y)), typeof(T)); | |
case UInt16 u16: return (T)Convert.ChangeType((u16 * Convert.ToUInt16 (y)), typeof(T)); | |
case Int32 i32: return (T)Convert.ChangeType((i32 * Convert.ToInt32 (y)), typeof(T)); | |
case UInt32 u32: return (T)Convert.ChangeType((u32 * Convert.ToUInt32 (y)), typeof(T)); | |
case Int64 i64: return (T)Convert.ChangeType((i64 * Convert.ToInt64 (y)), typeof(T)); | |
case UInt64 u64: return (T)Convert.ChangeType((u64 * Convert.ToUInt64 (y)), typeof(T)); | |
case Single s: return (T)Convert.ChangeType((s * Convert.ToSingle (y)), typeof(T)); | |
case Double d: return (T)Convert.ChangeType((d * Convert.ToDouble (y)), typeof(T)); | |
case Decimal dec: return (T)Convert.ChangeType((dec * Convert.ToDecimal (y)), typeof(T)); | |
default: return default; | |
} | |
} | |
public static T Power<T>(T x, T y) where T : struct, IConvertible | |
{ | |
switch (x) | |
{ | |
case Byte b: return (T)Convert.ChangeType(Math.Pow(b , Convert.ToByte (y)), typeof(T)); | |
case SByte sb: return (T)Convert.ChangeType(Math.Pow(sb , Convert.ToSByte (y)), typeof(T)); | |
case Int16 i16: return (T)Convert.ChangeType(Math.Pow(i16 , Convert.ToInt16 (y)), typeof(T)); | |
case UInt16 u16: return (T)Convert.ChangeType(Math.Pow(u16 , Convert.ToUInt16 (y)), typeof(T)); | |
case Int32 i32: return (T)Convert.ChangeType(Math.Pow(i32 , Convert.ToInt32 (y)), typeof(T)); | |
case UInt32 u32: return (T)Convert.ChangeType(Math.Pow(u32 , Convert.ToUInt32 (y)), typeof(T)); | |
case Int64 i64: return (T)Convert.ChangeType(Math.Pow(i64 , Convert.ToInt64 (y)), typeof(T)); | |
case UInt64 u64: return (T)Convert.ChangeType(Math.Pow(u64 , Convert.ToUInt64 (y)), typeof(T)); | |
case Single s: return (T)Convert.ChangeType(Math.Pow(s , Convert.ToSingle (y)), typeof(T)); | |
case Double d: return (T)Convert.ChangeType(Math.Pow(d , Convert.ToDouble (y)), typeof(T)); | |
// Math.Pow(Decimal, Decimal) does not exist as an overload. | |
default: return default; | |
} | |
} | |
public static T Min<T>(T x, T y) where T : struct, IConvertible | |
{ | |
switch (x) | |
{ | |
case Byte b: return (T)Convert.ChangeType(Math.Min(b , Convert.ToByte (y)), typeof(T)); | |
case SByte sb: return (T)Convert.ChangeType(Math.Min(sb , Convert.ToSByte (y)), typeof(T)); | |
case Int16 i16: return (T)Convert.ChangeType(Math.Min(i16 , Convert.ToInt16 (y)), typeof(T)); | |
case UInt16 u16: return (T)Convert.ChangeType(Math.Min(u16 , Convert.ToUInt16 (y)), typeof(T)); | |
case Int32 i32: return (T)Convert.ChangeType(Math.Min(i32 , Convert.ToInt32 (y)), typeof(T)); | |
case UInt32 u32: return (T)Convert.ChangeType(Math.Min(u32 , Convert.ToUInt32 (y)), typeof(T)); | |
case Int64 i64: return (T)Convert.ChangeType(Math.Min(i64 , Convert.ToInt64 (y)), typeof(T)); | |
case UInt64 u64: return (T)Convert.ChangeType(Math.Min(u64 , Convert.ToUInt64 (y)), typeof(T)); | |
case Single s: return (T)Convert.ChangeType(Math.Min(s , Convert.ToSingle (y)), typeof(T)); | |
case Double d: return (T)Convert.ChangeType(Math.Min(d , Convert.ToDouble (y)), typeof(T)); | |
case Decimal dec: return (T)Convert.ChangeType(Math.Min(dec , Convert.ToDecimal (y)), typeof(T)); | |
default: return default; | |
} | |
} | |
public static T Max<T>(T x, T y) where T : struct, IConvertible | |
{ | |
switch (x) | |
{ | |
case Byte b: return (T)Convert.ChangeType(Math.Max(b , Convert.ToByte (y)), typeof(T)); | |
case SByte sb: return (T)Convert.ChangeType(Math.Max(sb , Convert.ToSByte (y)), typeof(T)); | |
case Int16 i16: return (T)Convert.ChangeType(Math.Max(i16 , Convert.ToInt16 (y)), typeof(T)); | |
case UInt16 u16: return (T)Convert.ChangeType(Math.Max(u16 , Convert.ToUInt16 (y)), typeof(T)); | |
case Int32 i32: return (T)Convert.ChangeType(Math.Max(i32 , Convert.ToInt32 (y)), typeof(T)); | |
case UInt32 u32: return (T)Convert.ChangeType(Math.Max(u32 , Convert.ToUInt32 (y)), typeof(T)); | |
case Int64 i64: return (T)Convert.ChangeType(Math.Max(i64 , Convert.ToInt64 (y)), typeof(T)); | |
case UInt64 u64: return (T)Convert.ChangeType(Math.Max(u64 , Convert.ToUInt64 (y)), typeof(T)); | |
case Single s: return (T)Convert.ChangeType(Math.Max(s , Convert.ToSingle (y)), typeof(T)); | |
case Double d: return (T)Convert.ChangeType(Math.Max(d , Convert.ToDouble (y)), typeof(T)); | |
case Decimal dec: return (T)Convert.ChangeType(Math.Max(dec , Convert.ToDecimal (y)), typeof(T)); | |
default: return default; | |
} | |
} | |
public static T Clamp<T>(T number, T min, T max) where T : struct, IConvertible | |
{ | |
switch (number) | |
{ | |
case Byte b: return (T)Convert.ChangeType(Math.Clamp(b , Convert.ToByte (min), Convert.ToByte (max)), typeof(T)); | |
case SByte sb: return (T)Convert.ChangeType(Math.Clamp(sb , Convert.ToSByte (min), Convert.ToSByte (max)), typeof(T)); | |
case Int16 i16: return (T)Convert.ChangeType(Math.Clamp(i16 , Convert.ToInt16 (min), Convert.ToInt16 (max)), typeof(T)); | |
case UInt16 u16: return (T)Convert.ChangeType(Math.Clamp(u16 , Convert.ToUInt16 (min), Convert.ToUInt16 (max)), typeof(T)); | |
case Int32 i32: return (T)Convert.ChangeType(Math.Clamp(i32 , Convert.ToInt32 (min), Convert.ToInt32 (max)), typeof(T)); | |
case UInt32 u32: return (T)Convert.ChangeType(Math.Clamp(u32 , Convert.ToUInt32 (min), Convert.ToUInt32 (max)), typeof(T)); | |
case Int64 i64: return (T)Convert.ChangeType(Math.Clamp(i64 , Convert.ToInt64 (min), Convert.ToInt64 (max)), typeof(T)); | |
case UInt64 u64: return (T)Convert.ChangeType(Math.Clamp(u64 , Convert.ToUInt64 (min), Convert.ToUInt64 (max)), typeof(T)); | |
case Single s: return (T)Convert.ChangeType(Math.Clamp(s , Convert.ToSingle (min), Convert.ToSingle (max)), typeof(T)); | |
case Double d: return (T)Convert.ChangeType(Math.Clamp(d , Convert.ToDouble (min), Convert.ToDouble (max)), typeof(T)); | |
case Decimal dec: return (T)Convert.ChangeType(Math.Clamp(dec , Convert.ToDecimal (min), Convert.ToDecimal (max)), typeof(T)); | |
default: return default; | |
} | |
} | |
public static T Absolute<T>(T x) where T : struct, IConvertible | |
{ | |
switch (x) | |
{ | |
case Byte b: return (T)Convert.ChangeType(Math.Abs(b ), typeof(T)); | |
case SByte sb: return (T)Convert.ChangeType(Math.Abs(sb ), typeof(T)); | |
case Int16 i16: return (T)Convert.ChangeType(Math.Abs(i16 ), typeof(T)); | |
case UInt16 u16: return (T)Convert.ChangeType(Math.Abs(u16 ), typeof(T)); | |
case Int32 i32: return (T)Convert.ChangeType(Math.Abs(i32 ), typeof(T)); | |
case UInt32 u32: return (T)Convert.ChangeType(Math.Abs(u32 ), typeof(T)); | |
case Int64 i64: return (T)Convert.ChangeType(Math.Abs(i64 ), typeof(T)); | |
case UInt64 u64: return (T)Convert.ChangeType(Math.Abs((Decimal)u64), typeof(T)); | |
case Single s: return (T)Convert.ChangeType(Math.Abs(s ), typeof(T)); | |
case Double d: return (T)Convert.ChangeType(Math.Abs(d ), typeof(T)); | |
case Decimal dec: return (T)Convert.ChangeType(Math.Abs(dec ), typeof(T)); | |
default: return default; | |
} | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment