From 8c3caa06d5e82214f11ad3d49de9fe6f181b5449 Mon Sep 17 00:00:00 2001 From: atef Date: Thu, 2 Mar 2023 15:22:00 +0100 Subject: [PATCH] Introduce number type --- csharp/Lib/Units/Number.cs | 13 +++++ csharp/Lib/Units/Number.generated.cs | 77 ++++++++++++++++++++++++++++ 2 files changed, 90 insertions(+) create mode 100644 csharp/Lib/Units/Number.cs create mode 100644 csharp/Lib/Units/Number.generated.cs diff --git a/csharp/Lib/Units/Number.cs b/csharp/Lib/Units/Number.cs new file mode 100644 index 000000000..fdc9b3b42 --- /dev/null +++ b/csharp/Lib/Units/Number.cs @@ -0,0 +1,13 @@ +using InnovEnergy.Lib.Units.Generator; + + +namespace InnovEnergy.Lib.Units; + +[Sum] +public readonly partial struct Number +{ + public static String Unit => ""; + public static String Symbol => ""; + + public Number(Decimal value) => Value = value; +} \ No newline at end of file diff --git a/csharp/Lib/Units/Number.generated.cs b/csharp/Lib/Units/Number.generated.cs new file mode 100644 index 000000000..bfe8bcf8e --- /dev/null +++ b/csharp/Lib/Units/Number.generated.cs @@ -0,0 +1,77 @@ +#nullable enable // Auto-generated code requires an explicit '#nullable' directive in source. +#define Sum + +using static System.Math; + +namespace InnovEnergy.Lib.Units; + +using T = Number; + +public readonly partial struct Number +{ + public Decimal Value { get; } + public override String ToString() => Value + Unit; + + // scalar multiplication + + public static T operator *(Decimal scalar, T t) => new T(scalar * t.Value); + public static T operator *(T t, Decimal scalar) => new T(scalar * t.Value); + public static T operator /(T t, Decimal scalar) => new T(t.Value / scalar); + + // parallel + + #if Sum + + public static T operator |(T left, T right) => new T(left.Value + right.Value); + public static T operator -(T t) => new T(-t.Value); + + #elif Mean + + public static T operator |(T left, T right) => new T((left.Value + right.Value)/2m); + + #elif Equal + + public static T operator |(T left, T right) + { + var d = Max(Abs(left.Value), Abs(right.Value)); + + if (d == 0m) + return new T(0m); + + var relativeError = Abs(left.Value - right.Value) / d; + + const Decimal maxRelativeError = 0.05m; + + if (relativeError > maxRelativeError) + throw new Exception($"{nameof(left)} and {nameof(right)} must be approximately equal.\n" + + $"Difference > {maxRelativeError * 100}% detected\n" + + $"{nameof(left)} : {left}\n" + + $"{nameof(right)}: {right}"); + + return new T((left.Value + right.Value) / 2m); + } + #endif + + // compare + + public static Boolean operator ==(T left, T right) => left.Value == right.Value; + public static Boolean operator !=(T left, T right) => left.Value != right.Value; + public static Boolean operator > (T left, T right) => left.Value > right.Value; + public static Boolean operator < (T left, T right) => left.Value < right.Value; + public static Boolean operator >=(T left, T right) => left.Value >= right.Value; + public static Boolean operator <=(T left, T right) => left.Value <= right.Value; + + // conversion + + public static implicit operator T(Decimal d) => new T(d); + public static implicit operator T(Double d) => new T((Decimal)d); + public static implicit operator T(Int32 i) => new T(i); + public static implicit operator Decimal(T t) => t.Value; + + // equality + + public Boolean Equals(T other) => Value == other.Value; + public override Boolean Equals(Object? obj) => obj is T other && Equals(other); + public override Int32 GetHashCode() => Value.GetHashCode(); + +}