c2daad5673445e53e6317d3e8a11dec0f5739c73
[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
22 namespace Novacoin
23 {
24     public class base_uint : IComparable<base_uint>, IEquatable<base_uint>
25     {
26         protected int nWidth;
27         protected uint[] pn;
28
29         public double getDouble()
30         {
31             double ret = 0.0;
32             double fact = 1.0;
33
34             for (int i = 0; i < nWidth; i++)
35             {
36                 ret += fact * pn[i];
37                 fact *= 4294967296.0;
38             }
39
40             return ret;
41         }
42
43         public ulong GetLow64()
44         {
45             return pn[0] | (ulong)pn[1] << 32;
46         }
47
48         public uint GetLow32()
49         {
50             return pn[0];
51         }
52
53         public int Size
54         {
55             get
56             {
57                 return nWidth;
58             }
59         }
60
61
62         public static bool operator !(base_uint a)
63         {
64             for (int i = 0; i < a.nWidth; i++)
65             {
66                 if (a.pn[i] != 0)
67                 {
68                     return false;
69                 }
70             }
71             return true;
72         }
73
74         public static base_uint operator ~(base_uint a)
75         {
76             var ret = new base_uint();
77             for (int i = 0; i < a.nWidth; i++)
78             {
79                 ret.pn[i] = ~a.pn[i];
80             }
81             return ret;
82         }
83
84         public static base_uint operator -(base_uint a)
85         {
86             var ret = new base_uint();
87             for (int i = 0; i < a.nWidth; i++)
88             {
89                 ret.pn[i] = ~a.pn[i];
90             }
91             ret++;
92             return ret;
93         }
94
95
96         public static base_uint operator ++(base_uint a)
97         {
98             int i = 0;
99             while (++a.pn[i] == 0 && i < a.nWidth - 1)
100             {
101                 i++;
102             }
103             return a;
104         }
105
106         public static base_uint operator --(base_uint a)
107         {
108             int i = 0;
109             while (--a.pn[i] == uint.MaxValue && i < a.nWidth - 1)
110             {
111                 i++;
112             }
113             return a;
114         }
115
116         public static base_uint operator ^(base_uint a, base_uint b)
117         {
118             var result = new base_uint();
119             result.pn = new uint[a.nWidth];
120             for (int i = 0; i < result.nWidth; i++)
121             {
122                 result.pn[i] = a.pn[i] ^ b.pn[i];
123             }
124             return result;
125         }
126
127         public static base_uint operator +(base_uint a, base_uint b)
128         {
129             var result = new base_uint();
130             ulong carry = 0;
131             for (int i = 0; i < result.nWidth; i++)
132             {
133                 ulong n = carry + a.pn[i] + b.pn[i];
134                 result.pn[i] = (uint)(n & 0xffffffff);
135                 carry = n >> 32;
136             }
137             return result;
138         }
139
140         public static base_uint operator -(base_uint a, base_uint b)
141         {
142             return a + (-b);
143         }
144
145         public static base_uint operator &(base_uint a, base_uint b)
146         {
147             var result = new base_uint();
148             result.pn = new uint[a.nWidth];
149             for (int i = 0; i < result.nWidth; i++)
150             {
151                 result.pn[i] = a.pn[i] & b.pn[i];
152             }
153             return result;
154         }
155
156         public static base_uint operator |(base_uint a, base_uint b)
157         {
158             var result = new base_uint();
159             result.pn = new uint[a.nWidth];
160             for (int i = 0; i < result.nWidth; i++)
161             {
162                 result.pn[i] = a.pn[i] | b.pn[i];
163             }
164             return result;
165         }
166
167         public static bool operator <(base_uint a, base_uint b)
168         {
169             for (int i = a.nWidth - 1; i >= 0; i--)
170             {
171                 if (a.pn[i] < b.pn[i])
172                 {
173                     return true;
174                 }
175                 else if (a.pn[i] > b.pn[i])
176                 {
177                     return false;
178                 }
179             }
180             return false;
181         }
182
183         public static bool operator <=(base_uint a, base_uint b)
184         {
185             for (int i = a.nWidth - 1; i >= 0; i--)
186             {
187                 if (a.pn[i] < b.pn[i])
188                 {
189                     return true;
190                 }
191                 else if (a.pn[i] > b.pn[i])
192                 {
193                     return false;
194                 }
195             }
196             return true;
197         }
198
199         public static bool operator >(base_uint a, base_uint b)
200         {
201             for (int i = a.nWidth - 1; i >= 0; i--)
202             {
203                 if (a.pn[i] > b.pn[i])
204                 {
205                     return true;
206                 }
207                 else if (a.pn[i] < b.pn[i])
208                 {
209                     return false;
210                 }
211             }
212             return false;
213         }
214
215         public static bool operator >=(base_uint a, base_uint b)
216         {
217             for (int i = a.nWidth - 1; i >= 0; i--)
218             {
219                 if (a.pn[i] > b.pn[i])
220                 {
221                     return true;
222                 }
223                 else if (a.pn[i] < b.pn[i])
224                 {
225                     return false;
226                 }
227             }
228             return true;
229         }
230
231         public static bool operator ==(base_uint a, base_uint b)
232         {
233             if (object.ReferenceEquals(a, b))
234             {
235                 return true;
236             }
237
238             for (int i = 0; i < a.nWidth; i++)
239             {
240                 if (a.pn[i] != b.pn[i])
241                 {
242                     return false;
243                 }
244             }
245             return true;
246         }
247
248         public static bool operator ==(base_uint a, ulong b)
249         {
250             if (a.pn[0] != (uint)b)
251             {
252                 return false;
253             }
254             if (a.pn[1] != (uint)(b >> 32))
255             {
256                 return false;
257             }
258             for (int i = 2; i < a.nWidth; i++)
259             {
260                 if (a.pn[i] != 0)
261                 {
262                     return false;
263                 }
264             }
265             return true;
266         }
267
268         public static bool operator !=(base_uint a, base_uint b)
269         {
270             return (!(a == b));
271         }
272
273         public static bool operator !=(base_uint a, ulong b)
274         {
275             return (!(a == b));
276         }
277
278         public static bool operator true(base_uint a)
279         {
280             return (a != 0);
281         }
282
283         public static bool operator false(base_uint a)
284         {
285             return (a == 0);
286         }
287
288         public static implicit operator byte[] (base_uint a)
289         {
290             var result = new byte[a.nWidth];
291             for (int i = 0; i < a.nWidth; i++)
292             {
293                 Buffer.BlockCopy(BitConverter.GetBytes(a.pn[i]), 0, result, 4 * i, 4);
294             }
295             return result;
296         }
297
298         private static bool ArraysEqual(uint[] a, uint[] b)
299         {
300             if (a.Length != b.Length)
301             {
302                 return false;
303             }
304             for (int i = 0; i < a.Length; i++)
305             {
306                 if (a[i] != b[i])
307                 {
308                     return false;
309                 }
310             }
311             return true;
312         }
313
314         public override int GetHashCode()
315         {
316             int hash = 17;
317             unchecked
318             {
319                 foreach (var element in pn)
320                 {
321                     hash = hash * 31 + element.GetHashCode();
322                 }
323             }
324             return hash;
325         }
326
327         public int CompareTo(base_uint item)
328         {
329             if (this > item)
330             {
331                 return 1;
332             }
333             else if (this < item)
334             {
335                 return -1;
336             }
337
338             return 0;
339         }
340
341         public bool Equals(base_uint a)
342         {
343             if (a == null)
344             {
345                 return false;
346             }
347
348             return ArraysEqual(pn, a.pn);
349         }
350     }
351 }