072111f620af3eedd6ffbd8a1efffd250aac85e6
[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         private static bool ArraysEqual(uint[] a, uint[] b)
254         {
255             Contract.Requires<ArgumentException>(a.Length == b.Length, "Array length mismatch.");
256
257             for (int i = 0; i < a.Length; i++)
258             {
259                 if (a[i] != b[i])
260                 {
261                     return false;
262                 }
263             }
264             return true;
265         }
266
267
268         #region IEqualityComparer
269         public bool Equals(base_uint a, base_uint b)
270         {
271             if (object.ReferenceEquals(a, b))
272             {
273                 return true;
274             }
275
276             return ArraysEqual(a.pn, b.pn);
277         }
278
279         public int GetHashCode(base_uint a)
280         {
281             return a.GetHashCode();
282         }
283
284         #endregion
285
286         #region IComparable
287         public int CompareTo(base_uint item)
288         {
289             if (this > item)
290             {
291                 return 1;
292             }
293             else if (this < item)
294             {
295                 return -1;
296             }
297
298             return 0;
299         }
300         #endregion
301
302         #region IEquatable
303         public bool Equals(base_uint a)
304         {
305             if (a == null)
306             {
307                 return false;
308             }
309
310             return ArraysEqual(pn, a.pn);
311         }
312
313         public override int GetHashCode()
314         {
315             int hash = 17;
316             unchecked
317             {
318                 foreach (var element in pn)
319                 {
320                     hash = hash * 31 + element.GetHashCode();
321                 }
322             }
323             return hash;
324         }
325
326         public override bool Equals(object o)
327         {
328             return Equals(o as base_uint);
329         }
330         #endregion
331
332         public override string ToString()
333         {
334             return Interop.ToHex(Interop.ReverseBytes(this));
335         }
336     }
337 }