GuestHost/installation/VBoxWinDrvInst.cpp: Try harder if DiInstallDriverW() returns...
[vbox.git] / include / iprt / uint128.h
blob6f4a0d919ed9686301959d8d30324632da904ae9
1 /** @file
2 * IPRT - RTUINT128U & uint128_t methods.
3 */
5 /*
6 * Copyright (C) 2011-2024 Oracle and/or its affiliates.
8 * This file is part of VirtualBox base platform packages, as
9 * available from https://www.virtualbox.org.
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.
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.
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>.
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.
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.
33 * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
36 #ifndef IPRT_INCLUDED_uint128_h
37 #define IPRT_INCLUDED_uint128_h
38 #ifndef RT_WITHOUT_PRAGMA_ONCE
39 # pragma once
40 #endif
42 #include <iprt/cdefs.h>
43 #include <iprt/types.h>
44 #include <iprt/asm.h>
45 #include <iprt/asm-math.h>
47 RT_C_DECLS_BEGIN
49 /** @defgroup grp_rt_uint128 RTUInt128 - 128-bit Unsigned Integer Methods
50 * @ingroup grp_rt
51 * @{
55 /**
56 * Test if a 128-bit unsigned integer value is zero.
58 * @returns true if they are, false if they aren't.
59 * @param pValue The input and output value.
61 DECLINLINE(bool) RTUInt128IsZero(PCRTUINT128U pValue)
63 #if ARCH_BITS >= 64
64 return pValue->s.Hi == 0
65 && pValue->s.Lo == 0;
66 #else
67 return pValue->DWords.dw0 == 0
68 && pValue->DWords.dw1 == 0
69 && pValue->DWords.dw2 == 0
70 && pValue->DWords.dw3 == 0;
71 #endif
75 /**
76 * Set a 128-bit unsigned integer value to zero.
78 * @returns pResult
79 * @param pResult The result variable.
81 DECLINLINE(PRTUINT128U) RTUInt128SetZero(PRTUINT128U pResult)
83 #if ARCH_BITS >= 64
84 pResult->s.Hi = 0;
85 pResult->s.Lo = 0;
86 #else
87 pResult->DWords.dw0 = 0;
88 pResult->DWords.dw1 = 0;
89 pResult->DWords.dw2 = 0;
90 pResult->DWords.dw3 = 0;
91 #endif
92 return pResult;
96 /**
97 * Set a 128-bit unsigned integer value to the maximum value.
99 * @returns pResult
100 * @param pResult The result variable.
102 DECLINLINE(PRTUINT128U) RTUInt128SetMax(PRTUINT128U pResult)
104 #if ARCH_BITS >= 64
105 pResult->s.Hi = UINT64_MAX;
106 pResult->s.Lo = UINT64_MAX;
107 #else
108 pResult->DWords.dw0 = UINT32_MAX;
109 pResult->DWords.dw1 = UINT32_MAX;
110 pResult->DWords.dw2 = UINT32_MAX;
111 pResult->DWords.dw3 = UINT32_MAX;
112 #endif
113 return pResult;
120 * Adds two 128-bit unsigned integer values.
122 * @returns pResult
123 * @param pResult The result variable.
124 * @param pValue1 The first value.
125 * @param pValue2 The second value.
127 DECLINLINE(PRTUINT128U) RTUInt128Add(PRTUINT128U pResult, PCRTUINT128U pValue1, PCRTUINT128U pValue2)
129 pResult->s.Hi = pValue1->s.Hi + pValue2->s.Hi;
130 pResult->s.Lo = pValue1->s.Lo + pValue2->s.Lo;
131 if (pResult->s.Lo < pValue1->s.Lo)
132 pResult->s.Hi++;
133 return pResult;
138 * Adds a 128-bit and a 64-bit unsigned integer values.
140 * @returns pResult
141 * @param pResult The result variable.
142 * @param pValue1 The first value.
143 * @param uValue2 The second value, 64-bit.
145 DECLINLINE(PRTUINT128U) RTUInt128AddU64(PRTUINT128U pResult, PCRTUINT128U pValue1, uint64_t uValue2)
147 pResult->s.Hi = pValue1->s.Hi;
148 pResult->s.Lo = pValue1->s.Lo + uValue2;
149 if (pResult->s.Lo < pValue1->s.Lo)
150 pResult->s.Hi++;
151 return pResult;
156 * Subtracts a 128-bit unsigned integer value from another.
158 * @returns pResult
159 * @param pResult The result variable.
160 * @param pValue1 The minuend value.
161 * @param pValue2 The subtrahend value.
163 DECLINLINE(PRTUINT128U) RTUInt128Sub(PRTUINT128U pResult, PCRTUINT128U pValue1, PCRTUINT128U pValue2)
165 pResult->s.Lo = pValue1->s.Lo - pValue2->s.Lo;
166 pResult->s.Hi = pValue1->s.Hi - pValue2->s.Hi;
167 if (pResult->s.Lo > pValue1->s.Lo)
168 pResult->s.Hi--;
169 return pResult;
174 * Multiplies two 128-bit unsigned integer values.
176 * @returns pResult
177 * @param pResult The result variable.
178 * @param pValue1 The first value.
179 * @param pValue2 The second value.
181 DECLINLINE(PRTUINT128U) RTUInt128Mul(PRTUINT128U pResult, PCRTUINT128U pValue1, PCRTUINT128U pValue2)
183 RTUINT64U uTmp;
185 /* multiply all dwords in v1 by v2.dw0. */
186 pResult->s.Lo = (uint64_t)pValue1->DWords.dw0 * pValue2->DWords.dw0;
188 uTmp.u = (uint64_t)pValue1->DWords.dw1 * pValue2->DWords.dw0;
189 pResult->DWords.dw3 = 0;
190 pResult->DWords.dw2 = uTmp.DWords.dw1;
191 pResult->DWords.dw1 += uTmp.DWords.dw0;
192 if (pResult->DWords.dw1 < uTmp.DWords.dw0)
193 if (pResult->DWords.dw2++ == UINT32_MAX)
194 pResult->DWords.dw3++;
196 pResult->s.Hi += (uint64_t)pValue1->DWords.dw2 * pValue2->DWords.dw0;
197 pResult->DWords.dw3 += pValue1->DWords.dw3 * pValue2->DWords.dw0;
199 /* multiply dw0, dw1 & dw2 in v1 by v2.dw1. */
200 uTmp.u = (uint64_t)pValue1->DWords.dw0 * pValue2->DWords.dw1;
201 pResult->DWords.dw1 += uTmp.DWords.dw0;
202 if (pResult->DWords.dw1 < uTmp.DWords.dw0)
203 if (pResult->DWords.dw2++ == UINT32_MAX)
204 pResult->DWords.dw3++;
206 pResult->DWords.dw2 += uTmp.DWords.dw1;
207 if (pResult->DWords.dw2 < uTmp.DWords.dw1)
208 pResult->DWords.dw3++;
210 pResult->s.Hi += (uint64_t)pValue1->DWords.dw1 * pValue2->DWords.dw1;
211 pResult->DWords.dw3 += pValue1->DWords.dw2 * pValue2->DWords.dw1;
213 /* multiply dw0 & dw1 in v1 by v2.dw2. */
214 pResult->s.Hi += (uint64_t)pValue1->DWords.dw0 * pValue2->DWords.dw2;
215 pResult->DWords.dw3 += pValue1->DWords.dw1 * pValue2->DWords.dw2;
217 /* multiply dw0 in v1 by v2.dw3. */
218 pResult->DWords.dw3 += pValue1->DWords.dw0 * pValue2->DWords.dw3;
220 return pResult;
225 * Multiplies an 128-bit unsigned integer by a 64-bit unsigned integer value.
227 * @returns pResult
228 * @param pResult The result variable.
229 * @param pValue1 The first value.
230 * @param uValue2 The second value, 64-bit.
232 #if defined(RT_ARCH_AMD64)
233 RTDECL(PRTUINT128U) RTUInt128MulByU64(PRTUINT128U pResult, PCRTUINT128U pValue1, uint64_t uValue2);
234 #else
235 DECLINLINE(PRTUINT128U) RTUInt128MulByU64(PRTUINT128U pResult, PCRTUINT128U pValue1, uint64_t uValue2)
237 uint32_t const uLoValue2 = (uint32_t)uValue2;
238 uint32_t const uHiValue2 = (uint32_t)(uValue2 >> 32);
239 RTUINT64U uTmp;
241 /* multiply all dwords in v1 by uLoValue1. */
242 pResult->s.Lo = (uint64_t)pValue1->DWords.dw0 * uLoValue2;
244 uTmp.u = (uint64_t)pValue1->DWords.dw1 * uLoValue2;
245 pResult->DWords.dw3 = 0;
246 pResult->DWords.dw2 = uTmp.DWords.dw1;
247 pResult->DWords.dw1 += uTmp.DWords.dw0;
248 if (pResult->DWords.dw1 < uTmp.DWords.dw0)
249 if (pResult->DWords.dw2++ == UINT32_MAX)
250 pResult->DWords.dw3++;
252 pResult->s.Hi += (uint64_t)pValue1->DWords.dw2 * uLoValue2;
253 pResult->DWords.dw3 += pValue1->DWords.dw3 * uLoValue2;
255 /* multiply dw0, dw1 & dw2 in v1 by uHiValue2. */
256 uTmp.u = (uint64_t)pValue1->DWords.dw0 * uHiValue2;
257 pResult->DWords.dw1 += uTmp.DWords.dw0;
258 if (pResult->DWords.dw1 < uTmp.DWords.dw0)
259 if (pResult->DWords.dw2++ == UINT32_MAX)
260 pResult->DWords.dw3++;
262 pResult->DWords.dw2 += uTmp.DWords.dw1;
263 if (pResult->DWords.dw2 < uTmp.DWords.dw1)
264 pResult->DWords.dw3++;
266 pResult->s.Hi += (uint64_t)pValue1->DWords.dw1 * uHiValue2;
267 pResult->DWords.dw3 += pValue1->DWords.dw2 * uHiValue2;
269 return pResult;
271 #endif
275 * Multiplies two 64-bit unsigned integer values with 128-bit precision.
277 * @returns pResult
278 * @param pResult The result variable.
279 * @param uValue1 The first value. 64-bit.
280 * @param uValue2 The second value, 64-bit.
282 DECLINLINE(PRTUINT128U) RTUInt128MulU64ByU64(PRTUINT128U pResult, uint64_t uValue1, uint64_t uValue2)
284 #ifdef RT_ARCH_AMD64
285 pResult->s.Lo = ASMMult2xU64Ret2xU64(uValue1, uValue2, &pResult->s.Hi);
286 #else
287 uint32_t const uLoValue1 = (uint32_t)uValue1;
288 uint32_t const uHiValue1 = (uint32_t)(uValue1 >> 32);
289 uint32_t const uLoValue2 = (uint32_t)uValue2;
290 uint32_t const uHiValue2 = (uint32_t)(uValue2 >> 32);
291 RTUINT64U uTmp;
293 /* Multiply uLoValue1 and uHiValue1 by uLoValue1. */
294 pResult->s.Lo = (uint64_t)uLoValue1 * uLoValue2;
296 uTmp.u = (uint64_t)uHiValue1 * uLoValue2;
297 pResult->DWords.dw3 = 0;
298 pResult->DWords.dw2 = uTmp.DWords.dw1;
299 pResult->DWords.dw1 += uTmp.DWords.dw0;
300 if (pResult->DWords.dw1 < uTmp.DWords.dw0)
301 if (pResult->DWords.dw2++ == UINT32_MAX)
302 pResult->DWords.dw3++;
304 /* Multiply uLoValue1 and uHiValue1 by uHiValue2. */
305 uTmp.u = (uint64_t)uLoValue1 * uHiValue2;
306 pResult->DWords.dw1 += uTmp.DWords.dw0;
307 if (pResult->DWords.dw1 < uTmp.DWords.dw0)
308 if (pResult->DWords.dw2++ == UINT32_MAX)
309 pResult->DWords.dw3++;
311 pResult->DWords.dw2 += uTmp.DWords.dw1;
312 if (pResult->DWords.dw2 < uTmp.DWords.dw1)
313 pResult->DWords.dw3++;
315 pResult->s.Hi += (uint64_t)uHiValue1 * uHiValue2;
316 #endif
317 return pResult;
322 * Multiplies an 128-bit unsigned integer by a 64-bit unsigned integer value,
323 * returning a 256-bit result (top 64 bits are zero).
325 * @returns pResult
326 * @param pResult The result variable.
327 * @param pValue1 The first value.
328 * @param uValue2 The second value, 64-bit.
330 #if defined(RT_ARCH_AMD64)
331 RTDECL(PRTUINT256U) RTUInt128MulByU64Ex(PRTUINT256U pResult, PCRTUINT128U pValue1, uint64_t uValue2);
332 #else
333 DECLINLINE(PRTUINT256U) RTUInt128MulByU64Ex(PRTUINT256U pResult, PCRTUINT128U pValue1, uint64_t uValue2)
335 /* multiply the two qwords in pValue1 by uValue2. */
336 uint64_t uTmp = 0;
337 pResult->QWords.qw0 = ASMMult2xU64Ret2xU64(pValue1->s.Lo, uValue2, &uTmp);
338 pResult->QWords.qw1 = ASMMult2xU64Ret2xU64(pValue1->s.Hi, uValue2, &pResult->QWords.qw2);
339 pResult->QWords.qw3 = 0;
340 pResult->QWords.qw1 += uTmp;
341 if (pResult->QWords.qw1 < uTmp)
342 pResult->QWords.qw2++; /* This cannot overflow AFAIK: 0xffff*0xffff = 0xFFFE0001 */
344 return pResult;
346 #endif
350 * Multiplies two 128-bit unsigned integer values, returning a 256-bit result.
352 * @returns pResult
353 * @param pResult The result variable.
354 * @param pValue1 The first value.
355 * @param pValue2 The second value.
357 DECLINLINE(PRTUINT256U) RTUInt128MulEx(PRTUINT256U pResult, PCRTUINT128U pValue1, PCRTUINT128U pValue2)
359 RTUInt128MulByU64Ex(pResult, pValue1, pValue2->s.Lo);
360 if (pValue2->s.Hi)
362 /* Multiply the two qwords in pValue1 by the high part of uValue2. */
363 uint64_t uTmpHi = 0;
364 uint64_t uTmpLo = ASMMult2xU64Ret2xU64(pValue1->s.Lo, pValue2->s.Hi, &uTmpHi);
365 pResult->QWords.qw1 += uTmpLo;
366 if (pResult->QWords.qw1 < uTmpLo)
367 if (++pResult->QWords.qw2 == 0)
368 pResult->QWords.qw3++; /* (cannot overflow, was == 0) */
369 pResult->QWords.qw2 += uTmpHi;
370 if (pResult->QWords.qw2 < uTmpHi)
371 pResult->QWords.qw3++; /* (cannot overflow, was <= 1) */
373 uTmpLo = ASMMult2xU64Ret2xU64(pValue1->s.Hi, pValue2->s.Hi, &uTmpHi);
374 pResult->QWords.qw2 += uTmpLo;
375 if (pResult->QWords.qw2 < uTmpLo)
376 pResult->QWords.qw3++; /* (cannot overflow, was <= 2) */
377 pResult->QWords.qw3 += uTmpHi;
380 return pResult;
384 DECLINLINE(PRTUINT128U) RTUInt128DivRem(PRTUINT128U pQuotient, PRTUINT128U pRemainder, PCRTUINT128U pValue1, PCRTUINT128U pValue2);
387 * Divides a 128-bit unsigned integer value by another.
389 * @returns pResult
390 * @param pResult The result variable.
391 * @param pValue1 The dividend value.
392 * @param pValue2 The divisor value.
394 DECLINLINE(PRTUINT128U) RTUInt128Div(PRTUINT128U pResult, PCRTUINT128U pValue1, PCRTUINT128U pValue2)
396 RTUINT128U Ignored;
397 return RTUInt128DivRem(pResult, &Ignored, pValue1, pValue2);
402 * Divides a 128-bit unsigned integer value by another, returning the remainder.
404 * @returns pResult
405 * @param pResult The result variable (remainder).
406 * @param pValue1 The dividend value.
407 * @param pValue2 The divisor value.
409 DECLINLINE(PRTUINT128U) RTUInt128Mod(PRTUINT128U pResult, PCRTUINT128U pValue1, PCRTUINT128U pValue2)
411 RTUINT128U Ignored;
412 RTUInt128DivRem(&Ignored, pResult, pValue1, pValue2);
413 return pResult;
418 * Bitwise AND of two 128-bit unsigned integer values.
420 * @returns pResult
421 * @param pResult The result variable.
422 * @param pValue1 The first value.
423 * @param pValue2 The second value.
425 DECLINLINE(PRTUINT128U) RTUInt128And(PRTUINT128U pResult, PCRTUINT128U pValue1, PCRTUINT128U pValue2)
427 pResult->s.Hi = pValue1->s.Hi & pValue2->s.Hi;
428 pResult->s.Lo = pValue1->s.Lo & pValue2->s.Lo;
429 return pResult;
434 * Bitwise OR of two 128-bit unsigned integer values.
436 * @returns pResult
437 * @param pResult The result variable.
438 * @param pValue1 The first value.
439 * @param pValue2 The second value.
441 DECLINLINE(PRTUINT128U) RTUInt128Or( PRTUINT128U pResult, PCRTUINT128U pValue1, PCRTUINT128U pValue2)
443 pResult->s.Hi = pValue1->s.Hi | pValue2->s.Hi;
444 pResult->s.Lo = pValue1->s.Lo | pValue2->s.Lo;
445 return pResult;
450 * Bitwise XOR of two 128-bit unsigned integer values.
452 * @returns pResult
453 * @param pResult The result variable.
454 * @param pValue1 The first value.
455 * @param pValue2 The second value.
457 DECLINLINE(PRTUINT128U) RTUInt128Xor(PRTUINT128U pResult, PCRTUINT128U pValue1, PCRTUINT128U pValue2)
459 pResult->s.Hi = pValue1->s.Hi ^ pValue2->s.Hi;
460 pResult->s.Lo = pValue1->s.Lo ^ pValue2->s.Lo;
461 return pResult;
466 * Shifts a 128-bit unsigned integer value @a cBits to the left.
468 * @returns pResult
469 * @param pResult The result variable.
470 * @param pValue The value to shift.
471 * @param cBits The number of bits to shift it.
473 DECLINLINE(PRTUINT128U) RTUInt128ShiftLeft(PRTUINT128U pResult, PCRTUINT128U pValue, int cBits)
475 cBits &= 127;
476 if (cBits < 64)
478 pResult->s.Lo = pValue->s.Lo << cBits;
479 pResult->s.Hi = (pValue->s.Hi << cBits) | (pValue->s.Lo >> (64 - cBits));
481 else
483 pResult->s.Lo = 0;
484 pResult->s.Hi = pValue->s.Lo << (cBits - 64);
486 return pResult;
491 * Shifts a 128-bit unsigned integer value @a cBits to the right.
493 * @returns pResult
494 * @param pResult The result variable.
495 * @param pValue The value to shift.
496 * @param cBits The number of bits to shift it.
498 DECLINLINE(PRTUINT128U) RTUInt128ShiftRight(PRTUINT128U pResult, PCRTUINT128U pValue, int cBits)
500 cBits &= 127;
501 if (cBits < 64)
503 pResult->s.Hi = pValue->s.Hi >> cBits;
504 pResult->s.Lo = (pValue->s.Lo >> cBits) | (pValue->s.Hi << (64 - cBits));
506 else
508 pResult->s.Hi = 0;
509 pResult->s.Lo = pValue->s.Hi >> (cBits - 64);
511 return pResult;
516 * Boolean not (result 0 or 1).
518 * @returns pResult.
519 * @param pResult The result variable.
520 * @param pValue The value.
522 DECLINLINE(PRTUINT128U) RTUInt128BooleanNot(PRTUINT128U pResult, PCRTUINT128U pValue)
524 pResult->s.Lo = pValue->s.Lo || pValue->s.Hi ? 0 : 1;
525 pResult->s.Hi = 0;
526 return pResult;
531 * Bitwise not (flips each bit of the 128 bits).
533 * @returns pResult.
534 * @param pResult The result variable.
535 * @param pValue The value.
537 DECLINLINE(PRTUINT128U) RTUInt128BitwiseNot(PRTUINT128U pResult, PCRTUINT128U pValue)
539 pResult->s.Hi = ~pValue->s.Hi;
540 pResult->s.Lo = ~pValue->s.Lo;
541 return pResult;
546 * Assigns one 128-bit unsigned integer value to another.
548 * @returns pResult
549 * @param pResult The result variable.
550 * @param pValue The value to assign.
552 DECLINLINE(PRTUINT128U) RTUInt128Assign(PRTUINT128U pResult, PCRTUINT128U pValue)
554 #if ARCH_BITS >= 64
555 pResult->s.Hi = pValue->s.Hi;
556 pResult->s.Lo = pValue->s.Lo;
557 #else
558 pResult->DWords.dw0 = pValue->DWords.dw0;
559 pResult->DWords.dw1 = pValue->DWords.dw1;
560 pResult->DWords.dw2 = pValue->DWords.dw2;
561 pResult->DWords.dw3 = pValue->DWords.dw3;
562 #endif
563 return pResult;
568 * Assigns a boolean value to 128-bit unsigned integer.
570 * @returns pValueResult
571 * @param pValueResult The result variable.
572 * @param fValue The boolean value.
574 DECLINLINE(PRTUINT128U) RTUInt128AssignBoolean(PRTUINT128U pValueResult, bool fValue)
576 #if ARCH_BITS >= 64
577 pValueResult->s.Lo = fValue;
578 pValueResult->s.Hi = 0;
579 #else
580 pValueResult->DWords.dw0 = fValue;
581 pValueResult->DWords.dw1 = 0;
582 pValueResult->DWords.dw2 = 0;
583 pValueResult->DWords.dw3 = 0;
584 #endif
585 return pValueResult;
590 * Assigns a 8-bit unsigned integer value to 128-bit unsigned integer.
592 * @returns pValueResult
593 * @param pValueResult The result variable.
594 * @param u8Value The 8-bit unsigned integer value.
596 DECLINLINE(PRTUINT128U) RTUInt128AssignU8(PRTUINT128U pValueResult, uint8_t u8Value)
598 #if ARCH_BITS >= 64
599 pValueResult->s.Lo = u8Value;
600 pValueResult->s.Hi = 0;
601 #else
602 pValueResult->DWords.dw0 = u8Value;
603 pValueResult->DWords.dw1 = 0;
604 pValueResult->DWords.dw2 = 0;
605 pValueResult->DWords.dw3 = 0;
606 #endif
607 return pValueResult;
612 * Assigns a 16-bit unsigned integer value to 128-bit unsigned integer.
614 * @returns pValueResult
615 * @param pValueResult The result variable.
616 * @param u16Value The 16-bit unsigned integer value.
618 DECLINLINE(PRTUINT128U) RTUInt128AssignU16(PRTUINT128U pValueResult, uint16_t u16Value)
620 #if ARCH_BITS >= 64
621 pValueResult->s.Lo = u16Value;
622 pValueResult->s.Hi = 0;
623 #else
624 pValueResult->DWords.dw0 = u16Value;
625 pValueResult->DWords.dw1 = 0;
626 pValueResult->DWords.dw2 = 0;
627 pValueResult->DWords.dw3 = 0;
628 #endif
629 return pValueResult;
634 * Assigns a 32-bit unsigned integer value to 128-bit unsigned integer.
636 * @returns pValueResult
637 * @param pValueResult The result variable.
638 * @param u32Value The 32-bit unsigned integer value.
640 DECLINLINE(PRTUINT128U) RTUInt128AssignU32(PRTUINT128U pValueResult, uint32_t u32Value)
642 #if ARCH_BITS >= 64
643 pValueResult->s.Lo = u32Value;
644 pValueResult->s.Hi = 0;
645 #else
646 pValueResult->DWords.dw0 = u32Value;
647 pValueResult->DWords.dw1 = 0;
648 pValueResult->DWords.dw2 = 0;
649 pValueResult->DWords.dw3 = 0;
650 #endif
651 return pValueResult;
656 * Assigns a 64-bit unsigned integer value to 128-bit unsigned integer.
658 * @returns pValueResult
659 * @param pValueResult The result variable.
660 * @param u64Value The 64-bit unsigned integer value.
662 DECLINLINE(PRTUINT128U) RTUInt128AssignU64(PRTUINT128U pValueResult, uint64_t u64Value)
664 pValueResult->s.Lo = u64Value;
665 pValueResult->s.Hi = 0;
666 return pValueResult;
671 * Adds two 128-bit unsigned integer values, storing the result in the first.
673 * @returns pValue1Result.
674 * @param pValue1Result The first value and result.
675 * @param pValue2 The second value.
677 DECLINLINE(PRTUINT128U) RTUInt128AssignAdd(PRTUINT128U pValue1Result, PCRTUINT128U pValue2)
679 uint64_t const uTmp = pValue1Result->s.Lo;
680 pValue1Result->s.Lo += pValue2->s.Lo;
681 if (pValue1Result->s.Lo < uTmp)
682 pValue1Result->s.Hi++;
683 pValue1Result->s.Hi += pValue2->s.Hi;
684 return pValue1Result;
689 * Adds a 64-bit unsigned integer value to a 128-bit unsigned integer values,
690 * storing the result in the 128-bit one.
692 * @returns pValue1Result.
693 * @param pValue1Result The first value and result.
694 * @param uValue2 The second value, 64-bit.
696 DECLINLINE(PRTUINT128U) RTUInt128AssignAddU64(PRTUINT128U pValue1Result, uint64_t uValue2)
698 pValue1Result->s.Lo += uValue2;
699 if (pValue1Result->s.Lo < uValue2)
700 pValue1Result->s.Hi++;
701 return pValue1Result;
706 * Subtracts two 128-bit unsigned integer values, storing the result in the
707 * first.
709 * @returns pValue1Result.
710 * @param pValue1Result The minuend value and result.
711 * @param pValue2 The subtrahend value.
713 DECLINLINE(PRTUINT128U) RTUInt128AssignSub(PRTUINT128U pValue1Result, PCRTUINT128U pValue2)
715 uint64_t const uTmp = pValue1Result->s.Lo;
716 pValue1Result->s.Lo -= pValue2->s.Lo;
717 if (pValue1Result->s.Lo > uTmp)
718 pValue1Result->s.Hi--;
719 pValue1Result->s.Hi -= pValue2->s.Hi;
720 return pValue1Result;
725 * Negates a 128 number, storing the result in the input.
727 * @returns pValueResult.
728 * @param pValueResult The value to negate.
730 DECLINLINE(PRTUINT128U) RTUInt128AssignNeg(PRTUINT128U pValueResult)
732 /* result = 0 - value */
733 if (pValueResult->s.Lo != 0)
735 pValueResult->s.Lo = UINT64_C(0) - pValueResult->s.Lo;
736 pValueResult->s.Hi = UINT64_MAX - pValueResult->s.Hi;
738 else
739 pValueResult->s.Hi = UINT64_C(0) - pValueResult->s.Hi;
740 return pValueResult;
745 * Multiplies two 128-bit unsigned integer values, storing the result in the
746 * first.
748 * @returns pValue1Result.
749 * @param pValue1Result The first value and result.
750 * @param pValue2 The second value.
752 DECLINLINE(PRTUINT128U) RTUInt128AssignMul(PRTUINT128U pValue1Result, PCRTUINT128U pValue2)
754 RTUINT128U Result;
755 RTUInt128Mul(&Result, pValue1Result, pValue2);
756 *pValue1Result = Result;
757 return pValue1Result;
762 * Divides a 128-bit unsigned integer value by another, storing the result in
763 * the first.
765 * @returns pValue1Result.
766 * @param pValue1Result The dividend value and result.
767 * @param pValue2 The divisor value.
769 DECLINLINE(PRTUINT128U) RTUInt128AssignDiv(PRTUINT128U pValue1Result, PCRTUINT128U pValue2)
771 RTUINT128U Result;
772 RTUINT128U Ignored;
773 RTUInt128DivRem(&Result, &Ignored, pValue1Result, pValue2);
774 *pValue1Result = Result;
775 return pValue1Result;
780 * Divides a 128-bit unsigned integer value by another, storing the remainder in
781 * the first.
783 * @returns pValue1Result.
784 * @param pValue1Result The dividend value and result (remainder).
785 * @param pValue2 The divisor value.
787 DECLINLINE(PRTUINT128U) RTUInt128AssignMod(PRTUINT128U pValue1Result, PCRTUINT128U pValue2)
789 RTUINT128U Ignored;
790 RTUINT128U Result;
791 RTUInt128DivRem(&Ignored, &Result, pValue1Result, pValue2);
792 *pValue1Result = Result;
793 return pValue1Result;
798 * Performs a bitwise AND of two 128-bit unsigned integer values and assigned
799 * the result to the first one.
801 * @returns pValue1Result.
802 * @param pValue1Result The first value and result.
803 * @param pValue2 The second value.
805 DECLINLINE(PRTUINT128U) RTUInt128AssignAnd(PRTUINT128U pValue1Result, PCRTUINT128U pValue2)
807 #if ARCH_BITS >= 64
808 pValue1Result->s.Hi &= pValue2->s.Hi;
809 pValue1Result->s.Lo &= pValue2->s.Lo;
810 #else
811 pValue1Result->DWords.dw0 &= pValue2->DWords.dw0;
812 pValue1Result->DWords.dw1 &= pValue2->DWords.dw1;
813 pValue1Result->DWords.dw2 &= pValue2->DWords.dw2;
814 pValue1Result->DWords.dw3 &= pValue2->DWords.dw3;
815 #endif
816 return pValue1Result;
821 * Performs a bitwise AND of a 128-bit unsigned integer value and a mask made
822 * up of the first N bits, assigning the result to the the 128-bit value.
824 * @returns pValueResult.
825 * @param pValueResult The value and result.
826 * @param cBits The number of bits to AND (counting from the first
827 * bit).
829 DECLINLINE(PRTUINT128U) RTUInt128AssignAndNFirstBits(PRTUINT128U pValueResult, unsigned cBits)
831 if (cBits <= 64)
833 if (cBits != 64)
834 pValueResult->s.Lo &= (RT_BIT_64(cBits) - 1);
835 pValueResult->s.Hi = 0;
837 else if (cBits < 128)
838 pValueResult->s.Hi &= (RT_BIT_64(cBits - 64) - 1);
839 /** @todo \#if ARCH_BITS >= 64 */
840 return pValueResult;
845 * Performs a bitwise OR of two 128-bit unsigned integer values and assigned
846 * the result to the first one.
848 * @returns pValue1Result.
849 * @param pValue1Result The first value and result.
850 * @param pValue2 The second value.
852 DECLINLINE(PRTUINT128U) RTUInt128AssignOr(PRTUINT128U pValue1Result, PCRTUINT128U pValue2)
854 #if ARCH_BITS >= 64
855 pValue1Result->s.Hi |= pValue2->s.Hi;
856 pValue1Result->s.Lo |= pValue2->s.Lo;
857 #else
858 pValue1Result->DWords.dw0 |= pValue2->DWords.dw0;
859 pValue1Result->DWords.dw1 |= pValue2->DWords.dw1;
860 pValue1Result->DWords.dw2 |= pValue2->DWords.dw2;
861 pValue1Result->DWords.dw3 |= pValue2->DWords.dw3;
862 #endif
863 return pValue1Result;
868 * ORs in a bit and assign the result to the input value.
870 * @returns pValue1Result.
871 * @param pValue1Result The first value and result.
872 * @param iBit The bit to set (0 based).
874 DECLINLINE(PRTUINT128U) RTUInt128AssignOrBit(PRTUINT128U pValue1Result, uint32_t iBit)
876 #if ARCH_BITS >= 64
877 if (iBit >= 64)
878 pValue1Result->s.Hi |= RT_BIT_64(iBit - 64);
879 else
880 pValue1Result->s.Lo |= RT_BIT_64(iBit);
881 #else
882 if (iBit >= 64)
884 if (iBit >= 96)
885 pValue1Result->DWords.dw3 |= RT_BIT_32(iBit - 96);
886 else
887 pValue1Result->DWords.dw2 |= RT_BIT_32(iBit - 64);
889 else
891 if (iBit >= 32)
892 pValue1Result->DWords.dw1 |= RT_BIT_32(iBit - 32);
893 else
894 pValue1Result->DWords.dw0 |= RT_BIT_32(iBit);
896 #endif
897 return pValue1Result;
903 * Performs a bitwise XOR of two 128-bit unsigned integer values and assigned
904 * the result to the first one.
906 * @returns pValue1Result.
907 * @param pValue1Result The first value and result.
908 * @param pValue2 The second value.
910 DECLINLINE(PRTUINT128U) RTUInt128AssignXor(PRTUINT128U pValue1Result, PCRTUINT128U pValue2)
912 #if ARCH_BITS >= 64
913 pValue1Result->s.Hi ^= pValue2->s.Hi;
914 pValue1Result->s.Lo ^= pValue2->s.Lo;
915 #else
916 pValue1Result->DWords.dw0 ^= pValue2->DWords.dw0;
917 pValue1Result->DWords.dw1 ^= pValue2->DWords.dw1;
918 pValue1Result->DWords.dw2 ^= pValue2->DWords.dw2;
919 pValue1Result->DWords.dw3 ^= pValue2->DWords.dw3;
920 #endif
921 return pValue1Result;
926 * Performs a bitwise left shift on a 128-bit unsigned integer value, assigning
927 * the result to it.
929 * @returns pValueResult.
930 * @param pValueResult The first value and result.
931 * @param cBits The number of bits to shift.
933 DECLINLINE(PRTUINT128U) RTUInt128AssignShiftLeft(PRTUINT128U pValueResult, int cBits)
935 RTUINT128U const InVal = *pValueResult;
936 /** @todo \#if ARCH_BITS >= 64 */
937 if (cBits > 0)
939 /* (left shift) */
940 if (cBits >= 128)
941 RTUInt128SetZero(pValueResult);
942 else if (cBits >= 64)
944 pValueResult->s.Lo = 0;
945 pValueResult->s.Hi = InVal.s.Lo << (cBits - 64);
947 else
949 pValueResult->s.Hi = InVal.s.Hi << cBits;
950 pValueResult->s.Hi |= InVal.s.Lo >> (64 - cBits);
951 pValueResult->s.Lo = InVal.s.Lo << cBits;
954 else if (cBits < 0)
956 /* (right shift) */
957 cBits = -cBits;
958 if (cBits >= 128)
959 RTUInt128SetZero(pValueResult);
960 else if (cBits >= 64)
962 pValueResult->s.Hi = 0;
963 pValueResult->s.Lo = InVal.s.Hi >> (cBits - 64);
965 else
967 pValueResult->s.Lo = InVal.s.Lo >> cBits;
968 pValueResult->s.Lo |= InVal.s.Hi << (64 - cBits);
969 pValueResult->s.Hi = InVal.s.Hi >> cBits;
972 return pValueResult;
977 * Performs a bitwise left shift on a 128-bit unsigned integer value, assigning
978 * the result to it.
980 * @returns pValueResult.
981 * @param pValueResult The first value and result.
982 * @param cBits The number of bits to shift.
984 DECLINLINE(PRTUINT128U) RTUInt128AssignShiftRight(PRTUINT128U pValueResult, int cBits)
986 return RTUInt128AssignShiftLeft(pValueResult, -cBits);
991 * Performs a bitwise NOT on a 128-bit unsigned integer value, assigning the
992 * result to it.
994 * @returns pValueResult
995 * @param pValueResult The value and result.
997 DECLINLINE(PRTUINT128U) RTUInt128AssignBitwiseNot(PRTUINT128U pValueResult)
999 #if ARCH_BITS >= 64
1000 pValueResult->s.Hi = ~pValueResult->s.Hi;
1001 pValueResult->s.Lo = ~pValueResult->s.Lo;
1002 #else
1003 pValueResult->DWords.dw0 = ~pValueResult->DWords.dw0;
1004 pValueResult->DWords.dw1 = ~pValueResult->DWords.dw1;
1005 pValueResult->DWords.dw2 = ~pValueResult->DWords.dw2;
1006 pValueResult->DWords.dw3 = ~pValueResult->DWords.dw3;
1007 #endif
1008 return pValueResult;
1013 * Performs a boolean NOT on a 128-bit unsigned integer value, assigning the
1014 * result to it.
1016 * @returns pValueResult
1017 * @param pValueResult The value and result.
1019 DECLINLINE(PRTUINT128U) RTUInt128AssignBooleanNot(PRTUINT128U pValueResult)
1021 return RTUInt128AssignBoolean(pValueResult, RTUInt128IsZero(pValueResult));
1026 * Compares two 128-bit unsigned integer values.
1028 * @retval 0 if equal.
1029 * @retval -1 if the first value is smaller than the second.
1030 * @retval 1 if the first value is larger than the second.
1032 * @param pValue1 The first value.
1033 * @param pValue2 The second value.
1035 DECLINLINE(int) RTUInt128Compare(PCRTUINT128U pValue1, PCRTUINT128U pValue2)
1037 #if ARCH_BITS >= 64
1038 if (pValue1->s.Hi != pValue2->s.Hi)
1039 return pValue1->s.Hi > pValue2->s.Hi ? 1 : -1;
1040 if (pValue1->s.Lo != pValue2->s.Lo)
1041 return pValue1->s.Lo > pValue2->s.Lo ? 1 : -1;
1042 return 0;
1043 #else
1044 if (pValue1->DWords.dw3 != pValue2->DWords.dw3)
1045 return pValue1->DWords.dw3 > pValue2->DWords.dw3 ? 1 : -1;
1046 if (pValue1->DWords.dw2 != pValue2->DWords.dw2)
1047 return pValue1->DWords.dw2 > pValue2->DWords.dw2 ? 1 : -1;
1048 if (pValue1->DWords.dw1 != pValue2->DWords.dw1)
1049 return pValue1->DWords.dw1 > pValue2->DWords.dw1 ? 1 : -1;
1050 if (pValue1->DWords.dw0 != pValue2->DWords.dw0)
1051 return pValue1->DWords.dw0 > pValue2->DWords.dw0 ? 1 : -1;
1052 return 0;
1053 #endif
1058 * Tests if a 128-bit unsigned integer value is smaller than another.
1060 * @returns true if the first value is smaller, false if not.
1061 * @param pValue1 The first value.
1062 * @param pValue2 The second value.
1064 DECLINLINE(bool) RTUInt128IsSmaller(PCRTUINT128U pValue1, PCRTUINT128U pValue2)
1066 #if ARCH_BITS >= 64
1067 return pValue1->s.Hi < pValue2->s.Hi
1068 || ( pValue1->s.Hi == pValue2->s.Hi
1069 && pValue1->s.Lo < pValue2->s.Lo);
1070 #else
1071 return pValue1->DWords.dw3 < pValue2->DWords.dw3
1072 || ( pValue1->DWords.dw3 == pValue2->DWords.dw3
1073 && ( pValue1->DWords.dw2 < pValue2->DWords.dw2
1074 || ( pValue1->DWords.dw2 == pValue2->DWords.dw2
1075 && ( pValue1->DWords.dw1 < pValue2->DWords.dw1
1076 || ( pValue1->DWords.dw1 == pValue2->DWords.dw1
1077 && pValue1->DWords.dw0 < pValue2->DWords.dw0)))));
1078 #endif
1083 * Tests if a 128-bit unsigned integer value is larger than another.
1085 * @returns true if the first value is larger, false if not.
1086 * @param pValue1 The first value.
1087 * @param pValue2 The second value.
1089 DECLINLINE(bool) RTUInt128IsLarger(PCRTUINT128U pValue1, PCRTUINT128U pValue2)
1091 #if ARCH_BITS >= 64
1092 return pValue1->s.Hi > pValue2->s.Hi
1093 || ( pValue1->s.Hi == pValue2->s.Hi
1094 && pValue1->s.Lo > pValue2->s.Lo);
1095 #else
1096 return pValue1->DWords.dw3 > pValue2->DWords.dw3
1097 || ( pValue1->DWords.dw3 == pValue2->DWords.dw3
1098 && ( pValue1->DWords.dw2 > pValue2->DWords.dw2
1099 || ( pValue1->DWords.dw2 == pValue2->DWords.dw2
1100 && ( pValue1->DWords.dw1 > pValue2->DWords.dw1
1101 || ( pValue1->DWords.dw1 == pValue2->DWords.dw1
1102 && pValue1->DWords.dw0 > pValue2->DWords.dw0)))));
1103 #endif
1108 * Tests if a 128-bit unsigned integer value is larger or equal than another.
1110 * @returns true if the first value is larger or equal, false if not.
1111 * @param pValue1 The first value.
1112 * @param pValue2 The second value.
1114 DECLINLINE(bool) RTUInt128IsLargerOrEqual(PCRTUINT128U pValue1, PCRTUINT128U pValue2)
1116 #if ARCH_BITS >= 64
1117 return pValue1->s.Hi > pValue2->s.Hi
1118 || ( pValue1->s.Hi == pValue2->s.Hi
1119 && pValue1->s.Lo >= pValue2->s.Lo);
1120 #else
1121 return pValue1->DWords.dw3 > pValue2->DWords.dw3
1122 || ( pValue1->DWords.dw3 == pValue2->DWords.dw3
1123 && ( pValue1->DWords.dw2 > pValue2->DWords.dw2
1124 || ( pValue1->DWords.dw2 == pValue2->DWords.dw2
1125 && ( pValue1->DWords.dw1 > pValue2->DWords.dw1
1126 || ( pValue1->DWords.dw1 == pValue2->DWords.dw1
1127 && pValue1->DWords.dw0 >= pValue2->DWords.dw0)))));
1128 #endif
1133 * Tests if two 128-bit unsigned integer values not equal.
1135 * @returns true if equal, false if not equal.
1136 * @param pValue1 The first value.
1137 * @param pValue2 The second value.
1139 DECLINLINE(bool) RTUInt128IsEqual(PCRTUINT128U pValue1, PCRTUINT128U pValue2)
1141 #if ARCH_BITS >= 64
1142 return pValue1->s.Hi == pValue2->s.Hi
1143 && pValue1->s.Lo == pValue2->s.Lo;
1144 #else
1145 return pValue1->DWords.dw0 == pValue2->DWords.dw0
1146 && pValue1->DWords.dw1 == pValue2->DWords.dw1
1147 && pValue1->DWords.dw2 == pValue2->DWords.dw2
1148 && pValue1->DWords.dw3 == pValue2->DWords.dw3;
1149 #endif
1154 * Tests if two 128-bit unsigned integer values are not equal.
1156 * @returns true if not equal, false if equal.
1157 * @param pValue1 The first value.
1158 * @param pValue2 The second value.
1160 DECLINLINE(bool) RTUInt128IsNotEqual(PCRTUINT128U pValue1, PCRTUINT128U pValue2)
1162 return !RTUInt128IsEqual(pValue1, pValue2);
1167 * Sets a bit in a 128-bit unsigned integer type.
1169 * @returns pValueResult.
1170 * @param pValueResult The input and output value.
1171 * @param iBit The bit to set.
1173 DECLINLINE(PRTUINT128U) RTUInt128BitSet(PRTUINT128U pValueResult, unsigned iBit)
1175 if (iBit < 64)
1177 #if ARCH_BITS >= 64
1178 pValueResult->s.Lo |= RT_BIT_64(iBit);
1179 #else
1180 if (iBit < 32)
1181 pValueResult->DWords.dw0 |= RT_BIT_32(iBit);
1182 else
1183 pValueResult->DWords.dw1 |= RT_BIT_32(iBit - 32);
1184 #endif
1186 else if (iBit < 128)
1188 #if ARCH_BITS >= 64
1189 pValueResult->s.Hi |= RT_BIT_64(iBit - 64);
1190 #else
1191 if (iBit < 96)
1192 pValueResult->DWords.dw2 |= RT_BIT_32(iBit - 64);
1193 else
1194 pValueResult->DWords.dw3 |= RT_BIT_32(iBit - 96);
1195 #endif
1197 return pValueResult;
1202 * Sets a bit in a 128-bit unsigned integer type.
1204 * @returns pValueResult.
1205 * @param pValueResult The input and output value.
1206 * @param iBit The bit to set.
1208 DECLINLINE(PRTUINT128U) RTUInt128BitClear(PRTUINT128U pValueResult, unsigned iBit)
1210 if (iBit < 64)
1212 #if ARCH_BITS >= 64
1213 pValueResult->s.Lo &= ~RT_BIT_64(iBit);
1214 #else
1215 if (iBit < 32)
1216 pValueResult->DWords.dw0 &= ~RT_BIT_32(iBit);
1217 else
1218 pValueResult->DWords.dw1 &= ~RT_BIT_32(iBit - 32);
1219 #endif
1221 else if (iBit < 128)
1223 #if ARCH_BITS >= 64
1224 pValueResult->s.Hi &= ~RT_BIT_64(iBit - 64);
1225 #else
1226 if (iBit < 96)
1227 pValueResult->DWords.dw2 &= ~RT_BIT_32(iBit - 64);
1228 else
1229 pValueResult->DWords.dw3 &= ~RT_BIT_32(iBit - 96);
1230 #endif
1232 return pValueResult;
1237 * Tests if a bit in a 128-bit unsigned integer value is set.
1239 * @returns pValueResult.
1240 * @param pValueResult The input and output value.
1241 * @param iBit The bit to test.
1243 DECLINLINE(bool) RTUInt128BitTest(PRTUINT128U pValueResult, unsigned iBit)
1245 bool fRc;
1246 if (iBit < 64)
1248 #if ARCH_BITS >= 64
1249 fRc = RT_BOOL(pValueResult->s.Lo & RT_BIT_64(iBit));
1250 #else
1251 if (iBit < 32)
1252 fRc = RT_BOOL(pValueResult->DWords.dw0 & RT_BIT_32(iBit));
1253 else
1254 fRc = RT_BOOL(pValueResult->DWords.dw1 & RT_BIT_32(iBit - 32));
1255 #endif
1257 else if (iBit < 128)
1259 #if ARCH_BITS >= 64
1260 fRc = RT_BOOL(pValueResult->s.Hi & RT_BIT_64(iBit - 64));
1261 #else
1262 if (iBit < 96)
1263 fRc = RT_BOOL(pValueResult->DWords.dw2 & RT_BIT_32(iBit - 64));
1264 else
1265 fRc = RT_BOOL(pValueResult->DWords.dw3 & RT_BIT_32(iBit - 96));
1266 #endif
1268 else
1269 fRc = false;
1270 return fRc;
1275 * Set a range of bits a 128-bit unsigned integer value.
1277 * @returns pValueResult.
1278 * @param pValueResult The input and output value.
1279 * @param iFirstBit The first bit to test.
1280 * @param cBits The number of bits to set.
1282 DECLINLINE(PRTUINT128U) RTUInt128BitSetRange(PRTUINT128U pValueResult, unsigned iFirstBit, unsigned cBits)
1284 /* bounds check & fix. */
1285 if (iFirstBit < 128)
1287 if (iFirstBit + cBits > 128)
1288 cBits = 128 - iFirstBit;
1290 #if ARCH_BITS >= 64
1291 if (iFirstBit + cBits < 64)
1292 pValueResult->s.Lo |= (RT_BIT_64(cBits) - 1) << iFirstBit;
1293 else if (iFirstBit + cBits < 128 && iFirstBit >= 64)
1294 pValueResult->s.Hi |= (RT_BIT_64(cBits) - 1) << (iFirstBit - 64);
1295 else
1296 #else
1297 if (iFirstBit + cBits < 32)
1298 pValueResult->DWords.dw0 |= (RT_BIT_32(cBits) - 1) << iFirstBit;
1299 else if (iFirstBit + cBits < 64 && iFirstBit >= 32)
1300 pValueResult->DWords.dw1 |= (RT_BIT_32(cBits) - 1) << (iFirstBit - 32);
1301 else if (iFirstBit + cBits < 96 && iFirstBit >= 64)
1302 pValueResult->DWords.dw2 |= (RT_BIT_32(cBits) - 1) << (iFirstBit - 64);
1303 else if (iFirstBit + cBits < 128 && iFirstBit >= 96)
1304 pValueResult->DWords.dw3 |= (RT_BIT_32(cBits) - 1) << (iFirstBit - 96);
1305 else
1306 #endif
1307 while (cBits-- > 0)
1308 RTUInt128BitSet(pValueResult, iFirstBit++);
1310 return pValueResult;
1315 * Test if all the bits of a 128-bit unsigned integer value are set.
1317 * @returns true if they are, false if they aren't.
1318 * @param pValue The input and output value.
1320 DECLINLINE(bool) RTUInt128BitAreAllSet(PRTUINT128U pValue)
1322 #if ARCH_BITS >= 64
1323 return pValue->s.Hi == UINT64_MAX
1324 && pValue->s.Lo == UINT64_MAX;
1325 #else
1326 return pValue->DWords.dw0 == UINT32_MAX
1327 && pValue->DWords.dw1 == UINT32_MAX
1328 && pValue->DWords.dw2 == UINT32_MAX
1329 && pValue->DWords.dw3 == UINT32_MAX;
1330 #endif
1335 * Test if all the bits of a 128-bit unsigned integer value are clear.
1337 * @returns true if they are, false if they aren't.
1338 * @param pValue The input and output value.
1340 DECLINLINE(bool) RTUInt128BitAreAllClear(PRTUINT128U pValue)
1342 #if ARCH_BITS >= 64
1343 return pValue->s.Hi == 0
1344 && pValue->s.Lo == 0;
1345 #else
1346 return pValue->DWords.dw0 == 0
1347 && pValue->DWords.dw1 == 0
1348 && pValue->DWords.dw2 == 0
1349 && pValue->DWords.dw3 == 0;
1350 #endif
1355 * Number of significant bits in the value.
1357 * This is the same a ASMBitLastSetU64 and ASMBitLastSetU32.
1359 * @returns 0 if zero, 1-base index of the last bit set.
1360 * @param pValue The value to examine.
1362 DECLINLINE(uint32_t) RTUInt128BitCount(PCRTUINT128U pValue)
1364 uint32_t cBits;
1365 if (pValue->s.Hi != 0)
1367 if (pValue->DWords.dw3)
1368 cBits = 96 + ASMBitLastSetU32(pValue->DWords.dw3);
1369 else
1370 cBits = 64 + ASMBitLastSetU32(pValue->DWords.dw2);
1372 else
1374 if (pValue->DWords.dw1)
1375 cBits = 32 + ASMBitLastSetU32(pValue->DWords.dw1);
1376 else
1377 cBits = 0 + ASMBitLastSetU32(pValue->DWords.dw0);
1379 return cBits;
1384 * Divides a 128-bit unsigned integer value by another, returning both quotient
1385 * and remainder.
1387 * @returns pQuotient, NULL if pValue2 is 0.
1388 * @param pQuotient Where to return the quotient.
1389 * @param pRemainder Where to return the remainder.
1390 * @param pValue1 The dividend value.
1391 * @param pValue2 The divisor value.
1393 DECLINLINE(PRTUINT128U) RTUInt128DivRem(PRTUINT128U pQuotient, PRTUINT128U pRemainder, PCRTUINT128U pValue1, PCRTUINT128U pValue2)
1395 int iDiff;
1398 * Sort out all the special cases first.
1400 /* Divide by zero or 1? */
1401 if (!pValue2->s.Hi)
1403 if (!pValue2->s.Lo)
1405 RTUInt128SetZero(pRemainder);
1406 RTUInt128SetZero(pQuotient);
1407 return NULL;
1410 if (pValue2->s.Lo == 1)
1412 RTUInt128SetZero(pRemainder);
1413 *pQuotient = *pValue1;
1414 return pQuotient;
1416 /** @todo RTUint128DivModBy64 */
1419 /* Dividend is smaller? */
1420 iDiff = RTUInt128Compare(pValue1, pValue2);
1421 if (iDiff < 0)
1423 *pRemainder = *pValue1;
1424 RTUInt128SetZero(pQuotient);
1427 /* The values are equal? */
1428 else if (iDiff == 0)
1430 RTUInt128SetZero(pRemainder);
1431 RTUInt128AssignU64(pQuotient, 1);
1433 else
1436 * Prepare.
1438 uint32_t iBitAdder = RTUInt128BitCount(pValue1) - RTUInt128BitCount(pValue2);
1439 RTUINT128U NormDivisor = *pValue2;
1440 if (iBitAdder)
1442 RTUInt128ShiftLeft(&NormDivisor, pValue2, iBitAdder);
1443 if (RTUInt128IsLarger(&NormDivisor, pValue1))
1445 RTUInt128AssignShiftRight(&NormDivisor, 1);
1446 iBitAdder--;
1449 else
1450 NormDivisor = *pValue2;
1452 RTUInt128SetZero(pQuotient);
1453 *pRemainder = *pValue1;
1456 * Do the division.
1458 if (RTUInt128IsLargerOrEqual(pRemainder, pValue2))
1460 for (;;)
1462 if (RTUInt128IsLargerOrEqual(pRemainder, &NormDivisor))
1464 RTUInt128AssignSub(pRemainder, &NormDivisor);
1465 RTUInt128AssignOrBit(pQuotient, iBitAdder);
1467 if (RTUInt128IsSmaller(pRemainder, pValue2))
1468 break;
1469 RTUInt128AssignShiftRight(&NormDivisor, 1);
1470 iBitAdder--;
1474 return pQuotient;
1478 /** @} */
1480 RT_C_DECLS_END
1482 #endif /* !IPRT_INCLUDED_uint128_h */