eccfe956f19d30a19a70a1c8070b428afdde8689
[NovacoinLibrary.git] / Novacoin / uint160.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 using System.Linq;
22
23 namespace Novacoin
24 {
25     public class uint160 : base_uint
26     {
27         #region Access to internal representation
28         new protected int nWidth
29         {
30             get { return base.nWidth; }
31             private set { base.nWidth = value; }
32         }
33         new protected uint[] pn
34         {
35             get { return base.pn; }
36             private set { base.pn = value; }
37         }
38         #endregion
39
40         #region Constructors
41         public uint160()
42         {
43             nWidth = 5;
44             pn = new uint[nWidth];
45         }
46
47         public uint160(uint160 b) : this()
48         {
49             for (int i = 0; i < nWidth; i++)
50             {
51                 pn[i] = b.pn[i];
52             }
53         }
54
55
56         public uint160(ulong n) : this()
57         {
58             pn[0] = (uint)n;
59             pn[1] = (uint)(n >> 32);
60             for (int i = 2; i < nWidth; i++)
61             {
62                 pn[i] = 0;
63             }
64         }
65
66         public uint160(byte[] bytes) : this()
67         {
68             Contract.Requires<ArgumentException>(bytes.Length == 20, "Incorrect array length");
69             pn = Interop.ToUInt32Array(bytes);
70         }
71
72         public uint160(string hex) : this()
73         {
74             Contract.Requires<ArgumentException>(hex.Length == 40, "Incorrect string");
75             var bytes = Interop.ReverseBytes(Interop.HexToArray(hex));
76             pn = Interop.ToUInt32Array(bytes);
77         }
78         #endregion
79
80         #region Cast operators
81         public static implicit operator uint160(byte[] bytes)
82         {
83             return new uint160(bytes);
84         }
85
86         public static implicit operator uint160(ulong n)
87         {
88             return new uint160(n);
89         }
90         #endregion
91
92         #region Bitwise operations
93         public static uint160 operator ~(uint160 a)
94         {
95             var ret = new uint160();
96             for (int i = 0; i < a.nWidth; i++)
97             {
98                 ret.pn[i] = ~a.pn[i];
99             }
100             return ret;
101         }
102
103         public static uint160 operator ^(uint160 a, uint160 b)
104         {
105             var result = new uint160();
106             result.pn = new uint[a.nWidth];
107             for (int i = 0; i < result.nWidth; i++)
108             {
109                 result.pn[i] = a.pn[i] ^ b.pn[i];
110             }
111             return result;
112         }
113
114         public static uint160 operator &(uint160 a, uint160 b)
115         {
116             var result = new uint160();
117             result.pn = new uint[a.nWidth];
118             for (int i = 0; i < result.nWidth; i++)
119             {
120                 result.pn[i] = a.pn[i] & b.pn[i];
121             }
122             return result;
123         }
124
125         public static uint160 operator |(uint160 a, uint160 b)
126         {
127             var result = new uint160();
128             result.pn = new uint[a.nWidth];
129             for (int i = 0; i < result.nWidth; i++)
130             {
131                 result.pn[i] = a.pn[i] | b.pn[i];
132             }
133             return result;
134         }
135         #endregion
136
137         #region Basic arithmetics
138         public static uint160 operator +(uint160 a, uint160 b)
139         {
140             var result = new uint160();
141             ulong carry = 0;
142             for (int i = 0; i < result.nWidth; i++)
143             {
144                 ulong n = carry + a.pn[i] + b.pn[i];
145                 result.pn[i] = (uint)(n & 0xffffffff);
146                 carry = n >> 32;
147             }
148             return result;
149         }
150
151         public static uint160 operator +(uint160 a, ulong b)
152         {
153             return a + new uint160(b);
154         }
155
156         public static uint160 operator -(uint160 a, uint160 b)
157         {
158             return a + (-b);
159         }
160
161         public static uint160 operator -(uint160 a, ulong b)
162         {
163             return a - new uint160(b);
164         }
165
166         public static uint160 operator -(uint160 a)
167         {
168             var ret = new uint160();
169             for (int i = 0; i < a.nWidth; i++)
170             {
171                 ret.pn[i] = ~a.pn[i];
172             }
173             ret++;
174             return ret;
175         }
176
177
178         public static uint160 operator ++(uint160 a)
179         {
180             int i = 0;
181             while (++a.pn[i] == 0 && i < a.nWidth - 1)
182             {
183                 i++;
184             }
185             return a;
186         }
187
188         public static uint160 operator --(uint160 a)
189         {
190             int i = 0;
191             while (--a.pn[i] == uint.MaxValue && i < a.nWidth - 1)
192             {
193                 i++;
194             }
195             return a;
196         }
197
198         public static uint160 operator /(uint160 a, uint divisor)
199         {
200             var result = new uint160();
201
202             ulong r = 0;
203             int i = a.nWidth;
204
205             while (i-- > 0)
206             {
207                 r <<= 32;
208                 r |= a.pn[i];
209                 result.pn[i] = (uint)(r / divisor);
210                 r %= divisor;
211             }
212
213             return result;
214         }
215
216         public static uint160 operator *(uint160 a, uint multiplier)
217         {
218             var result = new uint160();
219
220             ulong c = 0;
221             uint i = 0;
222
223             do
224             {
225                 c += a.pn[i] * (ulong)multiplier;
226                 result.pn[i] = (uint)c;
227                 c >>= 32;
228             } while (++i < result.nWidth);
229
230             return result;
231         }
232
233         public static uint operator %(uint160 a, uint divisor)
234         {
235             ulong r = 0;
236             int i = a.nWidth;
237
238             while (i-- > 0)
239             {
240                 r <<= 32;
241                 r |= a.pn[i];
242                 r %= divisor;
243             }
244
245             return (uint)r;
246         }
247
248         public static uint160 operator /(uint160 a, uint160 b)
249         {
250             if (b.bits <= 32)
251             {
252                 return a / b.Low32;
253             }
254
255             uint160 result = new uint160();
256
257             uint[] quotient;
258             uint[] remainder_value;
259
260             int m = a.bits / 32 + (a.bits % 32 != 0 ? 1 : 0);
261             int n = b.bits / 32 + (b.bits % 32 != 0 ? 1 : 0);
262
263             BignumHelper.DivModUnsigned(a.pn.Take(m).ToArray(), b.pn.Take(n).ToArray(), out quotient, out remainder_value);
264
265             quotient.CopyTo(result.pn, 0);
266
267             return result;
268         }
269
270         public static uint160 operator %(uint160 a, uint160 b)
271         {
272             if (b.bits <= 32)
273             {
274                 return a % b.Low32;
275             }
276
277             uint160 result = new uint160();
278
279             uint[] quotient;
280             uint[] remainder_value;
281
282             int m = a.bits / 32 + (a.bits % 32 != 0 ? 1 : 0);
283             int n = b.bits / 32 + (b.bits % 32 != 0 ? 1 : 0);
284
285             BignumHelper.DivModUnsigned(a.pn.Take(m).ToArray(), b.pn.Take(n).ToArray(), out quotient, out remainder_value);
286
287             remainder_value.CopyTo(result.pn, 0);
288
289             return result;
290
291         }
292
293         #endregion
294
295         #region Shift
296         public static uint160 operator <<(uint160 a, int shift)
297         {
298             var result = new uint160();
299             int k = shift / 32;
300             shift = shift % 32;
301
302             for (int i = 0; i < a.nWidth; i++)
303             {
304                 if (i + k + 1 < a.nWidth && shift != 0)
305                 {
306                     result.pn[i + k + 1] |= (a.pn[i] >> (32 - shift));
307                 }
308
309                 if (i + k < a.nWidth)
310                 {
311                     result.pn[i + k] |= (a.pn[i] << shift);
312                 }
313             }
314
315             return result;
316         }
317
318         public static uint160 operator >>(uint160 a, int shift)
319         {
320             var result = new uint160();
321             int k = shift / 32;
322             shift = shift % 32;
323
324             for (int i = 0; i < a.nWidth; i++)
325             {
326                 if (i - k - 1 >= 0 && shift != 0)
327                 {
328                     result.pn[i - k - 1] |= (a.pn[i] << (32 - shift));
329                 }
330
331                 if (i - k >= 0)
332                 {
333                     result.pn[i - k] |= (a.pn[i] >> shift);
334                 }
335             }
336
337             return result;
338         }
339         #endregion
340     }
341 }