55
66using System ;
77using System . Collections . Generic ;
8+ using System . Diagnostics . Contracts ;
89
910namespace Open . Arithmetic
1011{
@@ -14,51 +15,72 @@ public static class MathExtensions
1415 static void ValidateIntPower ( int power )
1516 {
1617 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." ) ;
1820 }
1921
2022 /// <summary>
2123 /// Raise a number to the power of another. Uses integer math only.
2224 /// </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>
2527 /// <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 )
2729 {
2830 ValidateIntPower ( power ) ;
2931
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+ }
3240
33- if ( value == - 1 )
34- return power % 2 == 0 ? 1 : - 1 ;
41+ return result ;
42+ }
3543
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 ;
4062 }
4163
4264 /// <summary>
4365 /// Raise a number to the power of another. Uses integer math only.
4466 /// </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>
4769 /// <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 )
4971 {
5072 ValidateIntPower ( power ) ;
5173
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+ }
5782
58- var v = 1L ;
59- for ( var i = 1 ; i < power ; i ++ )
60- v *= value ;
61- return v ;
83+ return result ;
6284 }
6385
6486 /// <summary>
@@ -69,7 +91,8 @@ public static long PowerOf(this long value, int power)
6991 public static int AsInteger ( this bool [ ] source )
7092 {
7193 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 ( ) ;
7396
7497 var result = 0 ;
7598
@@ -81,14 +104,15 @@ public static int AsInteger(this bool[] source)
81104 }
82105
83106 /// <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.
85108 /// </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>
88111 public static long AsLong ( this bool [ ] source )
89112 {
90113 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 ( ) ;
92116
93117 long result = 0 ;
94118
@@ -99,10 +123,18 @@ public static long AsLong(this bool[] source)
99123 return result ;
100124 }
101125
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 )
103134 {
104-
105- if ( source == null ) throw new NullReferenceException ( ) ;
135+ if ( source == null )
136+ throw new NullReferenceException ( ) ;
137+ Contract . EndContractBlock ( ) ;
106138
107139 var any = false ;
108140 var result = 1d ;
@@ -113,13 +145,24 @@ public static double Product(this IEnumerable<double> source)
113145 result *= s ;
114146 }
115147
116- return any ? result : double . NaN ;
148+ return any ? result : defaultValueIfNoElements ;
117149 }
118150
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 )
120159 {
160+ if ( source == null )
161+ throw new NullReferenceException ( ) ;
162+ Contract . EndContractBlock ( ) ;
163+
121164 double sum = 0 ;
122- double count = 0 ;
165+ var count = 0 ;
123166 foreach ( var s in source )
124167 {
125168 if ( double . IsNaN ( s ) )
@@ -129,28 +172,40 @@ public static double AverageDouble(this IEnumerable<double> source)
129172 }
130173
131174 if ( count == 0 )
132- return double . NaN ;
175+ return defaultValueIfNoElements ;
133176
134177 return sum / count ;
135178 }
136179
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>
137185 public static double Quotient ( this IEnumerable < double > source )
138186 {
139- if ( source == null ) throw new NullReferenceException ( ) ;
187+ if ( source == null )
188+ throw new NullReferenceException ( ) ;
189+ Contract . EndContractBlock ( ) ;
140190
141191 var index = 0 ;
142192 var result = double . NaN ;
143193 foreach ( var s in source )
144194 {
145195 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 )
152197 {
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 ;
154209 }
155210
156211 index ++ ;
@@ -159,12 +214,27 @@ public static double Quotient(this IEnumerable<double> source)
159214 return result ;
160215 }
161216
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>
162223 public static double QuotientOf ( this IEnumerable < double > divisors , double numerator )
163224 {
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+
164233 var any = false ;
165234 var result = numerator ;
166235 foreach ( var s in divisors )
167236 {
237+ // ReSharper disable once CompareOfFloatsByEqualityOperator
168238 if ( s == 0 || double . IsNaN ( s ) ) return double . NaN ;
169239 result /= s ;
170240 any = true ;
@@ -173,27 +243,6 @@ public static double QuotientOf(this IEnumerable<double> divisors, double numera
173243 return any ? result : double . NaN ;
174244 }
175245
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-
197246
198247 }
199248}
0 commit comments