VirtualBox

source: vbox/trunk/include/iprt/uint256.h@ 104212

Last change on this file since 104212 was 98103, checked in by vboxsync, 23 months ago

Copyright year updates by scm.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 37.7 KB
Line 
1/** @file
2 * IPRT - RTUINT256U methods.
3 */
4
5/*
6 * Copyright (C) 2011-2023 Oracle and/or its affiliates.
7 *
8 * This file is part of VirtualBox base platform packages, as
9 * available from https://www.virtualbox.org.
10 *
11 * This program is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU General Public License
13 * as published by the Free Software Foundation, in version 3 of the
14 * License.
15 *
16 * This program is distributed in the hope that it will be useful, but
17 * WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 * General Public License for more details.
20 *
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, see <https://www.gnu.org/licenses>.
23 *
24 * The contents of this file may alternatively be used under the terms
25 * of the Common Development and Distribution License Version 1.0
26 * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
27 * in the VirtualBox distribution, in which case the provisions of the
28 * CDDL are applicable instead of those of the GPL.
29 *
30 * You may elect to license modified versions of this file under the
31 * terms and conditions of either the GPL or the CDDL or both.
32 *
33 * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
34 */
35
36#ifndef IPRT_INCLUDED_uint256_h
37#define IPRT_INCLUDED_uint256_h
38#ifndef RT_WITHOUT_PRAGMA_ONCE
39# pragma once
40#endif
41
42#include <iprt/cdefs.h>
43#include <iprt/types.h>
44#include <iprt/asm.h>
45#include <iprt/asm-math.h>
46
47RT_C_DECLS_BEGIN
48
49/** @defgroup grp_rt_uint256 RTUInt256 - 256-bit Unsigned Integer Methods
50 * @ingroup grp_rt
51 * @{
52 */
53
54
55/**
56 * Test if a 256-bit unsigned integer value is zero.
57 *
58 * @returns true if they are, false if they aren't.
59 * @param pValue The input and output value.
60 */
61DECLINLINE(bool) RTUInt256IsZero(PCRTUINT256U pValue)
62{
63#if ARCH_BITS >= 64
64 return pValue->QWords.qw0 == 0
65 && pValue->QWords.qw1 == 0
66 && pValue->QWords.qw2 == 0
67 && pValue->QWords.qw3 == 0;
68#else
69 return pValue->DWords.dw0 == 0
70 && pValue->DWords.dw1 == 0
71 && pValue->DWords.dw2 == 0
72 && pValue->DWords.dw3 == 0
73 && pValue->DWords.dw4 == 0
74 && pValue->DWords.dw5 == 0
75 && pValue->DWords.dw6 == 0
76 && pValue->DWords.dw7 == 0;
77#endif
78}
79
80
81/**
82 * Set a 256-bit unsigned integer value to zero.
83 *
84 * @returns pResult
85 * @param pResult The result variable.
86 */
87DECLINLINE(PRTUINT256U) RTUInt256SetZero(PRTUINT256U pResult)
88{
89#if ARCH_BITS >= 64
90 pResult->QWords.qw0 = 0;
91 pResult->QWords.qw1 = 0;
92 pResult->QWords.qw2 = 0;
93 pResult->QWords.qw3 = 0;
94#else
95 pResult->DWords.dw0 = 0;
96 pResult->DWords.dw1 = 0;
97 pResult->DWords.dw2 = 0;
98 pResult->DWords.dw3 = 0;
99 pResult->DWords.dw4 = 0;
100 pResult->DWords.dw5 = 0;
101 pResult->DWords.dw6 = 0;
102 pResult->DWords.dw7 = 0;
103#endif
104 return pResult;
105}
106
107
108/**
109 * Set a 256-bit unsigned integer value to the maximum value.
110 *
111 * @returns pResult
112 * @param pResult The result variable.
113 */
114DECLINLINE(PRTUINT256U) RTUInt256SetMax(PRTUINT256U pResult)
115{
116#if ARCH_BITS >= 64
117 pResult->QWords.qw0 = UINT64_MAX;
118 pResult->QWords.qw1 = UINT64_MAX;
119 pResult->QWords.qw2 = UINT64_MAX;
120 pResult->QWords.qw3 = UINT64_MAX;
121#else
122 pResult->DWords.dw0 = UINT32_MAX;
123 pResult->DWords.dw1 = UINT32_MAX;
124 pResult->DWords.dw2 = UINT32_MAX;
125 pResult->DWords.dw3 = UINT32_MAX;
126 pResult->DWords.dw4 = UINT32_MAX;
127 pResult->DWords.dw5 = UINT32_MAX;
128 pResult->DWords.dw6 = UINT32_MAX;
129 pResult->DWords.dw7 = UINT32_MAX;
130#endif
131 return pResult;
132}
133
134
135
136
137/**
138 * Adds two 256-bit unsigned integer values.
139 *
140 * @returns pResult
141 * @param pResult The result variable.
142 * @param pValue1 The first value.
143 * @param pValue2 The second value.
144 */
145DECLINLINE(PRTUINT256U) RTUInt256Add(PRTUINT256U pResult, PCRTUINT256U pValue1, PCRTUINT256U pValue2)
146{
147 unsigned uCarry;
148 pResult->QWords.qw0 = pValue1->QWords.qw0 + pValue2->QWords.qw0;
149 uCarry = pResult->QWords.qw0 < pValue1->QWords.qw0;
150
151 pResult->QWords.qw1 = pValue1->QWords.qw1 + pValue2->QWords.qw1 + uCarry;
152 uCarry = uCarry ? pResult->QWords.qw1 <= pValue1->QWords.qw1 : pResult->QWords.qw1 < pValue1->QWords.qw1;
153
154 pResult->QWords.qw2 = pValue1->QWords.qw2 + pValue2->QWords.qw2 + uCarry;
155 uCarry = uCarry ? pResult->QWords.qw2 <= pValue1->QWords.qw2 : pResult->QWords.qw2 < pValue1->QWords.qw2;
156
157 pResult->QWords.qw3 = pValue1->QWords.qw3 + pValue2->QWords.qw3 + uCarry;
158 return pResult;
159}
160
161
162/**
163 * Adds a 256-bit and a 64-bit unsigned integer values.
164 *
165 * @returns pResult
166 * @param pResult The result variable.
167 * @param pValue1 The first value.
168 * @param uValue2 The second value, 64-bit.
169 */
170DECLINLINE(PRTUINT256U) RTUInt256AddU64(PRTUINT256U pResult, PCRTUINT256U pValue1, uint64_t uValue2)
171{
172 pResult->QWords.qw3 = pValue1->QWords.qw3;
173 pResult->QWords.qw2 = pValue1->QWords.qw2;
174 pResult->QWords.qw1 = pValue1->QWords.qw1;
175 pResult->QWords.qw0 = pValue1->QWords.qw0 + uValue2;
176 if (pResult->QWords.qw0 < uValue2)
177 if (pResult->QWords.qw1++ == UINT64_MAX)
178 if (pResult->QWords.qw2++ == UINT64_MAX)
179 pResult->QWords.qw3++;
180 return pResult;
181}
182
183
184/**
185 * Subtracts a 256-bit unsigned integer value from another.
186 *
187 * @returns pResult
188 * @param pResult The result variable.
189 * @param pValue1 The minuend value.
190 * @param pValue2 The subtrahend value.
191 */
192DECLINLINE(PRTUINT256U) RTUInt256Sub(PRTUINT256U pResult, PCRTUINT256U pValue1, PCRTUINT256U pValue2)
193{
194 unsigned uBorrow;
195 pResult->QWords.qw0 = pValue1->QWords.qw0 - pValue2->QWords.qw0;
196 uBorrow = pResult->QWords.qw0 > pValue1->QWords.qw0;
197
198 pResult->QWords.qw1 = pValue1->QWords.qw1 - pValue2->QWords.qw1 - uBorrow;
199 uBorrow = uBorrow ? pResult->QWords.qw1 >= pValue1->QWords.qw1 : pResult->QWords.qw1 > pValue1->QWords.qw1;
200
201 pResult->QWords.qw2 = pValue1->QWords.qw2 - pValue2->QWords.qw2 - uBorrow;
202 uBorrow = uBorrow ? pResult->QWords.qw2 >= pValue1->QWords.qw2 : pResult->QWords.qw2 > pValue1->QWords.qw2;
203
204 pResult->QWords.qw3 = pValue1->QWords.qw3 - pValue2->QWords.qw3 - uBorrow;
205 return pResult;
206}
207
208
209/**
210 * Multiplies two 256-bit unsigned integer values.
211 *
212 * @returns pResult
213 * @param pResult The result variable.
214 * @param pValue1 The first value.
215 * @param pValue2 The second value.
216 */
217RTDECL(PRTUINT256U) RTUInt256Mul(PRTUINT256U pResult, PCRTUINT256U pValue1, PCRTUINT256U pValue2);
218
219/**
220 * Multiplies an 256-bit unsigned integer by a 64-bit unsigned integer value.
221 *
222 * @returns pResult
223 * @param pResult The result variable.
224 * @param pValue1 The first value.
225 * @param uValue2 The second value, 64-bit.
226 */
227RTDECL(PRTUINT256U) RTUInt256MulByU64(PRTUINT256U pResult, PCRTUINT256U pValue1, uint64_t uValue2);
228
229/**
230 * Divides a 256-bit unsigned integer value by another, returning both quotient
231 * and remainder.
232 *
233 * @returns pQuotient, NULL if pValue2 is 0.
234 * @param pQuotient Where to return the quotient.
235 * @param pRemainder Where to return the remainder.
236 * @param pValue1 The dividend value.
237 * @param pValue2 The divisor value.
238 */
239RTDECL(PRTUINT256U) RTUInt256DivRem(PRTUINT256U pQuotient, PRTUINT256U pRemainder, PCRTUINT256U pValue1, PCRTUINT256U pValue2);
240
241/**
242 * Divides a 256-bit unsigned integer value by another.
243 *
244 * @returns pResult
245 * @param pResult The result variable.
246 * @param pValue1 The dividend value.
247 * @param pValue2 The divisor value.
248 */
249DECLINLINE(PRTUINT256U) RTUInt256Div(PRTUINT256U pResult, PCRTUINT256U pValue1, PCRTUINT256U pValue2)
250{
251 RTUINT256U Ignored;
252 return RTUInt256DivRem(pResult, &Ignored, pValue1, pValue2);
253}
254
255
256/**
257 * Divides a 256-bit unsigned integer value by another, returning the remainder.
258 *
259 * @returns pResult
260 * @param pResult The result variable (remainder).
261 * @param pValue1 The dividend value.
262 * @param pValue2 The divisor value.
263 */
264DECLINLINE(PRTUINT256U) RTUInt256Mod(PRTUINT256U pResult, PCRTUINT256U pValue1, PCRTUINT256U pValue2)
265{
266 RTUINT256U Ignored;
267 RTUInt256DivRem(&Ignored, pResult, pValue1, pValue2);
268 return pResult;
269}
270
271
272/**
273 * Bitwise AND of two 256-bit unsigned integer values.
274 *
275 * @returns pResult
276 * @param pResult The result variable.
277 * @param pValue1 The first value.
278 * @param pValue2 The second value.
279 */
280DECLINLINE(PRTUINT256U) RTUInt256And(PRTUINT256U pResult, PCRTUINT256U pValue1, PCRTUINT256U pValue2)
281{
282 pResult->QWords.qw0 = pValue1->QWords.qw0 & pValue2->QWords.qw0;
283 pResult->QWords.qw1 = pValue1->QWords.qw1 & pValue2->QWords.qw1;
284 pResult->QWords.qw2 = pValue1->QWords.qw2 & pValue2->QWords.qw2;
285 pResult->QWords.qw3 = pValue1->QWords.qw3 & pValue2->QWords.qw3;
286 return pResult;
287}
288
289
290/**
291 * Bitwise OR of two 256-bit unsigned integer values.
292 *
293 * @returns pResult
294 * @param pResult The result variable.
295 * @param pValue1 The first value.
296 * @param pValue2 The second value.
297 */
298DECLINLINE(PRTUINT256U) RTUInt256Or( PRTUINT256U pResult, PCRTUINT256U pValue1, PCRTUINT256U pValue2)
299{
300 pResult->QWords.qw0 = pValue1->QWords.qw0 | pValue2->QWords.qw0;
301 pResult->QWords.qw1 = pValue1->QWords.qw1 | pValue2->QWords.qw1;
302 pResult->QWords.qw2 = pValue1->QWords.qw2 | pValue2->QWords.qw2;
303 pResult->QWords.qw3 = pValue1->QWords.qw3 | pValue2->QWords.qw3;
304 return pResult;
305}
306
307
308/**
309 * Bitwise XOR of two 256-bit unsigned integer values.
310 *
311 * @returns pResult
312 * @param pResult The result variable.
313 * @param pValue1 The first value.
314 * @param pValue2 The second value.
315 */
316DECLINLINE(PRTUINT256U) RTUInt256Xor(PRTUINT256U pResult, PCRTUINT256U pValue1, PCRTUINT256U pValue2)
317{
318 pResult->QWords.qw0 = pValue1->QWords.qw0 ^ pValue2->QWords.qw0;
319 pResult->QWords.qw1 = pValue1->QWords.qw1 ^ pValue2->QWords.qw1;
320 pResult->QWords.qw2 = pValue1->QWords.qw2 ^ pValue2->QWords.qw2;
321 pResult->QWords.qw3 = pValue1->QWords.qw3 ^ pValue2->QWords.qw3;
322 return pResult;
323}
324
325
326/**
327 * Shifts a 256-bit unsigned integer value @a cBits to the left.
328 *
329 * @returns pResult
330 * @param pResult The result variable.
331 * @param pValue The value to shift.
332 * @param cBits The number of bits to shift it. This is masked
333 * by 255 before shifting.
334 */
335DECLINLINE(PRTUINT256U) RTUInt256ShiftLeft(PRTUINT256U pResult, PCRTUINT256U pValue, unsigned cBits)
336{
337 /* This is a bit bulky & impractical since we cannot access the data using
338 an array because it is organized according to host endianness. Sigh. */
339 cBits &= 255;
340 if (!(cBits & 0x3f))
341 {
342 if (cBits == 0)
343 *pResult = *pValue;
344 else
345 {
346 pResult->QWords.qw0 = 0;
347 if (cBits == 64)
348 {
349 pResult->QWords.qw1 = pValue->QWords.qw0;
350 pResult->QWords.qw2 = pValue->QWords.qw1;
351 pResult->QWords.qw3 = pValue->QWords.qw2;
352 }
353 else
354 {
355 pResult->QWords.qw1 = 0;
356 if (cBits == 128)
357 {
358 pResult->QWords.qw2 = pValue->QWords.qw0;
359 pResult->QWords.qw3 = pValue->QWords.qw1;
360 }
361 else
362 {
363 pResult->QWords.qw2 = 0;
364 pResult->QWords.qw3 = pValue->QWords.qw0;
365 }
366 }
367 }
368 }
369 else if (cBits < 128)
370 {
371 if (cBits < 64)
372 {
373 pResult->QWords.qw0 = pValue->QWords.qw0 << cBits;
374 pResult->QWords.qw1 = pValue->QWords.qw0 >> (64 - cBits);
375 pResult->QWords.qw1 |= pValue->QWords.qw1 << cBits;
376 pResult->QWords.qw2 = pValue->QWords.qw1 >> (64 - cBits);
377 pResult->QWords.qw2 |= pValue->QWords.qw2 << cBits;
378 pResult->QWords.qw3 = pValue->QWords.qw2 >> (64 - cBits);
379 pResult->QWords.qw3 |= pValue->QWords.qw3 << cBits;
380 }
381 else
382 {
383 cBits -= 64;
384 pResult->QWords.qw0 = 0;
385 pResult->QWords.qw1 = pValue->QWords.qw0 << cBits;
386 pResult->QWords.qw2 = pValue->QWords.qw0 >> (64 - cBits);
387 pResult->QWords.qw2 |= pValue->QWords.qw1 << cBits;
388 pResult->QWords.qw3 = pValue->QWords.qw1 >> (64 - cBits);
389 pResult->QWords.qw3 |= pValue->QWords.qw2 << cBits;
390 }
391 }
392 else
393 {
394 if (cBits < 192)
395 {
396 cBits -= 128;
397 pResult->QWords.qw0 = 0;
398 pResult->QWords.qw1 = 0;
399 pResult->QWords.qw2 = pValue->QWords.qw0 << cBits;
400 pResult->QWords.qw3 = pValue->QWords.qw0 >> (64 - cBits);
401 pResult->QWords.qw3 |= pValue->QWords.qw1 << cBits;
402 }
403 else
404 {
405 cBits -= 192;
406 pResult->QWords.qw0 = 0;
407 pResult->QWords.qw1 = 0;
408 pResult->QWords.qw2 = 0;
409 pResult->QWords.qw3 = pValue->QWords.qw0 << cBits;
410 }
411 }
412 return pResult;
413}
414
415
416/**
417 * Shifts a 256-bit unsigned integer value @a cBits to the right.
418 *
419 * @returns pResult
420 * @param pResult The result variable.
421 * @param pValue The value to shift.
422 * @param cBits The number of bits to shift it. This is masked
423 * by 255 before shifting.
424 */
425DECLINLINE(PRTUINT256U) RTUInt256ShiftRight(PRTUINT256U pResult, PCRTUINT256U pValue, unsigned cBits)
426{
427 /* This is a bit bulky & impractical since we cannot access the data using
428 an array because it is organized according to host endianness. Sigh. */
429 cBits &= 255;
430 if (!(cBits & 0x3f))
431 {
432 if (cBits == 0)
433 *pResult = *pValue;
434 else
435 {
436 if (cBits == 64)
437 {
438 pResult->QWords.qw0 = pValue->QWords.qw1;
439 pResult->QWords.qw1 = pValue->QWords.qw2;
440 pResult->QWords.qw2 = pValue->QWords.qw3;
441 }
442 else
443 {
444 if (cBits == 128)
445 {
446 pResult->QWords.qw0 = pValue->QWords.qw2;
447 pResult->QWords.qw1 = pValue->QWords.qw3;
448 }
449 else
450 {
451 pResult->QWords.qw0 = pValue->QWords.qw3;
452 pResult->QWords.qw1 = 0;
453 }
454 pResult->QWords.qw2 = 0;
455 }
456 pResult->QWords.qw3 = 0;
457 }
458 }
459 else if (cBits < 128)
460 {
461 if (cBits < 64)
462 {
463 pResult->QWords.qw0 = pValue->QWords.qw0 >> cBits;
464 pResult->QWords.qw0 |= pValue->QWords.qw1 << (64 - cBits);
465 pResult->QWords.qw1 = pValue->QWords.qw1 >> cBits;
466 pResult->QWords.qw1 |= pValue->QWords.qw2 << (64 - cBits);
467 pResult->QWords.qw2 = pValue->QWords.qw2 >> cBits;
468 pResult->QWords.qw2 |= pValue->QWords.qw3 << (64 - cBits);
469 pResult->QWords.qw3 = pValue->QWords.qw3 >> cBits;
470 }
471 else
472 {
473 cBits -= 64;
474 pResult->QWords.qw0 = pValue->QWords.qw1 >> cBits;
475 pResult->QWords.qw0 |= pValue->QWords.qw2 << (64 - cBits);
476 pResult->QWords.qw1 = pValue->QWords.qw2 >> cBits;
477 pResult->QWords.qw1 |= pValue->QWords.qw3 << (64 - cBits);
478 pResult->QWords.qw2 = pValue->QWords.qw3 >> cBits;
479 pResult->QWords.qw3 = 0;
480 }
481 }
482 else
483 {
484 if (cBits < 192)
485 {
486 cBits -= 128;
487 pResult->QWords.qw0 = pValue->QWords.qw2 >> cBits;
488 pResult->QWords.qw0 |= pValue->QWords.qw3 << (64 - cBits);
489 pResult->QWords.qw1 = pValue->QWords.qw3 >> cBits;
490 pResult->QWords.qw2 = 0;
491 pResult->QWords.qw3 = 0;
492 }
493 else
494 {
495 cBits -= 192;
496 pResult->QWords.qw0 = pValue->QWords.qw3 >> cBits;
497 pResult->QWords.qw1 = 0;
498 pResult->QWords.qw2 = 0;
499 pResult->QWords.qw3 = 0;
500 }
501 }
502 return pResult;
503}
504
505
506/**
507 * Boolean not (result 0 or 1).
508 *
509 * @returns pResult.
510 * @param pResult The result variable.
511 * @param pValue The value.
512 */
513DECLINLINE(PRTUINT256U) RTUInt256BooleanNot(PRTUINT256U pResult, PCRTUINT256U pValue)
514{
515 pResult->QWords.qw0 = RTUInt256IsZero(pValue);
516 pResult->QWords.qw1 = 0;
517 pResult->QWords.qw2 = 0;
518 pResult->QWords.qw3 = 0;
519 return pResult;
520}
521
522
523/**
524 * Bitwise not (flips each bit of the 256 bits).
525 *
526 * @returns pResult.
527 * @param pResult The result variable.
528 * @param pValue The value.
529 */
530DECLINLINE(PRTUINT256U) RTUInt256BitwiseNot(PRTUINT256U pResult, PCRTUINT256U pValue)
531{
532 pResult->QWords.qw0 = ~pValue->QWords.qw0;
533 pResult->QWords.qw1 = ~pValue->QWords.qw1;
534 pResult->QWords.qw2 = ~pValue->QWords.qw2;
535 pResult->QWords.qw3 = ~pValue->QWords.qw3;
536 return pResult;
537}
538
539
540/**
541 * Assigns one 256-bit unsigned integer value to another.
542 *
543 * @returns pResult
544 * @param pResult The result variable.
545 * @param pValue The value to assign.
546 */
547DECLINLINE(PRTUINT256U) RTUInt256Assign(PRTUINT256U pResult, PCRTUINT256U pValue)
548{
549 pResult->QWords.qw0 = pValue->QWords.qw0;
550 pResult->QWords.qw1 = pValue->QWords.qw1;
551 pResult->QWords.qw2 = pValue->QWords.qw2;
552 pResult->QWords.qw3 = pValue->QWords.qw3;
553 return pResult;
554}
555
556
557/**
558 * Assigns a boolean value to 256-bit unsigned integer.
559 *
560 * @returns pValueResult
561 * @param pValueResult The result variable.
562 * @param fValue The boolean value.
563 */
564DECLINLINE(PRTUINT256U) RTUInt256AssignBoolean(PRTUINT256U pValueResult, bool fValue)
565{
566 pValueResult->QWords.qw0 = fValue;
567 pValueResult->QWords.qw1 = 0;
568 pValueResult->QWords.qw2 = 0;
569 pValueResult->QWords.qw3 = 0;
570 return pValueResult;
571}
572
573
574/**
575 * Assigns a 8-bit unsigned integer value to 256-bit unsigned integer.
576 *
577 * @returns pValueResult
578 * @param pValueResult The result variable.
579 * @param u8Value The 8-bit unsigned integer value.
580 */
581DECLINLINE(PRTUINT256U) RTUInt256AssignU8(PRTUINT256U pValueResult, uint8_t u8Value)
582{
583 pValueResult->QWords.qw0 = u8Value;
584 pValueResult->QWords.qw1 = 0;
585 pValueResult->QWords.qw2 = 0;
586 pValueResult->QWords.qw3 = 0;
587 return pValueResult;
588}
589
590
591/**
592 * Assigns a 16-bit unsigned integer value to 256-bit unsigned integer.
593 *
594 * @returns pValueResult
595 * @param pValueResult The result variable.
596 * @param u16Value The 16-bit unsigned integer value.
597 */
598DECLINLINE(PRTUINT256U) RTUInt256AssignU16(PRTUINT256U pValueResult, uint16_t u16Value)
599{
600 pValueResult->QWords.qw0 = u16Value;
601 pValueResult->QWords.qw1 = 0;
602 pValueResult->QWords.qw2 = 0;
603 pValueResult->QWords.qw3 = 0;
604 return pValueResult;
605}
606
607
608/**
609 * Assigns a 32-bit unsigned integer value to 256-bit unsigned integer.
610 *
611 * @returns pValueResult
612 * @param pValueResult The result variable.
613 * @param u32Value The 32-bit unsigned integer value.
614 */
615DECLINLINE(PRTUINT256U) RTUInt256AssignU32(PRTUINT256U pValueResult, uint32_t u32Value)
616{
617 pValueResult->QWords.qw0 = u32Value;
618 pValueResult->QWords.qw1 = 0;
619 pValueResult->QWords.qw2 = 0;
620 pValueResult->QWords.qw3 = 0;
621 return pValueResult;
622}
623
624
625/**
626 * Assigns a 64-bit unsigned integer value to 256-bit unsigned integer.
627 *
628 * @returns pValueResult
629 * @param pValueResult The result variable.
630 * @param u64Value The 64-bit unsigned integer value.
631 */
632DECLINLINE(PRTUINT256U) RTUInt256AssignU64(PRTUINT256U pValueResult, uint64_t u64Value)
633{
634 pValueResult->QWords.qw0 = u64Value;
635 pValueResult->QWords.qw1 = 0;
636 pValueResult->QWords.qw2 = 0;
637 pValueResult->QWords.qw3 = 0;
638 return pValueResult;
639}
640
641
642/**
643 * Adds two 256-bit unsigned integer values, storing the result in the first.
644 *
645 * @returns pValue1Result.
646 * @param pValue1Result The first value and result.
647 * @param pValue2 The second value.
648 */
649DECLINLINE(PRTUINT256U) RTUInt256AssignAdd(PRTUINT256U pValue1Result, PCRTUINT256U pValue2)
650{
651 RTUINT256U const uTmpValue1 = *pValue1Result; /* lazy bird */
652 return RTUInt256Add(pValue1Result, &uTmpValue1, pValue2);
653}
654
655
656/**
657 * Adds a 64-bit unsigned integer value to a 256-bit unsigned integer values,
658 * storing the result in the 256-bit one.
659 *
660 * @returns pValue1Result.
661 * @param pValue1Result The first value and result.
662 * @param uValue2 The second value, 64-bit.
663 */
664DECLINLINE(PRTUINT256U) RTUInt256AssignAddU64(PRTUINT256U pValue1Result, uint64_t uValue2)
665{
666 RTUINT256U const uTmpValue1 = *pValue1Result; /* lazy bird */
667 return RTUInt256AddU64(pValue1Result, &uTmpValue1, uValue2);
668}
669
670
671/**
672 * Subtracts two 256-bit unsigned integer values, storing the result in the
673 * first.
674 *
675 * @returns pValue1Result.
676 * @param pValue1Result The minuend value and result.
677 * @param pValue2 The subtrahend value.
678 */
679DECLINLINE(PRTUINT256U) RTUInt256AssignSub(PRTUINT256U pValue1Result, PCRTUINT256U pValue2)
680{
681 RTUINT256U const uTmpValue1 = *pValue1Result; /* lazy bird */
682 return RTUInt256Sub(pValue1Result, &uTmpValue1, pValue2);
683}
684
685
686#if 0
687/**
688 * Negates a 256 number, storing the result in the input.
689 *
690 * @returns pValueResult.
691 * @param pValueResult The value to negate.
692 */
693DECLINLINE(PRTUINT256U) RTUInt256AssignNeg(PRTUINT256U pValueResult)
694{
695 /* result = 0 - value */
696 if (pValueResult->s.Lo != 0)
697 {
698 pValueResult->s.Lo = UINT64_C(0) - pValueResult->s.Lo;
699 pValueResult->s.Hi = UINT64_MAX - pValueResult->s.Hi;
700 }
701 else
702 pValueResult->s.Hi = UINT64_C(0) - pValueResult->s.Hi;
703 return pValueResult;
704}
705#endif
706
707
708/**
709 * Multiplies two 256-bit unsigned integer values, storing the result in the
710 * first.
711 *
712 * @returns pValue1Result.
713 * @param pValue1Result The first value and result.
714 * @param pValue2 The second value.
715 */
716DECLINLINE(PRTUINT256U) RTUInt256AssignMul(PRTUINT256U pValue1Result, PCRTUINT256U pValue2)
717{
718 RTUINT256U Result;
719 RTUInt256Mul(&Result, pValue1Result, pValue2);
720 *pValue1Result = Result;
721 return pValue1Result;
722}
723
724
725/**
726 * Divides a 256-bit unsigned integer value by another, storing the result in
727 * the first.
728 *
729 * @returns pValue1Result.
730 * @param pValue1Result The dividend value and result.
731 * @param pValue2 The divisor value.
732 */
733DECLINLINE(PRTUINT256U) RTUInt256AssignDiv(PRTUINT256U pValue1Result, PCRTUINT256U pValue2)
734{
735 RTUINT256U Result;
736 RTUINT256U Ignored;
737 RTUInt256DivRem(&Result, &Ignored, pValue1Result, pValue2);
738 *pValue1Result = Result;
739 return pValue1Result;
740}
741
742
743/**
744 * Divides a 256-bit unsigned integer value by another, storing the remainder in
745 * the first.
746 *
747 * @returns pValue1Result.
748 * @param pValue1Result The dividend value and result (remainder).
749 * @param pValue2 The divisor value.
750 */
751DECLINLINE(PRTUINT256U) RTUInt256AssignMod(PRTUINT256U pValue1Result, PCRTUINT256U pValue2)
752{
753 RTUINT256U Ignored;
754 RTUINT256U Result;
755 RTUInt256DivRem(&Ignored, &Result, pValue1Result, pValue2);
756 *pValue1Result = Result;
757 return pValue1Result;
758}
759
760
761/**
762 * Performs a bitwise AND of two 256-bit unsigned integer values and assigned
763 * the result to the first one.
764 *
765 * @returns pValue1Result.
766 * @param pValue1Result The first value and result.
767 * @param pValue2 The second value.
768 */
769DECLINLINE(PRTUINT256U) RTUInt256AssignAnd(PRTUINT256U pValue1Result, PCRTUINT256U pValue2)
770{
771 pValue1Result->QWords.qw0 &= pValue2->QWords.qw0;
772 pValue1Result->QWords.qw1 &= pValue2->QWords.qw1;
773 pValue1Result->QWords.qw2 &= pValue2->QWords.qw2;
774 pValue1Result->QWords.qw3 &= pValue2->QWords.qw3;
775 return pValue1Result;
776}
777
778
779#if 0
780/**
781 * Performs a bitwise AND of a 256-bit unsigned integer value and a mask made
782 * up of the first N bits, assigning the result to the the 256-bit value.
783 *
784 * @returns pValueResult.
785 * @param pValueResult The value and result.
786 * @param cBits The number of bits to AND (counting from the first
787 * bit).
788 */
789DECLINLINE(PRTUINT256U) RTUInt256AssignAndNFirstBits(PRTUINT256U pValueResult, unsigned cBits)
790{
791 if (cBits <= 64)
792 {
793 if (cBits != 64)
794 pValueResult->s.Lo &= (RT_BIT_64(cBits) - 1);
795 pValueResult->s.Hi = 0;
796 }
797 else if (cBits < 256)
798 pValueResult->s.Hi &= (RT_BIT_64(cBits - 64) - 1);
799/** @todo \#if ARCH_BITS >= 64 */
800 return pValueResult;
801}
802#endif
803
804
805/**
806 * Performs a bitwise OR of two 256-bit unsigned integer values and assigned
807 * the result to the first one.
808 *
809 * @returns pValue1Result.
810 * @param pValue1Result The first value and result.
811 * @param pValue2 The second value.
812 */
813DECLINLINE(PRTUINT256U) RTUInt256AssignOr(PRTUINT256U pValue1Result, PCRTUINT256U pValue2)
814{
815 pValue1Result->QWords.qw0 |= pValue2->QWords.qw0;
816 pValue1Result->QWords.qw1 |= pValue2->QWords.qw1;
817 pValue1Result->QWords.qw2 |= pValue2->QWords.qw2;
818 pValue1Result->QWords.qw3 |= pValue2->QWords.qw3;
819 return pValue1Result;
820}
821
822
823DECLINLINE(PRTUINT256U) RTUInt256BitSet(PRTUINT256U pValueResult, unsigned iBit);
824
825/**
826 * ORs in a bit and assign the result to the input value.
827 *
828 * @returns pValue1Result.
829 * @param pValue1Result The first value and result.
830 * @param iBit The bit to set (0 based).
831 */
832DECLINLINE(PRTUINT256U) RTUInt256AssignOrBit(PRTUINT256U pValue1Result, uint32_t iBit)
833{
834 return RTUInt256BitSet(pValue1Result, (unsigned)iBit);
835}
836
837
838/**
839 * Performs a bitwise XOR of two 256-bit unsigned integer values and assigned
840 * the result to the first one.
841 *
842 * @returns pValue1Result.
843 * @param pValue1Result The first value and result.
844 * @param pValue2 The second value.
845 */
846DECLINLINE(PRTUINT256U) RTUInt256AssignXor(PRTUINT256U pValue1Result, PCRTUINT256U pValue2)
847{
848 pValue1Result->QWords.qw0 ^= pValue2->QWords.qw0;
849 pValue1Result->QWords.qw1 ^= pValue2->QWords.qw1;
850 pValue1Result->QWords.qw2 ^= pValue2->QWords.qw2;
851 pValue1Result->QWords.qw3 ^= pValue2->QWords.qw3;
852 return pValue1Result;
853}
854
855
856/**
857 * Performs a bitwise left shift on a 256-bit unsigned integer value, assigning
858 * the result to it.
859 *
860 * @returns pValueResult.
861 * @param pValueResult The first value and result.
862 * @param cBits The number of bits to shift - signed. Negative
863 * values are translated to right shifts. If the
864 * absolute value is 256 or higher, the value is set to
865 * zero.
866 *
867 * @note This works differently from RTUInt256ShiftLeft and
868 * RTUInt256ShiftRight in that the shift count is signed and not masked
869 * by 255.
870 */
871DECLINLINE(PRTUINT256U) RTUInt256AssignShiftLeft(PRTUINT256U pValueResult, int cBits)
872{
873 if (cBits == 0)
874 return pValueResult;
875 if (cBits > 0)
876 {
877 /* (left shift) */
878 if (cBits < 256)
879 {
880 RTUINT256U const InVal = *pValueResult;
881 return RTUInt256ShiftLeft(pValueResult, &InVal, cBits);
882 }
883 }
884 else if (cBits > -256)
885 {
886 /* (right shift) */
887 cBits = -cBits;
888 RTUINT256U const InVal = *pValueResult;
889 return RTUInt256ShiftRight(pValueResult, &InVal, cBits);
890 }
891 return RTUInt256SetZero(pValueResult);
892}
893
894
895/**
896 * Performs a bitwise left shift on a 256-bit unsigned integer value, assigning
897 * the result to it.
898 *
899 * @returns pValueResult.
900 * @param pValueResult The first value and result.
901 * @param cBits The number of bits to shift - signed. Negative
902 * values are translated to left shifts. If the
903 * absolute value is 256 or higher, the value is set to
904 * zero.
905 *
906 * @note This works differently from RTUInt256ShiftRight and
907 * RTUInt256ShiftLeft in that the shift count is signed and not masked
908 * by 255.
909 */
910DECLINLINE(PRTUINT256U) RTUInt256AssignShiftRight(PRTUINT256U pValueResult, int cBits)
911{
912 if (cBits == 0)
913 return pValueResult;
914 if (cBits > 0)
915 {
916 /* (right shift) */
917 if (cBits < 256)
918 {
919 RTUINT256U const InVal = *pValueResult;
920 return RTUInt256ShiftRight(pValueResult, &InVal, cBits);
921 }
922 }
923 else if (cBits > -256)
924 {
925 /* (left shift) */
926 cBits = -cBits;
927 RTUINT256U const InVal = *pValueResult;
928 return RTUInt256ShiftLeft(pValueResult, &InVal, cBits);
929 }
930 return RTUInt256SetZero(pValueResult);
931}
932
933
934/**
935 * Performs a bitwise NOT on a 256-bit unsigned integer value, assigning the
936 * result to it.
937 *
938 * @returns pValueResult
939 * @param pValueResult The value and result.
940 */
941DECLINLINE(PRTUINT256U) RTUInt256AssignBitwiseNot(PRTUINT256U pValueResult)
942{
943 pValueResult->QWords.qw0 = ~pValueResult->QWords.qw0;
944 pValueResult->QWords.qw1 = ~pValueResult->QWords.qw1;
945 pValueResult->QWords.qw2 = ~pValueResult->QWords.qw2;
946 pValueResult->QWords.qw3 = ~pValueResult->QWords.qw3;
947 return pValueResult;
948}
949
950
951/**
952 * Performs a boolean NOT on a 256-bit unsigned integer value, assigning the
953 * result to it.
954 *
955 * @returns pValueResult
956 * @param pValueResult The value and result.
957 */
958DECLINLINE(PRTUINT256U) RTUInt256AssignBooleanNot(PRTUINT256U pValueResult)
959{
960 return RTUInt256AssignBoolean(pValueResult, RTUInt256IsZero(pValueResult));
961}
962
963
964/**
965 * Compares two 256-bit unsigned integer values.
966 *
967 * @retval 0 if equal.
968 * @retval -1 if the first value is smaller than the second.
969 * @retval 1 if the first value is larger than the second.
970 *
971 * @param pValue1 The first value.
972 * @param pValue2 The second value.
973 */
974DECLINLINE(int) RTUInt256Compare(PCRTUINT256U pValue1, PCRTUINT256U pValue2)
975{
976 if (pValue1->QWords.qw3 != pValue2->QWords.qw3)
977 return pValue1->QWords.qw3 > pValue2->QWords.qw3 ? 1 : -1;
978 if (pValue1->QWords.qw2 != pValue2->QWords.qw2)
979 return pValue1->QWords.qw2 > pValue2->QWords.qw2 ? 1 : -1;
980 if (pValue1->QWords.qw1 != pValue2->QWords.qw1)
981 return pValue1->QWords.qw1 > pValue2->QWords.qw1 ? 1 : -1;
982 if (pValue1->QWords.qw0 != pValue2->QWords.qw0)
983 return pValue1->QWords.qw3 > pValue2->QWords.qw3 ? 1 : -1;
984 return 0;
985}
986
987
988/**
989 * Tests if a 256-bit unsigned integer value is smaller than another.
990 *
991 * @returns true if the first value is smaller, false if not.
992 * @param pValue1 The first value.
993 * @param pValue2 The second value.
994 */
995DECLINLINE(bool) RTUInt256IsSmaller(PCRTUINT256U pValue1, PCRTUINT256U pValue2)
996{
997 return pValue1->QWords.qw3 < pValue2->QWords.qw3
998 || ( pValue1->QWords.qw3 == pValue2->QWords.qw3
999 && ( pValue1->QWords.qw2 < pValue2->QWords.qw2
1000 || ( pValue1->QWords.qw2 == pValue2->QWords.qw2
1001 && ( pValue1->QWords.qw1 < pValue2->QWords.qw1
1002 || ( pValue1->QWords.qw1 == pValue2->QWords.qw1
1003 && pValue1->QWords.qw0 < pValue2->QWords.qw0)))));
1004}
1005
1006
1007/**
1008 * Tests if a 256-bit unsigned integer value is larger than another.
1009 *
1010 * @returns true if the first value is larger, false if not.
1011 * @param pValue1 The first value.
1012 * @param pValue2 The second value.
1013 */
1014DECLINLINE(bool) RTUInt256IsLarger(PCRTUINT256U pValue1, PCRTUINT256U pValue2)
1015{
1016 return pValue1->QWords.qw3 > pValue2->QWords.qw3
1017 || ( pValue1->QWords.qw3 == pValue2->QWords.qw3
1018 && ( pValue1->QWords.qw2 > pValue2->QWords.qw2
1019 || ( pValue1->QWords.qw2 == pValue2->QWords.qw2
1020 && ( pValue1->QWords.qw1 > pValue2->QWords.qw1
1021 || ( pValue1->QWords.qw1 == pValue2->QWords.qw1
1022 && pValue1->QWords.qw0 > pValue2->QWords.qw0)))));
1023}
1024
1025
1026/**
1027 * Tests if a 256-bit unsigned integer value is larger or equal than another.
1028 *
1029 * @returns true if the first value is larger or equal, false if not.
1030 * @param pValue1 The first value.
1031 * @param pValue2 The second value.
1032 */
1033DECLINLINE(bool) RTUInt256IsLargerOrEqual(PCRTUINT256U pValue1, PCRTUINT256U pValue2)
1034{
1035 return pValue1->QWords.qw3 > pValue2->QWords.qw3
1036 || ( pValue1->QWords.qw3 == pValue2->QWords.qw3
1037 && ( pValue1->QWords.qw2 > pValue2->QWords.qw2
1038 || ( pValue1->QWords.qw2 == pValue2->QWords.qw2
1039 && ( pValue1->QWords.qw1 > pValue2->QWords.qw1
1040 || ( pValue1->QWords.qw1 == pValue2->QWords.qw1
1041 && pValue1->QWords.qw0 >= pValue2->DWords.dw0)))));
1042}
1043
1044
1045/**
1046 * Tests if two 256-bit unsigned integer values not equal.
1047 *
1048 * @returns true if equal, false if not equal.
1049 * @param pValue1 The first value.
1050 * @param pValue2 The second value.
1051 */
1052DECLINLINE(bool) RTUInt256IsEqual(PCRTUINT256U pValue1, PCRTUINT256U pValue2)
1053{
1054 return pValue1->QWords.qw0 == pValue2->QWords.qw0
1055 && pValue1->QWords.qw1 == pValue2->QWords.qw1
1056 && pValue1->QWords.qw2 == pValue2->QWords.qw2
1057 && pValue1->QWords.qw3 == pValue2->QWords.qw3;
1058}
1059
1060
1061/**
1062 * Tests if two 256-bit unsigned integer values are not equal.
1063 *
1064 * @returns true if not equal, false if equal.
1065 * @param pValue1 The first value.
1066 * @param pValue2 The second value.
1067 */
1068DECLINLINE(bool) RTUInt256IsNotEqual(PCRTUINT256U pValue1, PCRTUINT256U pValue2)
1069{
1070 return !RTUInt256IsEqual(pValue1, pValue2);
1071}
1072
1073
1074/**
1075 * Sets a bit in a 256-bit unsigned integer type.
1076 *
1077 * @returns pValueResult.
1078 * @param pValueResult The input and output value.
1079 * @param iBit The bit to set.
1080 */
1081DECLINLINE(PRTUINT256U) RTUInt256BitSet(PRTUINT256U pValueResult, unsigned iBit)
1082{
1083 if (iBit < 256)
1084 {
1085 unsigned idxQWord = iBit >> 6;
1086#ifdef RT_BIG_ENDIAN
1087 idxQWord = RT_ELEMENTS(pValueResult->au64) - idxQWord;
1088#endif
1089 iBit &= 0x3f;
1090 pValueResult->au64[idxQWord] |= RT_BIT_64(iBit);
1091 }
1092 return pValueResult;
1093}
1094
1095
1096/**
1097 * Sets a bit in a 256-bit unsigned integer type.
1098 *
1099 * @returns pValueResult.
1100 * @param pValueResult The input and output value.
1101 * @param iBit The bit to set.
1102 */
1103DECLINLINE(PRTUINT256U) RTUInt256BitClear(PRTUINT256U pValueResult, unsigned iBit)
1104{
1105 if (iBit < 256)
1106 {
1107 unsigned idxQWord = iBit >> 6;
1108#ifdef RT_BIG_ENDIAN
1109 idxQWord = RT_ELEMENTS(pValueResult->au64) - idxQWord;
1110#endif
1111 iBit &= 0x3f;
1112 pValueResult->au64[idxQWord] &= ~RT_BIT_64(iBit);
1113 }
1114 return pValueResult;
1115}
1116
1117
1118/**
1119 * Tests if a bit in a 256-bit unsigned integer value is set.
1120 *
1121 * @returns pValueResult.
1122 * @param pValueResult The input and output value.
1123 * @param iBit The bit to test.
1124 */
1125DECLINLINE(bool) RTUInt256BitTest(PRTUINT256U pValueResult, unsigned iBit)
1126{
1127 bool fRc;
1128 if (iBit < 256)
1129 {
1130 unsigned idxQWord = iBit >> 6;
1131#ifdef RT_BIG_ENDIAN
1132 idxQWord = RT_ELEMENTS(pValueResult->au64) - idxQWord;
1133#endif
1134 iBit &= 0x3f;
1135 fRc = RT_BOOL(pValueResult->au64[idxQWord] & RT_BIT_64(iBit));
1136 }
1137 else
1138 fRc = false;
1139 return fRc;
1140}
1141
1142
1143/**
1144 * Set a range of bits a 256-bit unsigned integer value.
1145 *
1146 * @returns pValueResult.
1147 * @param pValueResult The input and output value.
1148 * @param iFirstBit The first bit to test.
1149 * @param cBits The number of bits to set.
1150 */
1151DECLINLINE(PRTUINT256U) RTUInt256BitSetRange(PRTUINT256U pValueResult, unsigned iFirstBit, unsigned cBits)
1152{
1153 /* bounds check & fix. */
1154 if (iFirstBit < 256)
1155 {
1156 if (iFirstBit + cBits > 256)
1157 cBits = 256 - iFirstBit;
1158
1159 /* Work the au64 array: */
1160#ifdef RT_BIG_ENDIAN
1161 int idxQWord = RT_ELEMENTS(pValueResult->au64) - (iFirstBit >> 6);
1162 int const idxInc = -1;
1163#else
1164 int idxQWord = iFirstBit >> 6;
1165 int const idxInc = 1;
1166#endif
1167 while (cBits > 0)
1168 {
1169 unsigned iQWordFirstBit = iFirstBit & 0x3f;
1170 unsigned cQWordBits = cBits + iQWordFirstBit >= 64 ? 64 - iQWordFirstBit : cBits;
1171 pValueResult->au64[idxQWord] |= cQWordBits < 64 ? (RT_BIT_64(cQWordBits) - 1) << iQWordFirstBit : UINT64_MAX;
1172
1173 idxQWord += idxInc;
1174 iFirstBit += cQWordBits;
1175 cBits -= cQWordBits;
1176 }
1177 }
1178 return pValueResult;
1179}
1180
1181
1182/**
1183 * Test if all the bits of a 256-bit unsigned integer value are set.
1184 *
1185 * @returns true if they are, false if they aren't.
1186 * @param pValue The input and output value.
1187 */
1188DECLINLINE(bool) RTUInt256BitAreAllSet(PRTUINT256U pValue)
1189{
1190 return pValue->QWords.qw0 == UINT64_MAX
1191 && pValue->QWords.qw1 == UINT64_MAX
1192 && pValue->QWords.qw2 == UINT64_MAX
1193 && pValue->QWords.qw3 == UINT64_MAX;
1194}
1195
1196
1197/**
1198 * Test if all the bits of a 256-bit unsigned integer value are clear.
1199 *
1200 * @returns true if they are, false if they aren't.
1201 * @param pValue The input and output value.
1202 */
1203DECLINLINE(bool) RTUInt256BitAreAllClear(PRTUINT256U pValue)
1204{
1205 return RTUInt256IsZero(pValue);
1206}
1207
1208
1209/**
1210 * Number of significant bits in the value.
1211 *
1212 * This is the same a ASMBitLastSetU64 and ASMBitLastSetU32.
1213 *
1214 * @returns 0 if zero, 1-base index of the last bit set.
1215 * @param pValue The value to examine.
1216 */
1217DECLINLINE(uint32_t) RTUInt256BitCount(PCRTUINT256U pValue)
1218{
1219 uint64_t u64;
1220 uint32_t cBits;
1221 if ((u64 = pValue->QWords.qw3) != 0)
1222 cBits = 192;
1223 else if ((u64 = pValue->QWords.qw2) != 0)
1224 cBits = 128;
1225 else if ((u64 = pValue->QWords.qw1) != 0)
1226 cBits = 64;
1227 else
1228 {
1229 u64 = pValue->QWords.qw0;
1230 cBits = 0;
1231 }
1232 return cBits + ASMBitLastSetU64(u64);
1233}
1234
1235
1236/** @} */
1237
1238RT_C_DECLS_END
1239
1240#endif /* !IPRT_INCLUDED_uint256_h */
1241
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette