HACK: initialize base.nWidth to resolve comparison issues.
[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
8 namespace Novacoin
9 {
10     public class uint256 : base_uint
11     {
12         new public readonly int nWidth = 8;
13
14         public uint256()
15         {
16             base.nWidth = nWidth;
17             pn = new uint[nWidth];
18
19             for (int i = 0; i < nWidth; i++)
20             {
21                 pn[i] = 0;
22             }
23         }
24
25         public uint256(uint256 b)
26         {
27             base.nWidth = nWidth;
28             pn = new uint[nWidth];
29
30             for (int i = 0; i < nWidth; i++)
31             {
32                 pn[i] = b.pn[i];
33             }
34         }
35
36
37         public uint256(ulong n)
38         {
39             base.nWidth = nWidth;
40             pn = new uint[nWidth];
41
42             pn[0] = (uint)n;
43             pn[1] = (uint)(n >> 32);
44             for (int i = 2; i < nWidth; i++)
45             {
46                 pn[i] = 0;
47             }
48         }
49
50         public uint256(byte[] bytes)
51         {
52             Contract.Requires<ArgumentException>(bytes.Length == 32, "Incorrect array length");
53
54             base.nWidth = nWidth;
55             pn = Interop.ToUInt32Array(bytes);
56         }
57
58         public uint256(string hex)
59         {
60             Contract.Requires<ArgumentException>(hex.Length == 64, "Incorrect string");
61
62             base.nWidth = nWidth;
63             var bytes = Interop.ReverseBytes(Interop.HexToArray(hex));
64             pn = Interop.ToUInt32Array(bytes);
65         }
66
67
68         public static uint256 operator ~(uint256 a)
69         {
70             var ret = new uint256();
71             for (int i = 0; i < a.nWidth; i++)
72             {
73                 ret.pn[i] = ~a.pn[i];
74             }
75             return ret;
76         }
77
78         public static uint256 operator -(uint256 a)
79         {
80             var ret = new uint256();
81             for (int i = 0; i < a.nWidth; i++)
82             {
83                 ret.pn[i] = ~a.pn[i];
84             }
85             ret++;
86             return ret;
87         }
88
89
90         public static uint256 operator ++(uint256 a)
91         {
92             int i = 0;
93             while (++a.pn[i] == 0 && i < a.nWidth - 1)
94             {
95                 i++;
96             }
97             return a;
98         }
99
100         public static uint256 operator --(uint256 a)
101         {
102             int i = 0;
103             while (--a.pn[i] == uint.MaxValue && i < a.nWidth - 1)
104             {
105                 i++;
106             }
107             return a;
108         }
109
110         public static uint256 operator ^(uint256 a, uint256 b)
111         {
112             var result = new uint256();
113             result.pn = new uint[a.nWidth];
114             for (int i = 0; i < result.nWidth; i++)
115             {
116                 result.pn[i] = a.pn[i] ^ b.pn[i];
117             }
118             return result;
119         }
120
121         public static uint256 operator +(uint256 a, uint256 b)
122         {
123             var result = new uint256();
124             ulong carry = 0;
125             for (int i = 0; i < result.nWidth; i++)
126             {
127                 ulong n = carry + a.pn[i] + b.pn[i];
128                 result.pn[i] = (uint)(n & 0xffffffff);
129                 carry = n >> 32;
130             }
131             return result;
132         }
133
134         public static uint256 operator +(uint256 a, ulong b)
135         {
136             return a + new uint256(b);
137         }
138
139         public static uint256 operator -(uint256 a, uint256 b)
140         {
141             return a + (-b);
142         }
143
144         public static uint256 operator -(uint256 a, ulong b)
145         {
146             return a - new uint256(b);
147         }
148
149         public static uint256 operator &(uint256 a, uint256 b)
150         {
151             var result = new uint256();
152             result.pn = new uint[a.nWidth];
153             for (int i = 0; i < result.nWidth; i++)
154             {
155                 result.pn[i] = a.pn[i] & b.pn[i];
156             }
157             return result;
158         }
159
160         public static uint256 operator |(uint256 a, uint256 b)
161         {
162             var result = new uint256();
163             result.pn = new uint[a.nWidth];
164             for (int i = 0; i < result.nWidth; i++)
165             {
166                 result.pn[i] = a.pn[i] | b.pn[i];
167             }
168             return result;
169         }
170
171         public static uint256 operator <<(uint256 a, int shift)
172         {
173             var result = new uint256();
174             int k = shift / 32;
175             shift = shift % 32;
176
177             for (int i = 0; i < a.nWidth; i++)
178             {
179                 if (i + k + 1 < a.nWidth && shift != 0)
180                 {
181                     result.pn[i + k + 1] |= (a.pn[i] >> (32 - shift));
182                 }
183
184                 if (i + k < a.nWidth)
185                 {
186                     result.pn[i + k] |= (a.pn[i] << shift);
187                 }
188             }
189
190             return result;
191         }
192
193         public static uint256 operator >>(uint256 a, int shift)
194         {
195             var result = new uint256();
196             int k = shift / 32;
197             shift = shift % 32;
198
199             for (int i = 0; i < a.nWidth; i++)
200             {
201                 if (i - k - 1 >= 0 && shift != 0)
202                 {
203                     result.pn[i - k - 1] |= (a.pn[i] << (32 - shift));
204                 }
205
206                 if (i - k >= 0)
207                 {
208                     result.pn[i - k] |= (a.pn[i] >> shift);
209                 }
210             }
211
212             return result;
213         }
214     }
215 }