uint256 division stub
[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         public static uint256 operator ++(uint256 a)
206         {
207             int i = 0;
208             while (++a.pn[i] == 0 && i < a.nWidth - 1)
209             {
210                 i++;
211             }
212             return a;
213         }
214
215         public static uint256 operator --(uint256 a)
216         {
217             int i = 0;
218             while (--a.pn[i] == uint.MaxValue && i < a.nWidth - 1)
219             {
220                 i++;
221             }
222             return a;
223         }
224
225
226         public static uint256 operator +(uint256 a, uint256 b)
227         {
228             var result = new uint256();
229             ulong carry = 0;
230             for (int i = 0; i < result.nWidth; i++)
231             {
232                 ulong n = carry + a.pn[i] + b.pn[i];
233                 result.pn[i] = (uint)(n & 0xffffffff);
234                 carry = n >> 32;
235             }
236             return result;
237         }
238
239         public static uint256 operator +(uint256 a, ulong b)
240         {
241             return a + new uint256(b);
242         }
243
244         public static uint256 operator -(uint256 a, uint256 b)
245         {
246             return a + (-b);
247         }
248
249         public static uint256 operator -(uint256 a, ulong b)
250         {
251             return a - new uint256(b);
252         }
253
254         public static uint256 operator /(uint256 a, uint divisor)
255         {
256             var result = new uint256();
257
258             ulong r = 0;
259             int i = a.nWidth;
260
261             while (i-- > 0)
262             {
263                 r <<= 32;
264                 r |= a.pn[i];
265                 result.pn[i] = (uint)(r / divisor);
266                 r %= divisor;
267             }
268
269             return result;
270         }
271
272         public static uint256 operator *(uint256 a, uint multiplier)
273         {
274             var result = new uint256();
275
276             ulong c = 0;
277             uint i = 0;
278
279             do
280             {
281                 c += a.pn[i] * (ulong)multiplier;
282                 result.pn[i] = (uint)c;
283                 c >>= 32;
284             } while (++i < result.nWidth);
285
286             return result;
287         }
288
289         public static uint operator %(uint256 a, uint divisor)
290         {
291             ulong r = 0;
292             int i = a.nWidth;
293
294             while (i-- > 0)
295             {
296                 r <<= 32;
297                 r |= a.pn[i];
298                 r %= divisor;
299             }
300
301             return (uint)r;
302         }
303
304         public static uint256 operator /(uint256 a, uint256 divisor)
305         {
306             if (divisor.bits <= 32)
307             {
308                 return a / divisor.Low32;
309             }
310
311             return Divide(a, divisor)[0];
312         }
313
314         public static uint256 operator %(uint256 a, uint256 divisor)
315         {
316             if (divisor.bits <= 32)
317             {
318                 return a % divisor.Low32;
319             }
320
321             return Divide(a, divisor)[1];
322         }
323         #endregion
324
325         public static uint256[] Divide(uint256 bi1, uint256 bi2)
326         {
327             // STUB!
328
329             uint256[] ret = new uint256[2] { 0, 0 };
330
331             return ret;
332         }
333
334
335
336         #region Shift
337         public static uint256 operator <<(uint256 a, int shift)
338         {
339             var result = new uint256();
340             int k = shift / 32;
341             shift = shift % 32;
342
343             for (int i = 0; i < a.nWidth; i++)
344             {
345                 if (i + k + 1 < a.nWidth && shift != 0)
346                 {
347                     result.pn[i + k + 1] |= (a.pn[i] >> (32 - shift));
348                 }
349
350                 if (i + k < a.nWidth)
351                 {
352                     result.pn[i + k] |= (a.pn[i] << shift);
353                 }
354             }
355
356             return result;
357         }
358
359         public static uint256 operator >>(uint256 a, int shift)
360         {
361             var result = new uint256();
362             int k = shift / 32;
363             shift = shift % 32;
364
365             for (int i = 0; i < a.nWidth; i++)
366             {
367                 if (i - k - 1 >= 0 && shift != 0)
368                 {
369                     result.pn[i - k - 1] |= (a.pn[i] << (32 - shift));
370                 }
371
372                 if (i - k >= 0)
373                 {
374                     result.pn[i - k] |= (a.pn[i] >> shift);
375                 }
376             }
377
378             return result;
379         }
380         #endregion
381     }
382 }