Add Compact property to uint256.
[NovacoinLibrary.git] / Novacoin / uint256.cs
1 \feffusing System;
2 using System.Collections.Generic;
3 using System.Diagnostics.Contracts;
4 using System.Linq;
5 using System.Text;
6 using System.Threading.Tasks;
7 using System.Numerics;
8
9 namespace Novacoin
10 {
11     public class uint256 : base_uint
12     {
13         new public readonly int nWidth = 8;
14
15         public uint256()
16         {
17             base.nWidth = nWidth;
18             pn = new uint[nWidth];
19
20             for (int i = 0; i < nWidth; i++)
21             {
22                 pn[i] = 0;
23             }
24         }
25
26         public uint256(uint256 b)
27         {
28             base.nWidth = nWidth;
29             pn = new uint[nWidth];
30
31             for (int i = 0; i < nWidth; i++)
32             {
33                 pn[i] = b.pn[i];
34             }
35         }
36
37
38         public uint256(ulong n)
39         {
40             base.nWidth = nWidth;
41             pn = new uint[nWidth];
42
43             pn[0] = (uint)n;
44             pn[1] = (uint)(n >> 32);
45             for (int i = 2; i < nWidth; i++)
46             {
47                 pn[i] = 0;
48             }
49         }
50
51         public uint256(byte[] bytes)
52         {
53             Contract.Requires<ArgumentException>(bytes.Length == 32, "Incorrect array length");
54
55             base.nWidth = nWidth;
56             pn = Interop.ToUInt32Array(bytes);
57         }
58
59         public uint256(string hex)
60         {
61             Contract.Requires<ArgumentException>(hex.Length == 64, "Incorrect string");
62
63             base.nWidth = nWidth;
64             var bytes = Interop.ReverseBytes(Interop.HexToArray(hex));
65             pn = Interop.ToUInt32Array(bytes);
66         }
67
68         /// <summary>
69         /// Compact representation of unsigned 256bit numbers.
70         /// 
71         /// N = (-1^sign) * m * 256^(exp-3)
72         /// 
73         /// http://bitcoin.stackexchange.com/questions/30467/what-are-the-equations-to-convert-between-bits-and-difficulty
74         /// </summary>
75         public uint Compact
76         {
77             get
78             {
79                 int nSize = (bits + 7) / 8;
80                 uint nCompact = 0;
81                 if (nSize <= 3)
82                     nCompact = ((uint)GetLow64()) << 8 * (3 - nSize);
83                 else
84                 {
85                     uint256 bn = this >> 8 * (nSize - 3);
86                     nCompact = (uint)bn.GetLow64();
87                 }
88
89                 if ((nCompact & 0x00800000) != 0)
90                 {
91                     nCompact >>= 8;
92                     nSize++;
93                 }
94
95                 Contract.Assert((nCompact & ~0x007fffff) == 0);
96                 Contract.Assert(nSize < 256);
97
98                 nCompact |= (uint)nSize << 24;
99                 nCompact |= 0;
100
101                 return nCompact;
102             }
103             set {
104                 int nSize = (int)value >> 24;
105                 uint nWord = value & 0x007fffff;
106
107                 uint256 i;
108
109                 if (nSize <= 3)
110                 {
111                     nWord >>= 8 * (3 - nSize);
112                     i = new uint256(nWord);
113                 }
114                 else
115                 {
116                     i = new uint256(nWord);
117                     i <<= 8 * (nSize - 3);
118                 }
119
120                 pn = i.pn;
121             }
122         }
123
124         private void SetBytes(byte[] bytes)
125         {
126             pn = Interop.ToUInt32Array(Interop.ReverseBytes(bytes));
127         }
128
129         public static uint256 operator ~(uint256 a)
130         {
131             var ret = new uint256();
132             for (int i = 0; i < a.nWidth; i++)
133             {
134                 ret.pn[i] = ~a.pn[i];
135             }
136             return ret;
137         }
138
139         public static uint256 operator -(uint256 a)
140         {
141             var ret = new uint256();
142             for (int i = 0; i < a.nWidth; i++)
143             {
144                 ret.pn[i] = ~a.pn[i];
145             }
146             ret++;
147             return ret;
148         }
149
150
151         public static uint256 operator ++(uint256 a)
152         {
153             int i = 0;
154             while (++a.pn[i] == 0 && i < a.nWidth - 1)
155             {
156                 i++;
157             }
158             return a;
159         }
160
161         public static uint256 operator --(uint256 a)
162         {
163             int i = 0;
164             while (--a.pn[i] == uint.MaxValue && i < a.nWidth - 1)
165             {
166                 i++;
167             }
168             return a;
169         }
170
171         public static uint256 operator ^(uint256 a, uint256 b)
172         {
173             var result = new uint256();
174             result.pn = new uint[a.nWidth];
175             for (int i = 0; i < result.nWidth; i++)
176             {
177                 result.pn[i] = a.pn[i] ^ b.pn[i];
178             }
179             return result;
180         }
181
182         public static uint256 operator +(uint256 a, uint256 b)
183         {
184             var result = new uint256();
185             ulong carry = 0;
186             for (int i = 0; i < result.nWidth; i++)
187             {
188                 ulong n = carry + a.pn[i] + b.pn[i];
189                 result.pn[i] = (uint)(n & 0xffffffff);
190                 carry = n >> 32;
191             }
192             return result;
193         }
194
195         public static uint256 operator +(uint256 a, ulong b)
196         {
197             return a + new uint256(b);
198         }
199
200         public static uint256 operator -(uint256 a, uint256 b)
201         {
202             return a + (-b);
203         }
204
205         public static uint256 operator -(uint256 a, ulong b)
206         {
207             return a - new uint256(b);
208         }
209
210         public static uint256 operator &(uint256 a, uint256 b)
211         {
212             var result = new uint256();
213             result.pn = new uint[a.nWidth];
214             for (int i = 0; i < result.nWidth; i++)
215             {
216                 result.pn[i] = a.pn[i] & b.pn[i];
217             }
218             return result;
219         }
220
221         public static uint256 operator |(uint256 a, uint256 b)
222         {
223             var result = new uint256();
224             result.pn = new uint[a.nWidth];
225             for (int i = 0; i < result.nWidth; i++)
226             {
227                 result.pn[i] = a.pn[i] | b.pn[i];
228             }
229             return result;
230         }
231
232         public static uint256 operator <<(uint256 a, int shift)
233         {
234             var result = new uint256();
235             int k = shift / 32;
236             shift = shift % 32;
237
238             for (int i = 0; i < a.nWidth; i++)
239             {
240                 if (i + k + 1 < a.nWidth && shift != 0)
241                 {
242                     result.pn[i + k + 1] |= (a.pn[i] >> (32 - shift));
243                 }
244
245                 if (i + k < a.nWidth)
246                 {
247                     result.pn[i + k] |= (a.pn[i] << shift);
248                 }
249             }
250
251             return result;
252         }
253
254         public static uint256 operator >>(uint256 a, int shift)
255         {
256             var result = new uint256();
257             int k = shift / 32;
258             shift = shift % 32;
259
260             for (int i = 0; i < a.nWidth; i++)
261             {
262                 if (i - k - 1 >= 0 && shift != 0)
263                 {
264                     result.pn[i - k - 1] |= (a.pn[i] << (32 - shift));
265                 }
266
267                 if (i - k >= 0)
268                 {
269                     result.pn[i - k] |= (a.pn[i] >> shift);
270                 }
271             }
272
273             return result;
274         }
275     }
276 }