Improve CryptoUtils with wrappers for managed implementations of standard hashing...
[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         protected int nWidth;
32         protected uint[] pn;
33
34         public double getDouble()
35         {
36             double ret = 0.0;
37             double fact = 1.0;
38
39             for (int i = 0; i < nWidth; i++)
40             {
41                 ret += fact * pn[i];
42                 fact *= 4294967296.0;
43             }
44
45             return ret;
46         }
47
48         public ulong GetLow64()
49         {
50             return pn[0] | (ulong)pn[1] << 32;
51         }
52
53         public uint GetLow32()
54         {
55             return pn[0];
56         }
57
58         /// <summary>
59         /// Total size in bytes.
60         /// </summary>
61         public int Size
62         {
63             get
64             {
65                 return nWidth * sizeof(uint);
66             }
67         }
68
69         /// <summary>
70         /// Zero or the position of highest non-zero bit plus one.
71         /// </summary>
72         protected int bits
73         {
74             get
75             {
76                 for (int pos = nWidth - 1; pos >= 0; pos--)
77                 {
78                     if (pn[pos]!=0)
79                     {
80                         for (int bits = 31; bits > 0; bits--)
81                         {
82                             if ((pn[pos] & 1 << bits)!=0)
83                                 return 32 * pos + bits + 1;
84                         }
85                         return 32 * pos + 1;
86                     }
87                 }
88                 return 0;
89             }
90         }
91
92         public static bool operator !(base_uint a)
93         {
94             for (int i = 0; i < a.nWidth; i++)
95             {
96                 if (a.pn[i] != 0)
97                 {
98                     return false;
99                 }
100             }
101             return true;
102         }
103
104
105         #region Comparison operations
106         public static bool operator <(base_uint a, base_uint b)
107         {
108             for (int i = a.nWidth - 1; i >= 0; i--)
109             {
110                 if (a.pn[i] < b.pn[i])
111                 {
112                     return true;
113                 }
114                 else if (a.pn[i] > b.pn[i])
115                 {
116                     return false;
117                 }
118             }
119             return false;
120         }
121
122         public static bool operator <=(base_uint a, base_uint b)
123         {
124             for (int i = a.nWidth - 1; i >= 0; i--)
125             {
126                 if (a.pn[i] < b.pn[i])
127                 {
128                     return true;
129                 }
130                 else if (a.pn[i] > b.pn[i])
131                 {
132                     return false;
133                 }
134             }
135             return true;
136         }
137
138         public static bool operator >(base_uint a, base_uint b)
139         {
140             for (int i = a.nWidth - 1; i >= 0; i--)
141             {
142                 if (a.pn[i] > b.pn[i])
143                 {
144                     return true;
145                 }
146                 else if (a.pn[i] < b.pn[i])
147                 {
148                     return false;
149                 }
150             }
151             return false;
152         }
153
154         public static bool operator >=(base_uint a, base_uint b)
155         {
156             for (int i = a.nWidth - 1; i >= 0; i--)
157             {
158                 if (a.pn[i] > b.pn[i])
159                 {
160                     return true;
161                 }
162                 else if (a.pn[i] < b.pn[i])
163                 {
164                     return false;
165                 }
166             }
167             return true;
168         }
169         #endregion
170
171         #region Equality operators
172         public static bool operator ==(base_uint a, base_uint b)
173         {
174             if (object.ReferenceEquals(a, b))
175             {
176                 return true;
177             }
178
179             for (int i = 0; i < a.nWidth; i++)
180             {
181                 if (a.pn[i] != b.pn[i])
182                 {
183                     return false;
184                 }
185             }
186             return true;
187         }
188
189         public static bool operator ==(base_uint a, ulong b)
190         {
191             if (a.pn[0] != (uint)b)
192             {
193                 return false;
194             }
195
196             if (a.pn[1] != (uint)(b >> 32))
197             {
198                 return false;
199             }
200
201             for (int i = 2; i < a.nWidth; i++)
202             {
203                 if (a.pn[i] != 0)
204                 {
205                     return false;
206                 }
207             }
208             return true;
209         }
210
211         public static bool operator !=(base_uint a, base_uint b)
212         {
213             return (!(a == b));
214         }
215
216         public static bool operator !=(base_uint a, ulong b)
217         {
218             return (!(a == b));
219         }
220         #endregion
221
222         #region Cast oerations
223         /// <summary>
224         /// True cast operator
225         /// </summary>
226         /// <param name="a"></param>
227         /// <returns></returns>
228         public static bool operator true(base_uint a)
229         {
230             return (a != 0);
231         }
232
233         /// <summary>
234         /// False cast operator.
235         /// </summary>
236         /// <param name="a">Value</param>
237         /// <returns>Boolean result</returns>
238         public static bool operator false(base_uint a)
239         {
240             return (a == 0);
241         }
242
243         /// <summary>
244         /// Imlicit byte[] cast operator.
245         /// </summary>
246         /// <param name="a">Value</param>
247         public static implicit operator byte[] (base_uint a)
248         {
249             return Interop.LEBytes(a.pn);
250         }
251         #endregion
252
253         /// <summary>
254         /// Arrays equality checking helper method.
255         /// </summary>
256         /// <param name="a">Array 1</param>
257         /// <param name="b">Array 2</param>
258         /// <returns>Result.</returns>
259         private static bool ArraysEqual(uint[] a, uint[] b)
260         {
261             Contract.Requires<ArgumentException>(a.Length == b.Length, "Array length mismatch.");
262
263             for (int i = 0; i < a.Length; i++)
264             {
265                 if (a[i] != b[i])
266                 {
267                     return false;
268                 }
269             }
270             return true;
271         }
272
273
274         #region IEqualityComparer
275         public bool Equals(base_uint a, base_uint b)
276         {
277             if (object.ReferenceEquals(a, b))
278             {
279                 return true;
280             }
281
282             return ArraysEqual(a.pn, b.pn);
283         }
284
285         public int GetHashCode(base_uint a)
286         {
287             return a.GetHashCode();
288         }
289
290         #endregion
291
292         #region IComparable
293         public int CompareTo(base_uint item)
294         {
295             if (this > item)
296             {
297                 return 1;
298             }
299             else if (this < item)
300             {
301                 return -1;
302             }
303
304             return 0;
305         }
306         #endregion
307
308         #region IEquatable
309         public bool Equals(base_uint a)
310         {
311             if (a == null)
312             {
313                 return false;
314             }
315
316             return ArraysEqual(pn, a.pn);
317         }
318
319         public override int GetHashCode()
320         {
321             int hash = 17;
322             unchecked
323             {
324                 foreach (var element in pn)
325                 {
326                     hash = hash * 31 + element.GetHashCode();
327                 }
328             }
329             return hash;
330         }
331
332         public override bool Equals(object o)
333         {
334             return Equals(o as base_uint);
335         }
336         #endregion
337
338         /// <summary>
339         /// Serialize to string.
340         /// </summary>
341         /// <returns></returns>
342         public override string ToString()
343         {
344             return Interop.ToHex(Interop.ReverseBytes(this));
345         }
346     }
347 }