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