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