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