Monero
int-util.h
Go to the documentation of this file.
1 // Copyright (c) 2014-2022, The Monero Project
2 //
3 // All rights reserved.
4 //
5 // Redistribution and use in source and binary forms, with or without modification, are
6 // permitted provided that the following conditions are met:
7 //
8 // 1. Redistributions of source code must retain the above copyright notice, this list of
9 // conditions and the following disclaimer.
10 //
11 // 2. Redistributions in binary form must reproduce the above copyright notice, this list
12 // of conditions and the following disclaimer in the documentation and/or other
13 // materials provided with the distribution.
14 //
15 // 3. Neither the name of the copyright holder nor the names of its contributors may be
16 // used to endorse or promote products derived from this software without specific
17 // prior written permission.
18 //
19 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
20 // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
21 // MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
22 // THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
24 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
25 // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
26 // STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
27 // THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 //
29 // Parts of this file are originally copyright (c) 2012-2013 The Cryptonote developers
30 
31 #pragma once
32 
33 #include <assert.h>
34 #include <stdbool.h>
35 #include <stdint.h>
36 #include <string.h>
37 
38 #ifndef _MSC_VER
39 #include <sys/param.h>
40 #endif
41 
42 #if defined(__ANDROID__)
43 #include <byteswap.h>
44 #endif
45 
46 #if defined(__sun) && defined(__SVR4)
47 #include <endian.h>
48 #endif
49 
50 #if defined(_MSC_VER)
51 #include <stdlib.h>
52 
53 static inline uint32_t rol32(uint32_t x, int r) {
54  static_assert(sizeof(uint32_t) == sizeof(unsigned int), "this code assumes 32-bit integers");
55  return _rotl(x, r);
56 }
57 
58 static inline uint64_t rol64(uint64_t x, int r) {
59  return _rotl64(x, r);
60 }
61 
62 #else
63 
64 static inline uint32_t rol32(uint32_t x, int r) {
65  return (x << (r & 31)) | (x >> (-r & 31));
66 }
67 
68 static inline uint64_t rol64(uint64_t x, int r) {
69  return (x << (r & 63)) | (x >> (-r & 63));
70 }
71 
72 #endif
73 
74 static inline uint64_t hi_dword(uint64_t val) {
75  return val >> 32;
76 }
77 
78 static inline uint64_t lo_dword(uint64_t val) {
79  return val & 0xFFFFFFFF;
80 }
81 
82 static inline uint64_t mul128(uint64_t multiplier, uint64_t multiplicand, uint64_t* product_hi) {
83  // multiplier = ab = a * 2^32 + b
84  // multiplicand = cd = c * 2^32 + d
85  // ab * cd = a * c * 2^64 + (a * d + b * c) * 2^32 + b * d
86  uint64_t a = hi_dword(multiplier);
87  uint64_t b = lo_dword(multiplier);
88  uint64_t c = hi_dword(multiplicand);
89  uint64_t d = lo_dword(multiplicand);
90 
91  uint64_t ac = a * c;
92  uint64_t ad = a * d;
93  uint64_t bc = b * c;
94  uint64_t bd = b * d;
95 
96  uint64_t adbc = ad + bc;
97  uint64_t adbc_carry = adbc < ad ? 1 : 0;
98 
99  // multiplier * multiplicand = product_hi * 2^64 + product_lo
100  uint64_t product_lo = bd + (adbc << 32);
101  uint64_t product_lo_carry = product_lo < bd ? 1 : 0;
102  *product_hi = ac + (adbc >> 32) + (adbc_carry << 32) + product_lo_carry;
103  assert(ac <= *product_hi);
104 
105  return product_lo;
106 }
107 
108 static inline uint64_t div_with_reminder(uint64_t dividend, uint32_t divisor, uint32_t* remainder) {
109  dividend |= ((uint64_t)*remainder) << 32;
110  *remainder = dividend % divisor;
111  return dividend / divisor;
112 }
113 
114 // Long division with 2^32 base
115 static inline uint32_t div128_32(uint64_t dividend_hi, uint64_t dividend_lo, uint32_t divisor, uint64_t* quotient_hi, uint64_t* quotient_lo) {
116  uint64_t dividend_dwords[4];
117  uint32_t remainder = 0;
118 
119  dividend_dwords[3] = hi_dword(dividend_hi);
120  dividend_dwords[2] = lo_dword(dividend_hi);
121  dividend_dwords[1] = hi_dword(dividend_lo);
122  dividend_dwords[0] = lo_dword(dividend_lo);
123 
124  *quotient_hi = div_with_reminder(dividend_dwords[3], divisor, &remainder) << 32;
125  *quotient_hi |= div_with_reminder(dividend_dwords[2], divisor, &remainder);
126  *quotient_lo = div_with_reminder(dividend_dwords[1], divisor, &remainder) << 32;
127  *quotient_lo |= div_with_reminder(dividend_dwords[0], divisor, &remainder);
128 
129  return remainder;
130 }
131 
132 // Long divisor with 2^64 base
133 void div128_64(uint64_t dividend_hi, uint64_t dividend_lo, uint64_t divisor, uint64_t* quotient_hi, uint64_t *quotient_lo, uint64_t *remainder_hi, uint64_t *remainder_lo);
134 
135 static inline void add64clamp(uint64_t *value, uint64_t add)
136 {
137  static const uint64_t maxval = (uint64_t)-1;
138  if (*value > maxval - add)
139  *value = maxval;
140  else
141  *value += add;
142 }
143 
144 static inline void sub64clamp(uint64_t *value, uint64_t sub)
145 {
146  if (*value < sub)
147  *value = 0;
148  else
149  *value -= sub;
150 }
151 
152 #define IDENT16(x) ((uint16_t) (x))
153 #define IDENT32(x) ((uint32_t) (x))
154 #define IDENT64(x) ((uint64_t) (x))
155 
156 #define SWAP16(x) ((((uint16_t) (x) & 0x00ff) << 8) | \
157  (((uint16_t) (x) & 0xff00) >> 8))
158 #define SWAP32(x) ((((uint32_t) (x) & 0x000000ff) << 24) | \
159  (((uint32_t) (x) & 0x0000ff00) << 8) | \
160  (((uint32_t) (x) & 0x00ff0000) >> 8) | \
161  (((uint32_t) (x) & 0xff000000) >> 24))
162 #define SWAP64(x) ((((uint64_t) (x) & 0x00000000000000ff) << 56) | \
163  (((uint64_t) (x) & 0x000000000000ff00) << 40) | \
164  (((uint64_t) (x) & 0x0000000000ff0000) << 24) | \
165  (((uint64_t) (x) & 0x00000000ff000000) << 8) | \
166  (((uint64_t) (x) & 0x000000ff00000000) >> 8) | \
167  (((uint64_t) (x) & 0x0000ff0000000000) >> 24) | \
168  (((uint64_t) (x) & 0x00ff000000000000) >> 40) | \
169  (((uint64_t) (x) & 0xff00000000000000) >> 56))
170 
171 static inline uint16_t ident16(uint16_t x) { return x; }
172 static inline uint32_t ident32(uint32_t x) { return x; }
173 static inline uint64_t ident64(uint64_t x) { return x; }
174 
175 #ifndef __OpenBSD__
176 # if defined(__ANDROID__) && defined(__swap16) && !defined(swap16)
177 # define swap16 __swap16
178 # elif !defined(swap16)
179 static inline uint16_t swap16(uint16_t x) {
180  return ((x & 0x00ff) << 8) | ((x & 0xff00) >> 8);
181 }
182 # endif
183 # if defined(__ANDROID__) && defined(__swap32) && !defined(swap32)
184 # define swap32 __swap32
185 # elif !defined(swap32)
186 static inline uint32_t swap32(uint32_t x) {
187  x = ((x & 0x00ff00ff) << 8) | ((x & 0xff00ff00) >> 8);
188  return (x << 16) | (x >> 16);
189 }
190 # endif
191 # if defined(__ANDROID__) && defined(__swap64) && !defined(swap64)
192 # define swap64 __swap64
193 # elif !defined(swap64)
194 static inline uint64_t swap64(uint64_t x) {
195  x = ((x & 0x00ff00ff00ff00ff) << 8) | ((x & 0xff00ff00ff00ff00) >> 8);
196  x = ((x & 0x0000ffff0000ffff) << 16) | ((x & 0xffff0000ffff0000) >> 16);
197  return (x << 32) | (x >> 32);
198 }
199 # endif
200 #endif /* __OpenBSD__ */
201 
202 #if defined(__GNUC__)
203 #define UNUSED __attribute__((unused))
204 #else
205 #define UNUSED
206 #endif
207 static inline void mem_inplace_ident(void *mem UNUSED, size_t n UNUSED) { }
208 #undef UNUSED
209 
210 static inline void mem_inplace_swap16(void *mem, size_t n) {
211  size_t i;
212  for (i = 0; i < n; i++) {
213  ((uint16_t *) mem)[i] = swap16(((const uint16_t *) mem)[i]);
214  }
215 }
216 static inline void mem_inplace_swap32(void *mem, size_t n) {
217  size_t i;
218  for (i = 0; i < n; i++) {
219  ((uint32_t *) mem)[i] = swap32(((const uint32_t *) mem)[i]);
220  }
221 }
222 static inline void mem_inplace_swap64(void *mem, size_t n) {
223  size_t i;
224  for (i = 0; i < n; i++) {
225  ((uint64_t *) mem)[i] = swap64(((const uint64_t *) mem)[i]);
226  }
227 }
228 
229 static inline void memcpy_ident16(void *dst, const void *src, size_t n) {
230  memcpy(dst, src, 2 * n);
231 }
232 static inline void memcpy_ident32(void *dst, const void *src, size_t n) {
233  memcpy(dst, src, 4 * n);
234 }
235 static inline void memcpy_ident64(void *dst, const void *src, size_t n) {
236  memcpy(dst, src, 8 * n);
237 }
238 
239 static inline void memcpy_swap16(void *dst, const void *src, size_t n) {
240  size_t i;
241  for (i = 0; i < n; i++) {
242  ((uint16_t *) dst)[i] = swap16(((const uint16_t *) src)[i]);
243  }
244 }
245 static inline void memcpy_swap32(void *dst, const void *src, size_t n) {
246  size_t i;
247  for (i = 0; i < n; i++) {
248  ((uint32_t *) dst)[i] = swap32(((const uint32_t *) src)[i]);
249  }
250 }
251 static inline void memcpy_swap64(void *dst, const void *src, size_t n) {
252  size_t i;
253  for (i = 0; i < n; i++) {
254  ((uint64_t *) dst)[i] = swap64(((const uint64_t *) src)[i]);
255  }
256 }
257 
258 #ifdef _MSC_VER
259 # define LITTLE_ENDIAN 1234
260 # define BIG_ENDIAN 4321
261 # define BYTE_ORDER LITTLE_ENDIAN
262 #endif
263 
264 #if !defined(BYTE_ORDER) || !defined(LITTLE_ENDIAN) || !defined(BIG_ENDIAN)
265 static_assert(false, "BYTE_ORDER is undefined. Perhaps, GNU extensions are not enabled");
266 #endif
267 
268 #if BYTE_ORDER == LITTLE_ENDIAN
269 #define SWAP16LE IDENT16
270 #define SWAP16BE SWAP16
271 #define swap16le ident16
272 #define swap16be swap16
273 #define mem_inplace_swap16le mem_inplace_ident
274 #define mem_inplace_swap16be mem_inplace_swap16
275 #define memcpy_swap16le memcpy_ident16
276 #define memcpy_swap16be memcpy_swap16
277 #define SWAP32LE IDENT32
278 #define SWAP32BE SWAP32
279 #define swap32le ident32
280 #define swap32be swap32
281 #define mem_inplace_swap32le mem_inplace_ident
282 #define mem_inplace_swap32be mem_inplace_swap32
283 #define memcpy_swap32le memcpy_ident32
284 #define memcpy_swap32be memcpy_swap32
285 #define SWAP64LE IDENT64
286 #define SWAP64BE SWAP64
287 #define swap64le ident64
288 #define swap64be swap64
289 #define mem_inplace_swap64le mem_inplace_ident
290 #define mem_inplace_swap64be mem_inplace_swap64
291 #define memcpy_swap64le memcpy_ident64
292 #define memcpy_swap64be memcpy_swap64
293 #endif
294 
295 #if BYTE_ORDER == BIG_ENDIAN
296 #define SWAP16BE IDENT16
297 #define SWAP16LE SWAP16
298 #define swap16be ident16
299 #define swap16le swap16
300 #define mem_inplace_swap16be mem_inplace_ident
301 #define mem_inplace_swap16le mem_inplace_swap16
302 #define memcpy_swap16be memcpy_ident16
303 #define memcpy_swap16le memcpy_swap16
304 #define SWAP32BE IDENT32
305 #define SWAP32LE SWAP32
306 #define swap32be ident32
307 #define swap32le swap32
308 #define mem_inplace_swap32be mem_inplace_ident
309 #define mem_inplace_swap32le mem_inplace_swap32
310 #define memcpy_swap32be memcpy_ident32
311 #define memcpy_swap32le memcpy_swap32
312 #define SWAP64BE IDENT64
313 #define SWAP64LE SWAP64
314 #define swap64be ident64
315 #define swap64le swap64
316 #define mem_inplace_swap64be mem_inplace_ident
317 #define mem_inplace_swap64le mem_inplace_swap64
318 #define memcpy_swap64be memcpy_ident64
319 #define memcpy_swap64le memcpy_swap64
320 #endif
static void mem_inplace_ident(void *mem UNUSED, size_t n UNUSED)
Definition: int-util.h:207
static void memcpy_ident32(void *dst, const void *src, size_t n)
Definition: int-util.h:232
int i
Definition: pymoduletest.py:23
static void sub64clamp(uint64_t *value, uint64_t sub)
Definition: int-util.h:144
static void memcpy_swap64(void *dst, const void *src, size_t n)
Definition: int-util.h:251
unsigned short uint16_t
Definition: stdint.h:125
static uint32_t div128_32(uint64_t dividend_hi, uint64_t dividend_lo, uint32_t divisor, uint64_t *quotient_hi, uint64_t *quotient_lo)
Definition: int-util.h:115
static void mem_inplace_swap64(void *mem, size_t n)
Definition: int-util.h:222
Definition: d.py:1
static void mem_inplace_swap16(void *mem, size_t n)
Definition: int-util.h:210
static void add(ge_p3 &p3, const ge_cached &other)
Definition: multiexp.cc:144
unsigned int uint32_t
Definition: stdint.h:126
static void memcpy_ident64(void *dst, const void *src, size_t n)
Definition: int-util.h:235
static uint16_t ident16(uint16_t x)
Definition: int-util.h:171
static uint32_t rol32(uint32_t x, int r)
Definition: int-util.h:64
static uint64_t swap64(uint64_t x)
Definition: int-util.h:194
static void add64clamp(uint64_t *value, uint64_t add)
Definition: int-util.h:135
unsigned __int64 uint64_t
Definition: stdint.h:136
static uint64_t div_with_reminder(uint64_t dividend, uint32_t divisor, uint32_t *remainder)
Definition: int-util.h:108
static void mem_inplace_swap32(void *mem, size_t n)
Definition: int-util.h:216
static uint64_t lo_dword(uint64_t val)
Definition: int-util.h:78
static uint32_t swap32(uint32_t x)
Definition: int-util.h:186
static void memcpy_swap16(void *dst, const void *src, size_t n)
Definition: int-util.h:239
void div128_64(uint64_t dividend_hi, uint64_t dividend_lo, uint64_t divisor, uint64_t *quotient_hi, uint64_t *quotient_lo, uint64_t *remainder_hi, uint64_t *remainder_lo)
Definition: int-util.cpp:31
static uint64_t hi_dword(uint64_t val)
Definition: int-util.h:74
static uint64_t ident64(uint64_t x)
Definition: int-util.h:173
static uint64_t rol64(uint64_t x, int r)
Definition: int-util.h:68
const GenericPointer< typename T::ValueType > T2 T::AllocatorType & a
Definition: pointer.h:1124
r
Definition: testupnpigd.py:61
static void memcpy_ident16(void *dst, const void *src, size_t n)
Definition: int-util.h:229
const GenericPointer< typename T::ValueType > T2 value
Definition: pointer.h:1225
void * memcpy(void *a, const void *b, size_t c)
Definition: glibc_compat.cpp:16
d
Definition: pymoduletest.py:79
#define UNUSED
Definition: int-util.h:205
static uint16_t swap16(uint16_t x)
Definition: int-util.h:179
static void memcpy_swap32(void *dst, const void *src, size_t n)
Definition: int-util.h:245
static uint32_t ident32(uint32_t x)
Definition: int-util.h:172
c
Definition: pymoduletest.py:79
static uint64_t mul128(uint64_t multiplier, uint64_t multiplicand, uint64_t *product_hi)
Definition: int-util.h:82
cryptonote::block b
Definition: block.cpp:40