Add Compact property to uint256.
[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.Diagnostics.Contracts;
22
23 namespace Novacoin
24 {
25     /// <summary>
26     /// Base class for uint256 and uint160.
27     /// </summary>
28     public class base_uint : IComparable<base_uint>, IEquatable<base_uint>
29     {
30         protected int nWidth;
31         protected uint[] pn;
32
33         public double getDouble()
34         {
35             double ret = 0.0;
36             double fact = 1.0;
37
38             for (int i = 0; i < nWidth; i++)
39             {
40                 ret += fact * pn[i];
41                 fact *= 4294967296.0;
42             }
43
44             return ret;
45         }
46
47         public ulong GetLow64()
48         {
49             return pn[0] | (ulong)pn[1] << 32;
50         }
51
52         public uint GetLow32()
53         {
54             return pn[0];
55         }
56
57         public int Size
58         {
59             get
60             {
61                 return nWidth;
62             }
63         }
64
65         /// <summary>
66         /// Zero or the position of highest non-zero bit plus one.
67         /// </summary>
68         protected int bits
69         {
70             get
71             {
72                 for (int pos = nWidth - 1; pos >= 0; pos--)
73                 {
74                     if (pn[pos]!=0)
75                     {
76                         for (int bits = 31; bits > 0; bits--)
77                         {
78                             if ((pn[pos] & 1 << bits)!=0)
79                                 return 32 * pos + bits + 1;
80                         }
81                         return 32 * pos + 1;
82                     }
83                 }
84                 return 0;
85             }
86         }
87
88         public static bool operator !(base_uint a)
89         {
90             for (int i = 0; i < a.nWidth; i++)
91             {
92                 if (a.pn[i] != 0)
93                 {
94                     return false;
95                 }
96             }
97             return true;
98         }
99
100
101         public static bool operator <(base_uint a, base_uint b)
102         {
103             for (int i = a.nWidth - 1; i >= 0; i--)
104             {
105                 if (a.pn[i] < b.pn[i])
106                 {
107                     return true;
108                 }
109                 else if (a.pn[i] > b.pn[i])
110                 {
111                     return false;
112                 }
113             }
114             return false;
115         }
116
117         public static bool operator <=(base_uint a, base_uint b)
118         {
119             for (int i = a.nWidth - 1; i >= 0; i--)
120             {
121                 if (a.pn[i] < b.pn[i])
122                 {
123                     return true;
124                 }
125                 else if (a.pn[i] > b.pn[i])
126                 {
127                     return false;
128                 }
129             }
130             return true;
131         }
132
133         public static bool operator >(base_uint a, base_uint b)
134         {
135             for (int i = a.nWidth - 1; i >= 0; i--)
136             {
137                 if (a.pn[i] > b.pn[i])
138                 {
139                     return true;
140                 }
141                 else if (a.pn[i] < b.pn[i])
142                 {
143                     return false;
144                 }
145             }
146             return false;
147         }
148
149         public static bool operator >=(base_uint a, base_uint b)
150         {
151             for (int i = a.nWidth - 1; i >= 0; i--)
152             {
153                 if (a.pn[i] > b.pn[i])
154                 {
155                     return true;
156                 }
157                 else if (a.pn[i] < b.pn[i])
158                 {
159                     return false;
160                 }
161             }
162             return true;
163         }
164
165         public static bool operator ==(base_uint a, base_uint b)
166         {
167             if (object.ReferenceEquals(a, b))
168             {
169                 return true;
170             }
171
172             for (int i = 0; i < a.nWidth; i++)
173             {
174                 if (a.pn[i] != b.pn[i])
175                 {
176                     return false;
177                 }
178             }
179             return true;
180         }
181
182         public static bool operator ==(base_uint a, ulong b)
183         {
184             if (a.pn[0] != (uint)b)
185             {
186                 return false;
187             }
188
189             if (a.pn[1] != (uint)(b >> 32))
190             {
191                 return false;
192             }
193
194             for (int i = 2; i < a.nWidth; i++)
195             {
196                 if (a.pn[i] != 0)
197                 {
198                     return false;
199                 }
200             }
201             return true;
202         }
203
204         public static bool operator !=(base_uint a, base_uint b)
205         {
206             return (!(a == b));
207         }
208
209         public static bool operator !=(base_uint a, ulong b)
210         {
211             return (!(a == b));
212         }
213
214         public static bool operator true(base_uint a)
215         {
216             return (a != 0);
217         }
218
219         public static bool operator false(base_uint a)
220         {
221             return (a == 0);
222         }
223
224         public static implicit operator byte[] (base_uint a)
225         {
226             return Interop.LEBytes(a.pn);
227         }
228
229         private static bool ArraysEqual(uint[] a, uint[] b)
230         {
231             Contract.Requires<ArgumentException>(a.Length == b.Length, "Array length mismatch.");
232
233             for (int i = 0; i < a.Length; i++)
234             {
235                 if (a[i] != b[i])
236                 {
237                     return false;
238                 }
239             }
240             return true;
241         }
242
243         public override int GetHashCode()
244         {
245             int hash = 17;
246             unchecked
247             {
248                 foreach (var element in pn)
249                 {
250                     hash = hash * 31 + element.GetHashCode();
251                 }
252             }
253             return hash;
254         }
255
256         public int CompareTo(base_uint item)
257         {
258             if (this > item)
259             {
260                 return 1;
261             }
262             else if (this < item)
263             {
264                 return -1;
265             }
266
267             return 0;
268         }
269
270         public bool Equals(base_uint a)
271         {
272             if (a == null)
273             {
274                 return false;
275             }
276
277             return ArraysEqual(pn, a.pn);
278         }
279
280         public override bool Equals(object o)
281         {
282             return Equals(o as base_uint);
283         }
284
285         public override string ToString()
286         {
287             return Interop.ToHex(Interop.ReverseBytes(this));
288         }
289     }
290 }