Bitcoin ABC 0.26.3
P2P Digital Currency
Loading...
Searching...
No Matches
arith_uint256.cpp
Go to the documentation of this file.
1// Copyright (c) 2009-2010 Satoshi Nakamoto
2// Copyright (c) 2009-2016 The Bitcoin Core developers
3// Distributed under the MIT software license, see the accompanying
4// file COPYING or http://www.opensource.org/licenses/mit-license.php.
5
6#include <arith_uint256.h>
7
8#include <crypto/common.h>
9#include <uint256.h>
10
11#include <cmath>
12
13template <unsigned int BITS>
14base_uint<BITS>::base_uint(const std::string &str) {
15 static_assert(BITS / 32 > 0 && BITS % 32 == 0,
16 "Template parameter BITS must be a positive multiple of 32.");
17
18 SetHex(str);
19}
20
21template <unsigned int BITS>
23 base_uint<BITS> a(*this);
24 for (int i = 0; i < WIDTH; i++) {
25 pn[i] = 0;
26 }
27 int k = shift / 32;
28 shift = shift % 32;
29 for (int i = 0; i < WIDTH; i++) {
30 if (i + k + 1 < WIDTH && shift != 0) {
31 pn[i + k + 1] |= (a.pn[i] >> (32 - shift));
32 }
33 if (i + k < WIDTH) {
34 pn[i + k] |= (a.pn[i] << shift);
35 }
36 }
37 return *this;
38}
39
40template <unsigned int BITS>
42 base_uint<BITS> a(*this);
43 for (int i = 0; i < WIDTH; i++) {
44 pn[i] = 0;
45 }
46 int k = shift / 32;
47 shift = shift % 32;
48 for (int i = 0; i < WIDTH; i++) {
49 if (i - k - 1 >= 0 && shift != 0) {
50 pn[i - k - 1] |= (a.pn[i] << (32 - shift));
51 }
52 if (i - k >= 0) {
53 pn[i - k] |= (a.pn[i] >> shift);
54 }
55 }
56 return *this;
57}
58
59template <unsigned int BITS>
61 uint64_t carry = 0;
62 for (int i = 0; i < WIDTH; i++) {
63 uint64_t n = carry + (uint64_t)b32 * pn[i];
64 pn[i] = n & 0xffffffff;
65 carry = n >> 32;
66 }
67 return *this;
69
70template <unsigned int BITS>
73 for (int j = 0; j < WIDTH; j++) {
74 uint64_t carry = 0;
75 for (int i = 0; i + j < WIDTH; i++) {
76 uint64_t n = carry + a.pn[i + j] + (uint64_t)pn[j] * b.pn[i];
77 a.pn[i + j] = n & 0xffffffff;
78 carry = n >> 32;
79 }
80 }
81 *this = a;
82 return *this;
83}
84
85template <unsigned int BITS>
87 // make a copy, so we can shift.
89 // make a copy, so we can subtract.
90 base_uint<BITS> num = *this;
91 // the quotient.
92 *this = 0;
93 int num_bits = num.bits();
94 int div_bits = div.bits();
95 if (div_bits == 0) {
96 throw uint_error("Division by zero");
97 }
98 // the result is certainly 0.
99 if (div_bits > num_bits) {
100 return *this;
101 }
102 int shift = num_bits - div_bits;
103 // shift so that div and num align.
104 div <<= shift;
105 while (shift >= 0) {
106 if (num >= div) {
107 num -= div;
108 // set a bit of the result.
109 pn[shift / 32] |= (1U << (shift & 31));
110 }
111 // shift back.
112 div >>= 1;
113 shift--;
114 }
115 // num now contains the remainder of the division.
116 return *this;
117}
118
119template <unsigned int BITS>
121 for (int i = WIDTH - 1; i >= 0; i--) {
122 if (pn[i] < b.pn[i]) {
123 return -1;
124 }
125 if (pn[i] > b.pn[i]) {
126 return 1;
127 }
128 }
129 return 0;
130}
132template <unsigned int BITS> bool base_uint<BITS>::EqualTo(uint64_t b) const {
133 for (int i = WIDTH - 1; i >= 2; i--) {
134 if (pn[i]) {
135 return false;
136 }
137 }
138 if (pn[1] != (b >> 32)) {
139 return false;
140 }
141 if (pn[0] != (b & 0xfffffffful)) {
142 return false;
143 }
144 return true;
145}
146
147template <unsigned int BITS> double base_uint<BITS>::getdouble() const {
148 double ret = 0.0;
149 double fact = 1.0;
150 for (int i = 0; i < WIDTH; i++) {
151 ret += fact * pn[i];
152 fact *= 4294967296.0;
153 }
154 return ret;
155}
156
157template <unsigned int BITS> std::string base_uint<BITS>::GetHex() const {
158 return ArithToUint256(*this).GetHex();
159}
160
161template <unsigned int BITS> void base_uint<BITS>::SetHex(const char *psz) {
162 *this = UintToArith256(uint256S(psz));
165template <unsigned int BITS>
166void base_uint<BITS>::SetHex(const std::string &str) {
167 SetHex(str.c_str());
168}
169
170template <unsigned int BITS> std::string base_uint<BITS>::ToString() const {
171 return (GetHex());
172}
173
174template <unsigned int BITS> unsigned int base_uint<BITS>::bits() const {
175 for (int pos = WIDTH - 1; pos >= 0; pos--) {
176 if (pn[pos]) {
177 for (int nbits = 31; nbits > 0; nbits--) {
178 if (pn[pos] & 1U << nbits) {
179 return 32 * pos + nbits + 1;
180 }
181 }
182 return 32 * pos + 1;
183 }
184 }
185 return 0;
186}
187
188// Explicit instantiations for base_uint<256>
189template base_uint<256>::base_uint(const std::string &);
190template base_uint<256> &base_uint<256>::operator<<=(unsigned int);
191template base_uint<256> &base_uint<256>::operator>>=(unsigned int);
195template int base_uint<256>::CompareTo(const base_uint<256> &) const;
196template bool base_uint<256>::EqualTo(uint64_t) const;
197template double base_uint<256>::getdouble() const;
198template std::string base_uint<256>::GetHex() const;
199template std::string base_uint<256>::ToString() const;
200template void base_uint<256>::SetHex(const char *);
201template void base_uint<256>::SetHex(const std::string &);
202template unsigned int base_uint<256>::bits() const;
203
204// This implementation directly uses shifts instead of going through an
205// intermediate MPI representation.
207 bool *pfOverflow) {
208 int nSize = nCompact >> 24;
209 uint32_t nWord = nCompact & 0x007fffff;
210 if (nSize <= 3) {
211 nWord >>= 8 * (3 - nSize);
212 *this = nWord;
213 } else {
214 *this = nWord;
215 *this <<= 8 * (nSize - 3);
216 }
217 if (pfNegative) {
218 *pfNegative = nWord != 0 && (nCompact & 0x00800000) != 0;
219 }
220 if (pfOverflow) {
221 *pfOverflow =
222 nWord != 0 && ((nSize > 34) || (nWord > 0xff && nSize > 33) ||
223 (nWord > 0xffff && nSize > 32));
224 }
225 return *this;
226}
227
229 int nSize = (bits() + 7) / 8;
230 uint32_t nCompact = 0;
231 if (nSize <= 3) {
232 nCompact = GetLow64() << 8 * (3 - nSize);
233 } else {
234 arith_uint256 bn = *this >> 8 * (nSize - 3);
235 nCompact = bn.GetLow64();
236 }
237 // The 0x00800000 bit denotes the sign.
238 // Thus, if it is already set, divide the mantissa by 256 and increase the
239 // exponent.
240 if (nCompact & 0x00800000) {
241 nCompact >>= 8;
242 nSize++;
243 }
244 assert((nCompact & ~0x007fffffU) == 0);
245 assert(nSize < 256);
246 nCompact |= nSize << 24;
247 nCompact |= (fNegative && (nCompact & 0x007fffff) ? 0x00800000 : 0);
248 return nCompact;
249}
250
253 for (int i = b.WIDTH - 1; i >= 0; i--) {
254 const double fact = std::pow(4294967296.0, i);
255 b.pn[i] = uint32_t(d / fact);
256 d -= fact * b.pn[i];
257 }
258 return b;
259}
260
262 uint256 b;
263 for (int x = 0; x < a.WIDTH; ++x) {
264 WriteLE32(b.begin() + x * 4, a.pn[x]);
266 return b;
270 for (int x = 0; x < b.WIDTH; ++x) {
271 b.pn[x] = ReadLE32(a.begin() + x * 4);
272 }
273 return b;
274}
arith_uint256 UintToArith256(const uint256 &a)
uint256 ArithToUint256(const arith_uint256 &a)
256-bit unsigned big integer.
arith_uint256 & SetCompact(uint32_t nCompact, bool *pfNegative=nullptr, bool *pfOverflow=nullptr)
The "compact" format is a representation of a whole number N using an unsigned 32bit number similar t...
uint32_t GetCompact(bool fNegative=false) const
static arith_uint256 fromDouble(double d)
std::string GetHex() const
Definition uint256.cpp:16
Template base class for unsigned big integers.
uint32_t pn[WIDTH]
int CompareTo(const base_uint &b) const
base_uint & operator>>=(unsigned int shift)
base_uint & operator*=(uint32_t b32)
bool EqualTo(uint64_t b) const
double getdouble() const
base_uint & operator<<=(unsigned int shift)
std::string ToString() const
base_uint & operator/=(const base_uint &b)
uint64_t GetLow64() const
void SetHex(const char *psz)
std::string GetHex() const
unsigned int bits() const
Returns the position of the highest bit set plus one, or zero if the value is zero.
256-bit opaque blob.
Definition uint256.h:129
static void WriteLE32(uint8_t *ptr, uint32_t x)
Definition common.h:40
static uint32_t ReadLE32(const uint8_t *ptr)
Definition common.h:23
T GetRand(T nMax=std::numeric_limits< T >::max()) noexcept
Generate a uniform random integer of type T in the range [0..nMax) nMax defaults to std::numeric_limi...
Definition random.h:85
uint256 uint256S(const char *str)
uint256 from const char *.
Definition uint256.h:143
assert(!tx.IsCoinBase())