Monero
Loading...
Searching...
No Matches
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
53static 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
58static inline uint64_t rol64(uint64_t x, int r) {
59 return _rotl64(x, r);
60}
61
62#else
63
64static inline uint32_t rol32(uint32_t x, int r) {
65 return (x << (r & 31)) | (x >> (-r & 31));
66}
67
68static inline uint64_t rol64(uint64_t x, int r) {
69 return (x << (r & 63)) | (x >> (-r & 63));
70}
71
72#endif
73
74static inline uint64_t hi_dword(uint64_t val) {
75 return val >> 32;
76}
77
78static inline uint64_t lo_dword(uint64_t val) {
79 return val & 0xFFFFFFFF;
80}
81
82static 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
108static 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
115static 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
133void 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
135static 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
144static 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
171static inline uint16_t ident16(uint16_t x) { return x; }
172static inline uint32_t ident32(uint32_t x) { return x; }
173static 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)
179static 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)
186static 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)
194static 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
207static inline void mem_inplace_ident(void *mem UNUSED, size_t n UNUSED) { }
208#undef UNUSED
209
210static 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}
216static 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}
222static 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
229static inline void memcpy_ident16(void *dst, const void *src, size_t n) {
230 memcpy(dst, src, 2 * n);
231}
232static inline void memcpy_ident32(void *dst, const void *src, size_t n) {
233 memcpy(dst, src, 4 * n);
234}
235static inline void memcpy_ident64(void *dst, const void *src, size_t n) {
236 memcpy(dst, src, 8 * n);
237}
238
239static 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}
245static 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}
251static 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)
265static_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
cryptonote::block b
Definition block.cpp:40
void * memcpy(void *a, const void *b, size_t c)
Definition glibc_compat.cpp:16
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 void memcpy_ident16(void *dst, const void *src, size_t n)
Definition int-util.h:229
static uint32_t swap32(uint32_t x)
Definition int-util.h:186
static void memcpy_swap32(void *dst, const void *src, size_t n)
Definition int-util.h:245
static void mem_inplace_swap16(void *mem, size_t n)
Definition int-util.h:210
static uint64_t ident64(uint64_t x)
Definition int-util.h:173
static void mem_inplace_swap64(void *mem, size_t n)
Definition int-util.h:222
static void memcpy_swap16(void *dst, const void *src, size_t n)
Definition int-util.h:239
static void memcpy_swap64(void *dst, const void *src, size_t n)
Definition int-util.h:251
static uint64_t swap64(uint64_t x)
Definition int-util.h:194
static uint32_t rol32(uint32_t x, int r)
Definition int-util.h:64
static uint64_t rol64(uint64_t x, int r)
Definition int-util.h:68
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 uint32_t ident32(uint32_t x)
Definition int-util.h:172
static void memcpy_ident32(void *dst, const void *src, size_t n)
Definition int-util.h:232
static uint16_t ident16(uint16_t x)
Definition int-util.h:171
static void sub64clamp(uint64_t *value, uint64_t sub)
Definition int-util.h:144
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 lo_dword(uint64_t val)
Definition int-util.h:78
static void add64clamp(uint64_t *value, uint64_t add)
Definition int-util.h:135
static void mem_inplace_ident(void *mem UNUSED, size_t n UNUSED)
Definition int-util.h:207
static uint64_t hi_dword(uint64_t val)
Definition int-util.h:74
static uint16_t swap16(uint16_t x)
Definition int-util.h:179
static void memcpy_ident64(void *dst, const void *src, size_t n)
Definition int-util.h:235
static uint64_t mul128(uint64_t multiplier, uint64_t multiplicand, uint64_t *product_hi)
Definition int-util.h:82
Definition d.py:1
int
Definition pymoduletest.py:17
const GenericPointer< typename T::ValueType > T2 value
Definition pointer.h:1225
const GenericPointer< typename T::ValueType > T2 T::AllocatorType & a
Definition pointer.h:1124
unsigned short uint16_t
Definition stdint.h:125
unsigned int uint32_t
Definition stdint.h:126
unsigned __int64 uint64_t
Definition stdint.h:136
#define UNUSED(expr)
Definition test-libusb-version.c:31