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