VirtualBox

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

Last change on this file since 95769 was 94513, checked in by vboxsync, 3 years ago

IPRT: Added RTUInt128MulEx and RTUInt128MulU64Ex as well as a limited RTUInt256Xxx Api. [build fix] bugref:9898

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