using System;
using System.Numerics;
public class Test
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine(Operation.Add(2, 2));
Console.WriteLine(Operation.Add(1.2, 3.4));
}
}
class Operation
{
public static T Add<T>(T t1, T t2) => OperationImpl<T>.add(t1, t2);
public static T Subtract<T>(T t1, T t2) => OperationImpl<T>.subtract(t1, t2);
class OperationImpl<T>
{
public static Func<T, T, T> add, subtract;
static Func<T, T, T> ForceCast<U>(Func<U, U, U> f) => (Func<T, T, T>)(object)f;
static OperationImpl()
{
if (typeof(T) == typeof(int))
{
add = ForceCast<int>((x, y) => x + y);
subtract = ForceCast<int>((x, y) => x - y);
}
else if (typeof(T) == typeof(double))
{
add = ForceCast<double>((x, y) => x + y);
subtract = ForceCast<double>((x, y) => x - y);
}
else if (typeof(T) == typeof(Complex))
{
add = ForceCast<Complex>((x, y) => x + y);
subtract = ForceCast<Complex>((x, y) => x - y);
}
else
{
throw new NotSupportedException(
$"Operations on type {typeof(T).Name} are not supported");
}
}
}
}
}
dXNpbmcgU3lzdGVtOwp1c2luZyBTeXN0ZW0uTnVtZXJpY3M7CgpwdWJsaWMgY2xhc3MgVGVzdAp7CiAgICBjbGFzcyBQcm9ncmFtCiAgICB7CiAgICAgICAgc3RhdGljIHZvaWQgTWFpbihzdHJpbmdbXSBhcmdzKQogICAgICAgIHsKICAgICAgICAgICAgQ29uc29sZS5Xcml0ZUxpbmUoT3BlcmF0aW9uLkFkZCgyLCAyKSk7CiAgICAgICAgICAgIENvbnNvbGUuV3JpdGVMaW5lKE9wZXJhdGlvbi5BZGQoMS4yLCAzLjQpKTsKICAgICAgICB9CiAgICB9CgogICAgY2xhc3MgT3BlcmF0aW9uCiAgICB7CiAgICAgICAgcHVibGljIHN0YXRpYyBUIEFkZDxUPihUIHQxLCBUIHQyKSA9PiBPcGVyYXRpb25JbXBsPFQ+LmFkZCh0MSwgdDIpOwogICAgICAgIHB1YmxpYyBzdGF0aWMgVCBTdWJ0cmFjdDxUPihUIHQxLCBUIHQyKSA9PiBPcGVyYXRpb25JbXBsPFQ+LnN1YnRyYWN0KHQxLCB0Mik7CgogICAgICAgIGNsYXNzIE9wZXJhdGlvbkltcGw8VD4KICAgICAgICB7CiAgICAgICAgICAgIHB1YmxpYyBzdGF0aWMgRnVuYzxULCBULCBUPiBhZGQsIHN1YnRyYWN0OwoKICAgICAgICAgICAgc3RhdGljIEZ1bmM8VCwgVCwgVD4gRm9yY2VDYXN0PFU+KEZ1bmM8VSwgVSwgVT4gZikgPT4gKEZ1bmM8VCwgVCwgVD4pKG9iamVjdClmOwoKICAgICAgICAgICAgc3RhdGljIE9wZXJhdGlvbkltcGwoKQogICAgICAgICAgICB7CiAgICAgICAgICAgICAgICBpZiAodHlwZW9mKFQpID09IHR5cGVvZihpbnQpKQogICAgICAgICAgICAgICAgewogICAgICAgICAgICAgICAgICAgIGFkZCA9IEZvcmNlQ2FzdDxpbnQ+KCh4LCB5KSA9PiB4ICsgeSk7CiAgICAgICAgICAgICAgICAgICAgc3VidHJhY3QgPSBGb3JjZUNhc3Q8aW50PigoeCwgeSkgPT4geCAtIHkpOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgZWxzZSBpZiAodHlwZW9mKFQpID09IHR5cGVvZihkb3VibGUpKQogICAgICAgICAgICAgICAgewogICAgICAgICAgICAgICAgICAgIGFkZCA9IEZvcmNlQ2FzdDxkb3VibGU+KCh4LCB5KSA9PiB4ICsgeSk7CiAgICAgICAgICAgICAgICAgICAgc3VidHJhY3QgPSBGb3JjZUNhc3Q8ZG91YmxlPigoeCwgeSkgPT4geCAtIHkpOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgZWxzZSBpZiAodHlwZW9mKFQpID09IHR5cGVvZihDb21wbGV4KSkKICAgICAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgICAgICBhZGQgPSBGb3JjZUNhc3Q8Q29tcGxleD4oKHgsIHkpID0+IHggKyB5KTsKICAgICAgICAgICAgICAgICAgICBzdWJ0cmFjdCA9IEZvcmNlQ2FzdDxDb21wbGV4PigoeCwgeSkgPT4geCAtIHkpOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgZWxzZQogICAgICAgICAgICAgICAgewogICAgICAgICAgICAgICAgICAgIHRocm93IG5ldyBOb3RTdXBwb3J0ZWRFeGNlcHRpb24oCiAgICAgICAgICAgICAgICAgICAgCSQiT3BlcmF0aW9ucyBvbiB0eXBlIHt0eXBlb2YoVCkuTmFtZX0gYXJlIG5vdCBzdXBwb3J0ZWQiKTsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgfQogICAgICAgIH0KICAgIH0KfQ==