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