5
5
6
6
using System ;
7
7
using System . Collections . Generic ;
8
+ using System . Diagnostics . Contracts ;
8
9
9
10
namespace Open . Arithmetic
10
11
{
@@ -14,51 +15,72 @@ public static class MathExtensions
14
15
static void ValidateIntPower ( int power )
15
16
{
16
17
if ( power < 0 )
17
- throw new ArgumentOutOfRangeException ( nameof ( power ) , power , "In order to maintain the interger math, power cannot be negative." ) ;
18
+ throw new ArgumentOutOfRangeException ( nameof ( power ) , power ,
19
+ "In order to maintain the interger math, power cannot be negative." ) ;
18
20
}
19
21
20
22
/// <summary>
21
23
/// Raise a number to the power of another. Uses integer math only.
22
24
/// </summary>
23
- /// <param name="value"> </param>
24
- /// <param name="power"></param>
25
+ /// <param name="base">The value to multiply. </param>
26
+ /// <param name="power">The number of times to multiply by. </param>
25
27
/// <returns>The value to the power.</returns>
26
- public static int PowerOf ( this int value , int power )
28
+ public static int PowerOf ( this int @base , int power )
27
29
{
28
30
ValidateIntPower ( power ) ;
29
31
30
- if ( value == 0 || value == 1 )
31
- return value ;
32
+ var result = 1 ;
33
+ while ( power != 0 )
34
+ {
35
+ if ( ( power & 1 ) == 1 )
36
+ result *= @base ;
37
+ power >>= 1 ;
38
+ @base *= @base ;
39
+ }
32
40
33
- if ( value == - 1 )
34
- return power % 2 == 0 ? 1 : - 1 ;
41
+ return result ;
42
+ }
35
43
36
- var v = 1 ;
37
- for ( var i = 1 ; i < power ; i ++ )
38
- v *= value ;
39
- return v ;
44
+ /// <summary>
45
+ /// Raise a number to the power of another. Uses integer math only.
46
+ /// </summary>
47
+ /// <param name="base">The value to multiply.</param>
48
+ /// <param name="power">The number of times to multiply by.</param>
49
+ /// <returns>The value to the power.</returns>
50
+ public static ulong PowerOf ( this ulong @base , int power )
51
+ {
52
+ ulong result = 1 ;
53
+ while ( power != 0 )
54
+ {
55
+ if ( ( power & 1 ) == 1 )
56
+ result *= @base ;
57
+ power >>= 1 ;
58
+ @base *= @base ;
59
+ }
60
+
61
+ return result ;
40
62
}
41
63
42
64
/// <summary>
43
65
/// Raise a number to the power of another. Uses integer math only.
44
66
/// </summary>
45
- /// <param name="value"> </param>
46
- /// <param name="power"></param>
67
+ /// <param name="base">The value to multiply. </param>
68
+ /// <param name="power">The number of times to multiply by. </param>
47
69
/// <returns>The value to the power.</returns>
48
- public static long PowerOf ( this long value , int power )
70
+ public static long PowerOf ( this long @base , int power )
49
71
{
50
72
ValidateIntPower ( power ) ;
51
73
52
- if ( value == 0L || value == 1L )
53
- return value ;
54
-
55
- if ( value == - 1L )
56
- return power % 2 == 0 ? 1L : - 1L ;
74
+ long result = 1 ;
75
+ while ( power != 0 )
76
+ {
77
+ if ( ( power & 1 ) == 1 )
78
+ result *= @base ;
79
+ power >>= 1 ;
80
+ @base *= @base ;
81
+ }
57
82
58
- var v = 1L ;
59
- for ( var i = 1 ; i < power ; i ++ )
60
- v *= value ;
61
- return v ;
83
+ return result ;
62
84
}
63
85
64
86
/// <summary>
@@ -69,7 +91,8 @@ public static long PowerOf(this long value, int power)
69
91
public static int AsInteger ( this bool [ ] source )
70
92
{
71
93
if ( source == null ) throw new NullReferenceException ( ) ;
72
- if ( source . Length > 32 ) throw new ArgumentOutOfRangeException ( "Array cannot be greater than 32 bits." ) ;
94
+ if ( source . Length > 32 ) throw new ArgumentOutOfRangeException ( nameof ( source ) , source , "Array cannot be greater than 32 bits." ) ;
95
+ Contract . EndContractBlock ( ) ;
73
96
74
97
var result = 0 ;
75
98
@@ -81,14 +104,15 @@ public static int AsInteger(this bool[] source)
81
104
}
82
105
83
106
/// <summary>
84
- /// Converts a set of booleans (0|1) to a 32 bit integer.
107
+ /// Converts a set of booleans (0|1) to a 64 bit integer.
85
108
/// </summary>
86
- /// <param name="source">A array of 32 booleans or less.</param>
87
- /// <returns>32 bit integer</returns>
109
+ /// <param name="source">A array of 64 booleans or less.</param>
110
+ /// <returns>64 bit integer</returns>
88
111
public static long AsLong ( this bool [ ] source )
89
112
{
90
113
if ( source == null ) throw new NullReferenceException ( ) ;
91
- if ( source . Length > 64 ) throw new ArgumentOutOfRangeException ( "Array cannot be greater than 32 bits." ) ;
114
+ if ( source . Length > 64 ) throw new ArgumentOutOfRangeException ( nameof ( source ) , source , "Array cannot be greater than 64 bits." ) ;
115
+ Contract . EndContractBlock ( ) ;
92
116
93
117
long result = 0 ;
94
118
@@ -99,10 +123,18 @@ public static long AsLong(this bool[] source)
99
123
return result ;
100
124
}
101
125
102
- public static double Product ( this IEnumerable < double > source )
126
+ /// <summary>
127
+ /// Multiplies a set of numbers together.
128
+ /// </summary>
129
+ /// <param name="source">The source enumerable.</param>
130
+ /// <param name="defaultValueIfNoElements">The value to return if the sequence contains no elements.</param>
131
+ /// <returns>The resultant product.</returns>
132
+ public static double Product ( this IEnumerable < double > source ,
133
+ double defaultValueIfNoElements = double . NaN )
103
134
{
104
-
105
- if ( source == null ) throw new NullReferenceException ( ) ;
135
+ if ( source == null )
136
+ throw new NullReferenceException ( ) ;
137
+ Contract . EndContractBlock ( ) ;
106
138
107
139
var any = false ;
108
140
var result = 1d ;
@@ -113,13 +145,24 @@ public static double Product(this IEnumerable<double> source)
113
145
result *= s ;
114
146
}
115
147
116
- return any ? result : double . NaN ;
148
+ return any ? result : defaultValueIfNoElements ;
117
149
}
118
150
119
- public static double AverageDouble ( this IEnumerable < double > source )
151
+ /// <summary>
152
+ /// Sums all the values of the sequence and divides by the count of the elements. (The average of the sequence.)
153
+ /// </summary>
154
+ /// <param name="source">The source enumerable.</param>
155
+ /// <param name="defaultValueIfNoElements">The value to return if the sequence contains no elements.</param>
156
+ /// <returns>The resultant average of the sequence.</returns>
157
+ public static double AverageDouble ( this IEnumerable < double > source ,
158
+ double defaultValueIfNoElements = double . NaN )
120
159
{
160
+ if ( source == null )
161
+ throw new NullReferenceException ( ) ;
162
+ Contract . EndContractBlock ( ) ;
163
+
121
164
double sum = 0 ;
122
- double count = 0 ;
165
+ var count = 0 ;
123
166
foreach ( var s in source )
124
167
{
125
168
if ( double . IsNaN ( s ) )
@@ -129,28 +172,40 @@ public static double AverageDouble(this IEnumerable<double> source)
129
172
}
130
173
131
174
if ( count == 0 )
132
- return double . NaN ;
175
+ return defaultValueIfNoElements ;
133
176
134
177
return sum / count ;
135
178
}
136
179
180
+ /// <summary>
181
+ /// Takes the first element in the sequence and divides it by the following elements.
182
+ /// </summary>
183
+ /// <param name="source">The source enumerable.</param>
184
+ /// <returns>The resultant quotiient.</returns>
137
185
public static double Quotient ( this IEnumerable < double > source )
138
186
{
139
- if ( source == null ) throw new NullReferenceException ( ) ;
187
+ if ( source == null )
188
+ throw new NullReferenceException ( ) ;
189
+ Contract . EndContractBlock ( ) ;
140
190
141
191
var index = 0 ;
142
192
var result = double . NaN ;
143
193
foreach ( var s in source )
144
194
{
145
195
if ( double . IsNaN ( s ) ) return double . NaN ;
146
- if ( index == 0 )
147
- {
148
- if ( s == 0 ) return 0 ;
149
- result = s ;
150
- }
151
- else
196
+ switch ( index )
152
197
{
153
- result /= s ;
198
+ // ReSharper disable once CompareOfFloatsByEqualityOperator
199
+ case 0 when s == 0 :
200
+ return 0 ;
201
+ case 0 :
202
+ result = s ;
203
+ break ;
204
+ default :
205
+ // ReSharper disable once CompareOfFloatsByEqualityOperator
206
+ if ( s == 0 ) return double . NaN ;
207
+ result /= s ;
208
+ break ;
154
209
}
155
210
156
211
index ++ ;
@@ -159,12 +214,27 @@ public static double Quotient(this IEnumerable<double> source)
159
214
return result ;
160
215
}
161
216
217
+ /// <summary>
218
+ /// Takes the numerator and divides it by the divisors.
219
+ /// </summary>
220
+ /// <param name="divisors">The source enumerable.</param>
221
+ /// <param name="numerator">The value to divide.</param>
222
+ /// <returns>The resultant quotient.</returns>
162
223
public static double QuotientOf ( this IEnumerable < double > divisors , double numerator )
163
224
{
225
+ if ( divisors == null )
226
+ throw new NullReferenceException ( ) ;
227
+ Contract . EndContractBlock ( ) ;
228
+
229
+ // ReSharper disable once CompareOfFloatsByEqualityOperator
230
+ if ( double . IsNaN ( numerator ) || double . IsInfinity ( numerator ) || numerator == 0 )
231
+ return numerator ;
232
+
164
233
var any = false ;
165
234
var result = numerator ;
166
235
foreach ( var s in divisors )
167
236
{
237
+ // ReSharper disable once CompareOfFloatsByEqualityOperator
168
238
if ( s == 0 || double . IsNaN ( s ) ) return double . NaN ;
169
239
result /= s ;
170
240
any = true ;
@@ -173,27 +243,6 @@ public static double QuotientOf(this IEnumerable<double> divisors, double numera
173
243
return any ? result : double . NaN ;
174
244
}
175
245
176
- public static double Difference ( this IEnumerable < double > source )
177
- {
178
- if ( source == null ) throw new NullReferenceException ( ) ;
179
-
180
- var any = false ;
181
- var result = 0d ;
182
- foreach ( var s in source )
183
- {
184
- if ( double . IsNaN ( s ) ) return double . NaN ;
185
- if ( ! any )
186
- result = s ;
187
- else
188
- result -= s ;
189
-
190
- any = true ;
191
-
192
- }
193
-
194
- return any ? result : double . NaN ;
195
- }
196
-
197
246
198
247
}
199
248
}
0 commit comments