Remove Hash, Hash256, Hash160 and ScryptHash256 classes.
[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
22 namespace Novacoin
23 {
24     public class uint160 : base_uint
25     {
26         #region Access to internal representation
27         new protected int nWidth
28         {
29             get { return base.nWidth; }
30             private set { base.nWidth = value; }
31         }
32         new protected uint[] pn
33         {
34             get { return base.pn; }
35             private set { base.pn = value; }
36         }
37         #endregion
38
39         #region Constructors
40         public uint160()
41         {
42             nWidth = 5;
43             pn = new uint[nWidth];
44         }
45
46         public uint160(uint160 b) : this()
47         {
48             for (int i = 0; i < nWidth; i++)
49             {
50                 pn[i] = b.pn[i];
51             }
52         }
53
54
55         public uint160(ulong n) : this()
56         {
57             pn[0] = (uint)n;
58             pn[1] = (uint)(n >> 32);
59             for (int i = 2; i < nWidth; i++)
60             {
61                 pn[i] = 0;
62             }
63         }
64
65         public uint160(byte[] bytes) : this()
66         {
67             Contract.Requires<ArgumentException>(bytes.Length == 20, "Incorrect array length");
68             pn = Interop.ToUInt32Array(bytes);
69         }
70
71         public uint160(string hex) : this()
72         {
73             Contract.Requires<ArgumentException>(hex.Length == 40, "Incorrect string");
74             var bytes = Interop.ReverseBytes(Interop.HexToArray(hex));
75             pn = Interop.ToUInt32Array(bytes);
76         }
77         #endregion
78
79         #region Cast operators
80         public static implicit operator uint160(byte[] bytes)
81         {
82             return new uint160(bytes);
83         }
84
85         public static implicit operator uint160(ulong n)
86         {
87             return new uint160(n);
88         }
89         #endregion
90
91         #region Bitwise operations
92         public static uint160 operator ~(uint160 a)
93         {
94             var ret = new uint160();
95             for (int i = 0; i < a.nWidth; i++)
96             {
97                 ret.pn[i] = ~a.pn[i];
98             }
99             return ret;
100         }
101
102         public static uint160 operator ^(uint160 a, uint160 b)
103         {
104             var result = new uint160();
105             result.pn = new uint[a.nWidth];
106             for (int i = 0; i < result.nWidth; i++)
107             {
108                 result.pn[i] = a.pn[i] ^ b.pn[i];
109             }
110             return result;
111         }
112
113         public static uint160 operator &(uint160 a, uint160 b)
114         {
115             var result = new uint160();
116             result.pn = new uint[a.nWidth];
117             for (int i = 0; i < result.nWidth; i++)
118             {
119                 result.pn[i] = a.pn[i] & b.pn[i];
120             }
121             return result;
122         }
123
124         public static uint160 operator |(uint160 a, uint160 b)
125         {
126             var result = new uint160();
127             result.pn = new uint[a.nWidth];
128             for (int i = 0; i < result.nWidth; i++)
129             {
130                 result.pn[i] = a.pn[i] | b.pn[i];
131             }
132             return result;
133         }
134         #endregion
135
136         #region Basic arithmetics
137         public static uint160 operator +(uint160 a, uint160 b)
138         {
139             var result = new uint160();
140             ulong carry = 0;
141             for (int i = 0; i < result.nWidth; i++)
142             {
143                 ulong n = carry + a.pn[i] + b.pn[i];
144                 result.pn[i] = (uint)(n & 0xffffffff);
145                 carry = n >> 32;
146             }
147             return result;
148         }
149
150         public static uint160 operator +(uint160 a, ulong b)
151         {
152             return a + new uint160(b);
153         }
154
155         public static uint160 operator -(uint160 a, uint160 b)
156         {
157             return a + (-b);
158         }
159
160         public static uint160 operator -(uint160 a, ulong b)
161         {
162             return a - new uint160(b);
163         }
164
165         public static uint160 operator -(uint160 a)
166         {
167             var ret = new uint160();
168             for (int i = 0; i < a.nWidth; i++)
169             {
170                 ret.pn[i] = ~a.pn[i];
171             }
172             ret++;
173             return ret;
174         }
175
176
177         public static uint160 operator ++(uint160 a)
178         {
179             int i = 0;
180             while (++a.pn[i] == 0 && i < a.nWidth - 1)
181             {
182                 i++;
183             }
184             return a;
185         }
186
187         public static uint160 operator --(uint160 a)
188         {
189             int i = 0;
190             while (--a.pn[i] == uint.MaxValue && i < a.nWidth - 1)
191             {
192                 i++;
193             }
194             return a;
195         }
196
197         #endregion
198
199         #region Shift
200         public static uint160 operator <<(uint160 a, int shift)
201         {
202             var result = new uint160();
203             int k = shift / 32;
204             shift = shift % 32;
205
206             for (int i = 0; i < a.nWidth; i++)
207             {
208                 if (i + k + 1 < a.nWidth && shift != 0)
209                 {
210                     result.pn[i + k + 1] |= (a.pn[i] >> (32 - shift));
211                 }
212
213                 if (i + k < a.nWidth)
214                 {
215                     result.pn[i + k] |= (a.pn[i] << shift);
216                 }
217             }
218
219             return result;
220         }
221
222         public static uint160 operator >>(uint160 a, int shift)
223         {
224             var result = new uint160();
225             int k = shift / 32;
226             shift = shift % 32;
227
228             for (int i = 0; i < a.nWidth; i++)
229             {
230                 if (i - k - 1 >= 0 && shift != 0)
231                 {
232                     result.pn[i - k - 1] |= (a.pn[i] << (32 - shift));
233                 }
234
235                 if (i - k >= 0)
236                 {
237                     result.pn[i - k] |= (a.pn[i] >> shift);
238                 }
239             }
240
241             return result;
242         }
243         #endregion
244     }
245 }