Remove legacy stake reward calculation code.
[NovacoinLibrary.git] / Novacoin / base_uint.cs
1 \feff/**
2 *  Novacoin classes library
3 *  Copyright (C) 2015 Alex D. (balthazar.ad@gmail.com)
4
5 *  This program is free software: you can redistribute it and/or modify
6 *  it under the terms of the GNU Affero General Public License as
7 *  published by the Free Software Foundation, either version 3 of the
8 *  License, or (at your option) any later version.
9
10 *  This program is distributed in the hope that it will be useful,
11 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
12 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 *  GNU Affero General Public License for more details.
14
15 *  You should have received a copy of the GNU Affero General Public License
16 *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
17 */
18
19
20 using System;
21 using System.Collections.Generic;
22 using System.Diagnostics.Contracts;
23
24 namespace Novacoin
25 {
26     /// <summary>
27     /// Base class for uint256 and uint160.
28     /// </summary>
29     public class base_uint : IComparable<base_uint>, IEquatable<base_uint>, IEqualityComparer<base_uint>
30     {
31         #region Internal representation
32         /// <summary>
33         /// Length of internal representation
34         /// </summary>
35         protected int nWidth;
36         /// <summary>
37         /// Big numbers are stored as array of unsigned 32-bit integers.
38         /// </summary>
39         protected uint[] pn;
40         #endregion
41
42         #region Helper properties
43         public double Double
44         {
45             get
46             {
47                 double ret = 0.0;
48                 double fact = 1.0;
49
50                 for (int i = 0; i < nWidth; i++)
51                 {
52                     ret += fact * pn[i];
53                     fact *= 4294967296.0;
54                 }
55
56                 return ret;
57             }
58         }
59
60         /// <summary>
61         /// First 64 bits as ulong value.
62         /// </summary>
63         public ulong Low64
64         {
65             get { return pn[0] | (ulong)pn[1] << 32; }
66         }
67
68         /// <summary>
69         /// First 32 bits as uint value.
70         /// </summary>
71         public uint Low32
72         {
73             get { return pn[0]; }
74         }
75
76         /// <summary>
77         /// Total size in bytes.
78         /// </summary>
79         public int Size
80         {
81             get
82             {
83                 return nWidth * sizeof(uint);
84             }
85         }
86
87         /// <summary>
88         /// Zero or the position of highest non-zero bit plus one.
89         /// </summary>
90         public int bits
91         {
92             get
93             {
94                 for (int pos = nWidth - 1; pos >= 0; pos--)
95                 {
96                     if (pn[pos] != 0)
97                     {
98                         for (int bits = 31; bits > 0; bits--)
99                         {
100                             if ((pn[pos] & 1 << bits) != 0)
101                                 return 32 * pos + bits + 1;
102                         }
103                         return 32 * pos + 1;
104                     }
105                 }
106                 return 0;
107             }
108         }
109         #endregion
110
111
112         /// <summary>
113         /// Negation operator
114         /// </summary>
115         /// <param name="a">Value</param>
116         /// <returns>True if value is zero, false otherwise.</returns>
117         public static bool operator !(base_uint a)
118         {
119             for (int i = 0; i < a.nWidth; i++)
120             {
121                 if (a.pn[i] != 0)
122                 {
123                     return false;
124                 }
125             }
126             return true;
127         }
128
129
130         #region Comparison operations
131         public static bool operator <(base_uint a, base_uint b)
132         {
133             for (int i = a.nWidth - 1; i >= 0; i--)
134             {
135                 if (a.pn[i] < b.pn[i])
136                 {
137                     return true;
138                 }
139                 else if (a.pn[i] > b.pn[i])
140                 {
141                     return false;
142                 }
143             }
144             return false;
145         }
146
147         public static bool operator <=(base_uint a, base_uint b)
148         {
149             for (int i = a.nWidth - 1; i >= 0; i--)
150             {
151                 if (a.pn[i] < b.pn[i])
152                 {
153                     return true;
154                 }
155                 else if (a.pn[i] > b.pn[i])
156                 {
157                     return false;
158                 }
159             }
160             return true;
161         }
162
163         public static bool operator >(base_uint a, base_uint b)
164         {
165             for (int i = a.nWidth - 1; i >= 0; i--)
166             {
167                 if (a.pn[i] > b.pn[i])
168                 {
169                     return true;
170                 }
171                 else if (a.pn[i] < b.pn[i])
172                 {
173                     return false;
174                 }
175             }
176             return false;
177         }
178
179         public static bool operator >=(base_uint a, base_uint b)
180         {
181             for (int i = a.nWidth - 1; i >= 0; i--)
182             {
183                 if (a.pn[i] > b.pn[i])
184                 {
185                     return true;
186                 }
187                 else if (a.pn[i] < b.pn[i])
188                 {
189                     return false;
190                 }
191             }
192             return true;
193         }
194         #endregion
195
196         #region Equality operators
197         public static bool operator ==(base_uint a, base_uint b)
198         {
199             if (object.ReferenceEquals(a, b))
200             {
201                 return true;
202             }
203
204             for (int i = 0; i < a.nWidth; i++)
205             {
206                 if (a.pn[i] != b.pn[i])
207                 {
208                     return false;
209                 }
210             }
211             return true;
212         }
213
214         public static bool operator ==(base_uint a, ulong b)
215         {
216             if (a.pn[0] != (uint)b)
217             {
218                 return false;
219             }
220
221             if (a.pn[1] != (uint)(b >> 32))
222             {
223                 return false;
224             }
225
226             for (int i = 2; i < a.nWidth; i++)
227             {
228                 if (a.pn[i] != 0)
229                 {
230                     return false;
231                 }
232             }
233             return true;
234         }
235
236         public static bool operator !=(base_uint a, base_uint b)
237         {
238             return (!(a == b));
239         }
240
241         public static bool operator !=(base_uint a, ulong b)
242         {
243             return (!(a == b));
244         }
245         #endregion
246
247         #region Cast operations
248         /// <summary>
249         /// True cast operator
250         /// </summary>
251         /// <param name="a"></param>
252         /// <returns></returns>
253         public static bool operator true(base_uint a)
254         {
255             return (a != 0);
256         }
257
258         /// <summary>
259         /// False cast operator.
260         /// </summary>
261         /// <param name="a">Value</param>
262         /// <returns>Boolean result</returns>
263         public static bool operator false(base_uint a)
264         {
265             return (a == 0);
266         }
267
268         /// <summary>
269         /// Imlicit byte[] cast operator.
270         /// </summary>
271         /// <param name="a">Value</param>
272         public static implicit operator byte[] (base_uint a)
273         {
274             return Interop.LEBytes(a.pn);
275         }
276         #endregion
277
278         /// <summary>
279         /// Arrays equality checking helper method.
280         /// </summary>
281         /// <param name="a">Array 1</param>
282         /// <param name="b">Array 2</param>
283         /// <returns>Result.</returns>
284         private static bool ArraysEqual(uint[] a, uint[] b)
285         {
286             Contract.Requires<ArgumentException>(a.Length == b.Length, "Array length mismatch.");
287
288             for (int i = 0; i < a.Length; i++)
289             {
290                 if (a[i] != b[i])
291                 {
292                     return false;
293                 }
294             }
295             return true;
296         }
297
298
299         #region IEqualityComparer
300         public bool Equals(base_uint a, base_uint b)
301         {
302             if (object.ReferenceEquals(a, b))
303             {
304                 return true;
305             }
306
307             return ArraysEqual(a.pn, b.pn);
308         }
309
310         public int GetHashCode(base_uint a)
311         {
312             return a.GetHashCode();
313         }
314
315         #endregion
316
317         #region IComparable
318         public int CompareTo(base_uint item)
319         {
320             if (this > item)
321             {
322                 return 1;
323             }
324             else if (this < item)
325             {
326                 return -1;
327             }
328
329             return 0;
330         }
331         #endregion
332
333         #region IEquatable
334         public bool Equals(base_uint a)
335         {
336             if (object.ReferenceEquals(a, null))
337             {
338                 return false;
339             }
340
341             return ArraysEqual(pn, a.pn);
342         }
343
344         public override int GetHashCode()
345         {
346             int hash = 17;
347             unchecked
348             {
349                 foreach (var element in pn)
350                 {
351                     hash = hash * 31 + element.GetHashCode();
352                 }
353             }
354             return hash;
355         }
356
357         public override bool Equals(object o)
358         {
359             return Equals(o as base_uint);
360         }
361         #endregion
362
363         /// <summary>
364         /// Serialize to string.
365         /// </summary>
366         /// <returns></returns>
367         public override string ToString()
368         {
369             return Interop.ToHex(Interop.ReverseBytes(this));
370         }
371     }
372 }