using System;
using System.Collections.Generic;
using System.Text;
using Sasa.Emit;
using System.Reflection;
namespace Sasa
{
/// <summary>
/// Operators defined for type <typeparamref name="T"/>.
/// </summary>
/// <typeparam name="T">The type on which the operators are defined.</typeparam>
/// <remarks>
/// When writing generic code, it's pretty common to yearn for some generic operator interface so
/// you don't have to copy-paste the same function over and over to provide overloads for all the
/// CLR's primitive types. Omitting a standard operator interface was one of .NET's biggest mistakes
/// in my opinion.
///
/// Enter <see cref="Operators{T}"/>, a static class library that exposes the delegates for the
/// standard mathematical and logical operators on any given type <typeparamref name="T"/>.
/// If <typeparamref name="T"/> does not contain a particular operator overload, the
/// corresponding delegate for that operation will be null, so you just need to check for
/// their presence as a precondition.
/// </remarks>
public static class Operators<T>
{
static Operators()
{
Add = Operators<T, T, T>.Add;
Subtract = Operators<T, T, T>.Subtract;
Divide = Operators<T, T, T>.Divide;
Multiply = Operators<T, T, T>.Multiply;
Modulo = Operators<T, T, T>.Modulo;
Negate = Operators<T, T>.Negate;
Not = Operators<T, T>.Not;
Or = Operators<T, T, T>.Or;
Xor = Operators<T, T, T>.Xor;
And = Operators<T, T, T>.And;
LeftShift = Operators<T, T>.LeftShift;
RightShift = Operators<T, T>.RightShift;
GreaterThan = Operators<T, T>.GreaterThan;
LessThan = Operators<T, T>.LessThan;
GreaterThanOrEqual = Operators<T, T>.GreaterThanOrEqual;
LessThanOrEqual = Operators<T, T>.LessThanOrEqual;
Increment = Operators<T, T>.Increment;
Decrement = Operators<T, T>.Decrement;
Plus = Operators<T, T>.Plus;
True = Func.Operator<Func<T, bool>>(Operators.True);
False = Func.Operator<Func<T, bool>>(Operators.False);
Equal = Operators<T, T>.Equal;
NotEqual = Operators<T, T>.NotEqual;
MaxValue = Select("MaxValue", int.MaxValue, long.MaxValue, uint.MaxValue, ulong.MaxValue, char.MaxValue, byte.MaxValue, decimal.MaxValue, float.MaxValue, double.MaxValue, short.MaxValue, ushort.MaxValue);
MinValue = Select("MinValue", int.MinValue, long.MinValue, uint.MinValue, ulong.MinValue, char.MinValue, byte.MinValue, decimal.MinValue, float.MinValue, double.MinValue, short.MinValue, ushort.MinValue);
}
/// <summary>
/// The minimum value, if applicable.
/// </summary>
public static readonly T MinValue;
/// <summary>
/// The max possible value, if applicable.
/// </summary>
public static readonly T MaxValue;
static T Select(string name, int i, long l, uint ui, ulong ul, char c, byte b, decimal dc, float f, double db, short s, ushort us) =>
typeof(T) == typeof(int) ? (T)(object)i:
typeof(T) == typeof(long) ? (T)(object)l:
typeof(T) == typeof(uint) ? (T)(object)ui:
typeof(T) == typeof(ulong) ? (T)(object)ul:
typeof(T) == typeof(char) ? (T)(object)c:
typeof(T) == typeof(byte) ? (T)(object)b:
typeof(T) == typeof(decimal)? (T)(object)dc:
typeof(T) == typeof(float) ? (T)(object)f:
typeof(T) == typeof(double) ? (T)(object)db:
typeof(T) == typeof(short) ? (T)(object)s:
typeof(T) == typeof(ushort) ? (T)(object)us:
(T)(typeof(T).GetRuntimeProperty(name)?.GetValue(null) ?? default(T));
/// <summary>
/// Adds two arguments.
/// </summary>
/// <remarks>
/// The standard addition operation is straightforward, taking two T arguments and returning their addition:
/// <code>
/// var x = Operators<int>.Add(1, 2);
/// Console.WriteLine(x);
/// // output:
/// // 3
/// </code>
/// </remarks>
public static readonly Func<T, T, T> Add;
/// <summary>
/// Subtracts two arguments.
/// </summary>
/// <remarks>
/// The subtraction operator takes two T arguments, and returns their subtraction:
/// <code>
/// var x = Operators<int>.Subtract(1, 3);
/// Console.WriteLine(x);
/// // output:
/// // -2
/// </code>
/// </remarks>
public static readonly Func<T, T, T> Subtract;
/// <summary>
/// Divides two arguments.
/// </summary>
/// <remarks>
/// The divide operator two T arguments and returns a T argument corresponding to their division:
/// <code>
/// var x = Operators<int>.Divide(6, 2);
/// Console.WriteLine(x);
/// // output:
/// // 3
/// </code>
/// </remarks>
public static readonly Func<T, T, T> Divide;
/// <summary>
/// Multiplies two arguments.
/// </summary>
/// <remarks>
/// The multiply operator takes two T arguments, and returns their multiplication:
/// <code>
/// var x = Operators<int>.Multiply(9, 2);
/// Console.WriteLine(x);
/// // output:
/// // 18
/// </code>
/// </remarks>
public static readonly Func<T, T, T> Multiply;
/// <summary>
/// Takes the remainder of two arguments.
/// </summary>
/// <remarks>
/// The modulo operator takes two T arguments, and returns the modulus/remainder of dividing the two arguments:
/// <code>
/// var x = Operators<int>.Modulo(9, 2);
/// Console.WriteLine(x);
/// // output:
/// // 1
/// </code>
/// </remarks>
public static readonly Func<T, T, T> Modulo;
/// <summary>
/// Negates an argument.
/// </summary>
/// <remarks>
/// The negate operator takes a T argument, and returns its negation:
/// <code>
/// var x = Operators<int>.Negate(9);
/// Console.WriteLine(x);
/// // output:
/// // -9
/// </code>
/// </remarks>
public static readonly Func<T, T> Negate;
/// <summary>
/// Bitwise complement.
/// </summary>
/// <remarks>
/// The 'not' operator takes a T argument, and returns logical/bitwise not of the value:
/// <code>
/// // given twos-complement, not(-1) == 0
/// var x = Operators<int>.Not(-1);
/// Console.WriteLine(x);
/// // output:
/// // 0
/// </code>
/// </remarks>
public static readonly Func<T, T> Not;
/// <summary>
/// Increments an argument.
/// </summary>
/// <remarks>
/// The increment operator a T argument and returns an "incremented" T:
/// <code>
/// var x = Operators<int>.Increment(98);
/// Console.WriteLine(x);
/// // output:
/// // 99
/// </code>
/// </remarks>
public static readonly Func<T, T> Increment;
/// <summary>
/// Decrements an argument.
/// </summary>
/// <remarks>
/// The decrement operator takes a T argument, and returns a "decremented" T argument:
/// <code>
/// var x = Operators<double>.Decrement(1.5);
/// Console.WriteLine(x);
/// // output:
/// // 0.5
/// </code>
/// </remarks>
public static readonly Func<T, T> Decrement;
/// <summary>
/// Or's an argument.
/// </summary>
/// <remarks>
/// The 'or' operator takes two T arguments, and returns their logical/bitwise-or:
/// <code>
/// var x = Operators<int>.Or(1, 2);
/// Console.WriteLine(x);
/// // output:
/// // 3
/// </code>
/// </remarks>
public static readonly Func<T, T, T> Or;
/// <summary>
/// Xor's its argument.
/// </summary>
/// <remarks>
/// The xor operator takes two T arguments, and returns their logical/bitwise exclusive-or:
/// <code>
/// var x = Operators<int>.Xor(1, 3);
/// Console.WriteLine(x);
/// // output:
/// // 2
/// </code>
/// </remarks>
public static readonly Func<T, T, T> Xor;
/// <summary>
/// And's its argument.
/// </summary>
/// <remarks>
/// The 'And' operation takes two T arguments, and returns a T argument which is the bitwise/logical
/// 'and' of the two arguments:
/// <code>
/// var x = Operators<int>.And(1, 3);
/// Console.WriteLine(x);
/// // output:
/// // 1
/// </code>
/// </remarks>
public static readonly Func<T, T, T> And;
/// <summary>
/// Left shifts an argument.
/// </summary>
/// <remarks>
/// The left shift operator a T argument, followed by an Int32 argument, and returns a T "left-shifted" by the Int32:
/// <code>
/// var x = Operators<int>.LeftShift(1, 3);
/// Console.WriteLine(x);
/// // output:
/// // 8
/// </code>
/// </remarks>
public static readonly Func<T, int, T> LeftShift;
/// <summary>
/// Right shifts an argument.
/// </summary>
/// <remarks>
/// The right shift operator a T argument, followed by an Int32 argument, and returns a T "right-shifted" by the Int32:
/// <code>
/// var x = Operators<int>.RightShift(8, 3);
/// Console.WriteLine(x);
/// // output:
/// // 1
/// </code>
/// </remarks>
public static readonly Func<T, int, T> RightShift;
/// <summary>
/// Converts the type to a boolean.
/// </summary>
/// <remarks>
/// The boolean conversion operator:
/// <code>
/// Console.WriteLine(Operators<bool>.True(false));
/// Console.WriteLine(Operators<bool>.True(true));
/// // output:
/// // false
/// // true
/// </code>
/// </remarks>
public static readonly Func<T, bool> True;
/// <summary>
/// Converts the type to a boolean.
/// </summary>
/// <remarks>
/// The boolean conversion operator:
/// <code>
/// Console.WriteLine(Operators<bool>.False(false));
/// Console.WriteLine(Operators<bool>.False(true));
/// // output:
/// // true
/// // false
/// </code>
/// </remarks>
public static readonly Func<T, bool> False;
/// <summary>
/// Unary plus operator.
/// </summary>
/// <remarks>
/// The unary plus operator:
/// <code>
/// var x = Operators<Foo>.Plus(new Foo());
/// Console.WriteLine(x);
/// // output:
/// // 1
/// </code>
/// </remarks>
public static readonly Func<T, T> Plus;
/// <summary>
/// Compare argument magnitudes.
/// </summary>
/// <remarks>
/// The > operator takes two T arguments, and returns true if the first is greater than the second:
/// <code>
/// var x = Operators<int>.GreaterThan(1, 2);
/// Console.WriteLine(x);
/// // output:
/// // false
/// </code>
/// </remarks>
public static readonly Func<T, T, bool> GreaterThan;
/// <summary>
/// Compare argument magnitudes.
/// </summary>
/// <remarks>
/// The > operator takes two T arguments, and returns true if the first is less than the second:
/// <code>
/// var x = Operators<int>.LessThan(1, 2);
/// Console.WriteLine(x);
/// // output:
/// // true
/// </code>
/// </remarks>
public static readonly Func<T, T, bool> LessThan;
/// <summary>
/// Compare argument magnitudes.
/// </summary>
/// <remarks>
/// The > operator takes two T arguments, and returns true if the first is greater than or equal to the second:
/// <code>
/// var x = Operators<int>.GreaterThan(1, 2);
/// Console.WriteLine(x);
/// // output:
/// // false
/// </code>
/// </remarks>
public static readonly Func<T, T, bool> GreaterThanOrEqual;
/// <summary>
/// Compare argument magnitudes.
/// </summary>
/// <remarks>
/// The > operator takes two T arguments, and returns true if the first is less than or equal to the second:
/// <code>
/// var x = Operators<int>.LessThan(1, 2);
/// Console.WriteLine(x);
/// // output:
/// // true
/// </code>
/// </remarks>
public static readonly Func<T, T, bool> LessThanOrEqual;
/// <summary>
/// Compare arguments for equality.
/// </summary>
/// <remarks>
/// The == operator takes two T arguments, and returns true if they are equal:
/// <code>
/// var x = Operators<int>.Equal(1, 2);
/// Console.WriteLine(x);
/// // output:
/// // false
/// </code>
/// </remarks>
public static readonly Func<T, T, bool> Equal;
/// <summary>
/// Compare arguments for inequality.
/// </summary>
/// <remarks>
/// The == operator takes two T arguments, and returns true if they are not equal:
/// <code>
/// var x = Operators<int>.NotEqual(1, 2);
/// Console.WriteLine(x);
/// // output:
/// // true
/// </code>
/// </remarks>
public static readonly Func<T, T, bool> NotEqual;
}
/// <summary>
/// Operators defined for types <typeparamref name="T0"/> and <typeparamref name="T1"/>.
/// </summary>
/// <typeparam name="T0">The first operator type.</typeparam>
/// <typeparam name="T1">The second operator type.</typeparam>
/// <remarks>
/// When writing generic code, it's pretty common to yearn for some generic operator interface so
/// you don't have to copy-paste the same function over and over to provide overloads for all the
/// CLR's primitive types. Omitting a standard operator interface was one of .NET's biggest mistakes
/// in my opinion.
///
/// Enter <see cref="Operators{T0, T1}"/>, a static class library that exposes delegates for the
/// overloadable operators defined on types <typeparamref name="T0"/> and <typeparamref name="T1"/>.
/// If neither type contains an operator overload for a given operation, the corresponding delegate
/// for that operation will be null, so you just need to check for their presence as a precondition.
/// </remarks>
public static class Operators<T0, T1>
{
static Operators()
{
Increment = Func.Operator<Func<T0, T1>>(Operators.Increment);
Decrement = Func.Operator<Func<T0, T1>>(Operators.Decrement);
Negate = Func.Operator<Func<T0, T1>>(Operators.UnaryNegation);
Not = Func.Operator<Func<T0, T1>>(Operators.OnesComplement);
LeftShift = Func.Operator<Func<T0, int, T1>>(Operators.LeftShift);
RightShift = Func.Operator<Func<T0, int, T1>>(Operators.RightShift);
GreaterThan = Func.Operator<Func<T0, T1, bool>>(Operators.GreaterThan);
LessThan = Func.Operator<Func<T0, T1, bool>>(Operators.LessThan);
GreaterThanOrEqual = Func.Operator<Func<T0, T1, bool>>(Operators.GreaterThanOrEqual);
LessThanOrEqual = Func.Operator<Func<T0, T1, bool>>(Operators.LessThanOrEqual);
Equal = Func.Operator<Func<T0, T1, bool>>(Operators.Equality);
NotEqual = Func.Operator<Func<T0, T1, bool>>(Operators.Inequality);
Plus = Func.Operator<Func<T0, T1>>(Operators.UnaryPlus);
Explicit = Func.Operator<Func<T0, T1>>(Operators.Explicit);
Implicit = Func.Operator<Func<T0, T1>>(Operators.Implicit);
}
/// <summary>
/// Negates an argument.
/// </summary>
/// <remarks>
/// The negate operator takes a T argument, and returns its negation:
/// <code>
/// var x = Operators<int, int>.Negate(9);
/// Console.WriteLine(x);
/// // output:
/// // -9
/// </code>
/// </remarks>
public static readonly Func<T0, T1> Negate;
/// <summary>
/// Implicitly converts an argument type.
/// </summary>
/// <remarks>
/// The implicit conversion operator converts a <typeparamref name="T0"/> to a <typeparamref name="T1"/>:
/// <code>
/// var x = Operators<int, int>.Implicit(9);
/// Console.WriteLine(x);
/// // output:
/// // -9
/// </code>
/// </remarks>
public static readonly Func<T0, T1> Implicit;
/// <summary>
/// Explicitly converts an argument type.
/// </summary>
/// <remarks>
/// The explicit conversion operator converts a <typeparamref name="T0"/> to a <typeparamref name="T1"/>:
/// <code>
/// var x = Operators<int, float>.Explicit(9);
/// Console.WriteLine(x);
/// // output:
/// // -9
/// </code>
/// </remarks>
public static readonly Func<T0, T1> Explicit;
/// <summary>
/// Bitwise complement.
/// </summary>
/// <remarks>
/// The 'not' operator takes a T argument, and returns logical/bitwise not of the value:
/// <code>
/// // given twos-complement, not(-1) == 0
/// var x = Operators<int, int>.Not(-1);
/// Console.WriteLine(x);
/// // output:
/// // 0
/// </code>
/// </remarks>
public static readonly Func<T0, T1> Not;
/// <summary>
/// Increments an argument.
/// </summary>
/// <remarks>
/// The increment operator a T argument and returns an "incremented" T:
/// <code>
/// var x = Operators<int, int>.Increment(98);
/// Console.WriteLine(x);
/// // output:
/// // 99
/// </code>
/// </remarks>
public static readonly Func<T0, T1> Increment;
/// <summary>
/// Decrements an argument.
/// </summary>
/// <remarks>
/// The decrement operator takes a T argument, and returns a "decremented" T argument:
/// <code>
/// var x = Operators<double, double>.Decrement(1.5);
/// Console.WriteLine(x);
/// // output:
/// // 0.5
/// </code>
/// </remarks>
public static readonly Func<T0, T1> Decrement;
/// <summary>
/// Left shifts an argument.
/// </summary>
/// <remarks>
/// The left shift operator a T argument, followed by an Int32 argument, and returns a T "left-shifted" by the Int32:
/// <code>
/// var x = Operators<int, int>.LeftShift(1, 3);
/// Console.WriteLine(x);
/// // output:
/// // 8
/// </code>
/// </remarks>
public static readonly Func<T0, int, T1> LeftShift;
/// <summary>
/// Right shifts an argument.
/// </summary>
/// <remarks>
/// The right shift operator a T argument, followed by an Int32 argument, and returns a T "right-shifted" by the Int32:
/// <code>
/// var x = Operators<int, int>.RightShift(8, 3);
/// Console.WriteLine(x);
/// // output:
/// // 1
/// </code>
/// </remarks>
public static readonly Func<T0, int, T1> RightShift;
/// <summary>
/// Unary plus operator.
/// </summary>
/// <remarks>
/// The unary plus operator:
/// <code>
/// var x = Operators<int, int>.Plus(-1);
/// Console.WriteLine(x);
/// // output:
/// // -1
/// </code>
/// </remarks>
public static readonly Func<T0, T1> Plus;
/// <summary>
/// Compare argument magnitudes.
/// </summary>
/// <remarks>
/// The > operator takes two T arguments, and returns true if the first is greater than the second:
/// <code>
/// var x = Operators<int, int>.GreaterThan(1, 2);
/// Console.WriteLine(x);
/// // output:
/// // false
/// </code>
/// </remarks>
public static readonly Func<T0, T1, bool> GreaterThan;
/// <summary>
/// Compare argument magnitudes.
/// </summary>
/// <remarks>
/// The > operator takes two T arguments, and returns true if the first is less than the second:
/// <code>
/// var x = Operators<int, int>.LessThan(1, 2);
/// Console.WriteLine(x);
/// // output:
/// // true
/// </code>
/// </remarks>
public static readonly Func<T0, T1, bool> LessThan;
/// <summary>
/// Compare argument magnitudes.
/// </summary>
/// <remarks>
/// The > operator takes two T arguments, and returns true if the first is greater than or equal to the second:
/// <code>
/// var x = Operators<int, int>.GreaterThan(1, 2);
/// Console.WriteLine(x);
/// // output:
/// // false
/// </code>
/// </remarks>
public static readonly Func<T0, T1, bool> GreaterThanOrEqual;
/// <summary>
/// Compare argument magnitudes.
/// </summary>
/// <remarks>
/// The > operator takes two T arguments, and returns true if the first is less than or equal to the second:
/// <code>
/// var x = Operators<int, int>.LessThan(1, 2);
/// Console.WriteLine(x);
/// // output:
/// // true
/// </code>
/// </remarks>
public static readonly Func<T0, T1, bool> LessThanOrEqual;
/// <summary>
/// Compare arguments for equality.
/// </summary>
/// <remarks>
/// The == operator takes two T arguments, and returns true if they are equal:
/// <code>
/// var x = Operators<int, int>.Equal(1, 2);
/// Console.WriteLine(x);
/// // output:
/// // false
/// </code>
/// </remarks>
public static readonly Func<T0, T1, bool> Equal;
/// <summary>
/// Compare arguments for inequality.
/// </summary>
/// <remarks>
/// The == operator takes two T arguments, and returns true if they are not equal:
/// <code>
/// var x = Operators<int, int>.NotEqual(1, 2);
/// Console.WriteLine(x);
/// // output:
/// // true
/// </code>
/// </remarks>
public static readonly Func<T0, T1, bool> NotEqual;
}
/// <summary>
/// Operators defined for types <typeparamref name="T0"/>, <typeparamref name="T1"/>
/// <typeparamref name="T2"/>.
/// </summary>
/// <typeparam name="T0">The first operator type.</typeparam>
/// <typeparam name="T1">The second operator type.</typeparam>
/// <typeparam name="T2">The third operator type.</typeparam>
/// <remarks>
/// When writing generic code, it's pretty common to yearn for some generic operator interface so
/// you don't have to copy-paste the same function over and over to provide overloads for all the
/// CLR's primitive types. Omitting a standard operator interface was one of .NET's biggest mistakes
/// in my opinion.
///
/// Enter <see cref="Operators{T0, T1, T2}"/>, a static class library that exposes delegates for the
/// overloadable operators defined on types <typeparamref name="T0"/> and <typeparamref name="T1"/>.
/// If neither type contains an operator overload for a given operation, the corresponding delegate
/// for that operation will be null, so you just need to check for their presence as a precondition.
/// </remarks>
public static class Operators<T0, T1, T2>
{
static Operators()
{
Add = Func.Operator<Func<T0, T1, T2>>(Operators.Addition);
Subtract = Func.Operator<Func<T0, T1, T2>>(Operators.Subtraction);
Divide = Func.Operator<Func<T0, T1, T2>>(Operators.Division);
Multiply = Func.Operator<Func<T0, T1, T2>>(Operators.Multiply);
Modulo = Func.Operator<Func<T0, T1, T2>>(Operators.Modulus);
Or = Func.Operator<Func<T0, T1, T2>>(Operators.BitwiseOr);
And = Func.Operator<Func<T0, T1, T2>>(Operators.BitwiseAnd);
Xor = Func.Operator<Func<T0, T1, T2>>(Operators.ExclusiveOr);
GreaterThan = Func.Operator<Func<T0, T1, T2>>(Operators.GreaterThan);
GreaterThanOrEqual = Func.Operator<Func<T0, T1, T2>>(Operators.GreaterThanOrEqual);
LessThan = Func.Operator<Func<T0, T1, T2>>(Operators.LessThan);
LessThanOrEqual = Func.Operator<Func<T0, T1, T2>>(Operators.LessThanOrEqual);
Equal = Func.Operator<Func<T0, T1, T2>>(Operators.Equality);
NotEqual = Func.Operator<Func<T0, T1, T2>>(Operators.Inequality);
}
/// <summary>
/// Adds two arguments.
/// </summary>
/// <remarks>
/// The standard addition operation takes arguments <typeparamref name="T0"/> and <typeparamref name="T1"/> and
/// returns their addition as type <typeparamref name="T2"/>:
/// <code>
/// var x = Operators<int, long, double>.Add(1, 2);
/// Console.WriteLine(x);
/// // output:
/// // 3.0
/// </code>
/// </remarks>
public static readonly Func<T0, T1, T2> Add;
/// <summary>
/// Subtracts two arguments.
/// </summary>
/// <remarks>
/// The subtraction operator takes arguments <typeparamref name="T0"/> and <typeparamref name="T1"/> and returns their subtraction as type <typeparamref name="T2"/>:
/// <code>
/// var x = Operators<int, int, int>.Subtract(1, 3);
/// Console.WriteLine(x);
/// // output:
/// // -2
/// </code>
/// </remarks>
public static readonly Func<T0, T1, T2> Subtract;
/// <summary>
/// Divides two arguments.
/// </summary>
/// <remarks>
/// The divide operator takes arguments <typeparamref name="T0"/> and <typeparamref name="T1"/> and returns their
/// division as type <typeparamref name="T2"/>:
/// <code>
/// var x = Operators<long, int, int>.Divide(6, 2);
/// Console.WriteLine(x);
/// // output:
/// // 3
/// </code>
/// </remarks>
public static readonly Func<T0, T1, T2> Divide;
/// <summary>
/// Multiplies two arguments.
/// </summary>
/// <remarks>
/// The multiply operator takes arguments <typeparamref name="T0"/> and <typeparamref name="T1"/> and returns their multiplication as type <typeparamref name="T2"/>:
/// <code>
/// var x = Operators<int, int, uint>.Multiply(9, 2);
/// Console.WriteLine(x);
/// // output:
/// // 18
/// </code>
/// </remarks>
public static readonly Func<T0, T1, T2> Multiply;
/// <summary>
/// Takes the remainder of two arguments.
/// </summary>
/// <remarks>
/// The modulo operator takes arguments <typeparamref name="T0"/> and <typeparamref name="T1"/> and returns their modulus as type <typeparamref name="T2"/>:
/// <code>
/// var x = Operators<int, int, int>.Modulo(9, 2);
/// Console.WriteLine(x);
/// // output:
/// // 1
/// </code>
/// </remarks>
public static readonly Func<T0, T1, T2> Modulo;
/// <summary>
/// Or's an argument.
/// </summary>
/// <remarks>
/// The 'or' operator takes arguments <typeparamref name="T0"/> and <typeparamref name="T1"/> and returns their logical/bitwise-or as type <typeparamref name="T2"/>:
/// <code>
/// var x = Operators<int>.Or(1, 2);
/// Console.WriteLine(x);
/// // output:
/// // 3
/// </code>
/// </remarks>
public static readonly Func<T0, T1, T2> Or;
/// <summary>
/// Xor's its argument.
/// </summary>
/// <remarks>
/// The xor operator takes arguments <typeparamref name="T0"/> and <typeparamref name="T1"/> and returns their logical/bitwise exclusive-or as type <typeparamref name="T2"/>:
/// <code>
/// var x = Operators<int, int, uint>.Xor(1, 3);
/// Console.WriteLine(x);
/// // output:
/// // 2
/// </code>
/// </remarks>
public static readonly Func<T0, T1, T2> Xor;
/// <summary>
/// And's its argument.
/// </summary>
/// <remarks>
/// The 'And' operation takes arguments <typeparamref name="T0"/> and <typeparamref name="T1"/> and returns their
/// bitwise/logical 'and' as type <typeparamref name="T2"/>:
/// <code>
/// var x = Operators<int, uint, uint>.And(1, 3);
/// Console.WriteLine(x);
/// // output:
/// // 1
/// </code>
/// </remarks>
public static readonly Func<T0, T1, T2> And;
/// <summary>
/// Compare argument magnitudes.
/// </summary>
/// <remarks>
/// The > operator takes arguments <typeparamref name="T0"/> and <typeparamref name="T1"/> and returns their > as type <typeparamref name="T2"/>, where T2 must implement the true/false operators:
/// <code>
/// var x = Operators<int>.GreaterThan(1, 2);
/// Console.WriteLine(x);
/// // output:
/// // false
/// </code>
/// </remarks>
public static readonly Func<T0, T1, T2> GreaterThan;
/// <summary>
/// Compare argument magnitudes.
/// </summary>
/// <remarks>
/// The > operator takes arguments <typeparamref name="T0"/> and <typeparamref name="T1"/> and returns their < as type <typeparamref name="T2"/>, where T2 must implement the true/false operators:
/// <code>
/// var x = Operators<int>.LessThan(1, 2);
/// Console.WriteLine(x);
/// // output:
/// // true
/// </code>
/// </remarks>
public static readonly Func<T0, T1, T2> LessThan;
/// <summary>
/// Compare argument magnitudes.
/// </summary>
/// <remarks>
/// The > operator takes arguments <typeparamref name="T0"/> and <typeparamref name="T1"/> and returns their >= as type <typeparamref name="T2"/>, where T2 must implement the true/false operators:
/// <code>
/// var x = Operators<int>.GreaterThan(1, 2);
/// Console.WriteLine(x);
/// // output:
/// // false
/// </code>
/// </remarks>
public static readonly Func<T0, T1, T2> GreaterThanOrEqual;
/// <summary>
/// Compare argument magnitudes.
/// </summary>
/// <remarks>
/// The > operator takes arguments <typeparamref name="T0"/> and <typeparamref name="T1"/> and returns their <= as type <typeparamref name="T2"/>, where T2 must implement the true/false operators:
/// <code>
/// var x = Operators<int>.LessThan(1, 2);
/// Console.WriteLine(x);
/// // output:
/// // true
/// </code>
/// </remarks>
public static readonly Func<T0, T1, T2> LessThanOrEqual;
/// <summary>
/// Compare arguments for equality.
/// </summary>
/// <remarks>
/// The == operator takes arguments <typeparamref name="T0"/> and <typeparamref name="T1"/> and returns their equality as type <typeparamref name="T2"/>, where T2 must implement the true/false operators:
/// <code>
/// var x = Operators<int>.Equal(1, 2);
/// Console.WriteLine(x);
/// // output:
/// // false
/// </code>
/// </remarks>
public static readonly Func<T0, T1, T2> Equal;
/// <summary>
/// Compare arguments for inequality.
/// </summary>
/// <remarks>
/// The != operator takes arguments <typeparamref name="T0"/> and <typeparamref name="T1"/> and returns their inequality as type <typeparamref name="T2"/>, where T2 must implement the true/false operators:
/// <code>
/// var x = Operators<int>.NotEqual(1, 2);
/// Console.WriteLine(x);
/// // output:
/// // true
/// </code>
/// </remarks>
public static readonly Func<T0, T1, T2> NotEqual;
}
}