-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathProcedureResult.cs
107 lines (85 loc) · 3.03 KB
/
ProcedureResult.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
using Open.Numeric.Precision;
using System;
using System.Globalization;
#if NET7_0_OR_GREATER
using System.Numerics;
#endif
namespace Open.Numeric;
public readonly record struct ProcedureResult : IComparable<ProcedureResult>, IProcedureResult<double>
{
public int Count { get; }
public double Sum { get; }
public double Average { get; }
public ProcedureResult(double sum, int count)
{
Count = count;
Sum = sum;
Average = count == 0 ? 0 : sum / count;
}
public ProcedureResult Add(double value, int count = 1)
=> new(Sum + value, Count + count);
[System.Diagnostics.CodeAnalysis.SuppressMessage("Style", "IDE0046:Convert to conditional expression")]
public int CompareTo(ProcedureResult other)
{
var a = Average;
var b = other.Average;
if (a.IsNearEqual(b, 0.00000001) && a.ToString(CultureInfo.InvariantCulture) == b.ToString(CultureInfo.InvariantCulture))
return 0; // We hate precision issues. :( 1==1 dammit!
if (a < b || double.IsNaN(a) && !double.IsNaN(b)) return -1;
if (a > b || !double.IsNaN(a) && double.IsNaN(b)) return +1;
if (Count < other.Count) return -1;
if (Count > other.Count) return +1;
return 0;
}
public static ProcedureResult operator +(ProcedureResult a, ProcedureResult b)
=> new(
a.Sum + b.Sum,
a.Count + b.Count
);
public static bool operator >(ProcedureResult a, ProcedureResult b) => a.CompareTo(b) == 1;
public static bool operator <(ProcedureResult a, ProcedureResult b) => a.CompareTo(b) == -1;
public static bool operator >=(ProcedureResult a, ProcedureResult b) => a.CompareTo(b) >= 0;
public static bool operator <=(ProcedureResult a, ProcedureResult b) => a.CompareTo(b) <= 0;
}
#if NET7_0_OR_GREATER
public readonly record struct ProcedureResult<T>
: IComparable<ProcedureResult<T>>, IProcedureResult<T>
where T : notnull, INumber<T>
{
public int Count { get; }
public T Sum { get; }
public T Average { get; }
public ProcedureResult(T sum, int count)
{
Count = count;
Sum = sum;
Average = count == 0 ? 0 : sum / (dynamic)count;
}
public ProcedureResult<T> Add(T value, int count = 1)
=> new(Sum + value, Count + count);
[System.Diagnostics.CodeAnalysis.SuppressMessage("Style", "IDE0046:Convert to conditional expression")]
public int CompareTo(ProcedureResult<T> other)
{
var a = Average;
var b = other.Average;
if (a < b || T.IsNaN(a) && !T.IsNaN(b)) return -1;
if (a > b || !T.IsNaN(a) && T.IsNaN(b)) return +1;
if (Count < other.Count) return -1;
if (Count > other.Count) return +1;
return 0;
}
public static ProcedureResult<T> operator +(ProcedureResult<T> a, ProcedureResult<T> b)
=> new(
a.Sum + b.Sum,
a.Count + b.Count
);
public static bool operator >(ProcedureResult<T> a, ProcedureResult<T> b)
=> a.CompareTo(b) == 1;
public static bool operator <(ProcedureResult<T> a, ProcedureResult<T> b)
=> a.CompareTo(b) == -1;
public static bool operator >=(ProcedureResult<T> a, ProcedureResult<T> b)
=> a.CompareTo(b) >= 0;
public static bool operator <=(ProcedureResult<T> a, ProcedureResult<T> b)
=> a.CompareTo(b) <= 0;
}
#endif