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