2 * IPRT - RTUINT128U & uint128_t methods.
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
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
42 #include <iprt/cdefs.h>
43 #include <iprt/types.h>
45 #include <iprt/asm-math.h>
49 /** @defgroup grp_rt_uint128 RTUInt128 - 128-bit Unsigned Integer Methods
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
)
64 return pValue
->s
.Hi
== 0
67 return pValue
->DWords
.dw0
== 0
68 && pValue
->DWords
.dw1
== 0
69 && pValue
->DWords
.dw2
== 0
70 && pValue
->DWords
.dw3
== 0;
76 * Set a 128-bit unsigned integer value to zero.
79 * @param pResult The result variable.
81 DECLINLINE(PRTUINT128U
) RTUInt128SetZero(PRTUINT128U pResult
)
87 pResult
->DWords
.dw0
= 0;
88 pResult
->DWords
.dw1
= 0;
89 pResult
->DWords
.dw2
= 0;
90 pResult
->DWords
.dw3
= 0;
97 * Set a 128-bit unsigned integer value to the maximum value.
100 * @param pResult The result variable.
102 DECLINLINE(PRTUINT128U
) RTUInt128SetMax(PRTUINT128U pResult
)
105 pResult
->s
.Hi
= UINT64_MAX
;
106 pResult
->s
.Lo
= UINT64_MAX
;
108 pResult
->DWords
.dw0
= UINT32_MAX
;
109 pResult
->DWords
.dw1
= UINT32_MAX
;
110 pResult
->DWords
.dw2
= UINT32_MAX
;
111 pResult
->DWords
.dw3
= UINT32_MAX
;
120 * Adds two 128-bit unsigned integer values.
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
)
138 * Adds a 128-bit and a 64-bit unsigned integer values.
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
)
156 * Subtracts a 128-bit unsigned integer value from another.
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
)
174 * Multiplies two 128-bit unsigned integer values.
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
)
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
;
225 * Multiplies an 128-bit unsigned integer by a 64-bit unsigned integer value.
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
);
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);
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
;
275 * Multiplies two 64-bit unsigned integer values with 128-bit precision.
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
)
285 pResult
->s
.Lo
= ASMMult2xU64Ret2xU64(uValue1
, uValue2
, &pResult
->s
.Hi
);
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);
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
;
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).
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
);
333 DECLINLINE(PRTUINT256U
) RTUInt128MulByU64Ex(PRTUINT256U pResult
, PCRTUINT128U pValue1
, uint64_t uValue2
)
335 /* multiply the two qwords in pValue1 by uValue2. */
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 */
350 * Multiplies two 128-bit unsigned integer values, returning a 256-bit result.
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
);
362 /* Multiply the two qwords in pValue1 by the high part of uValue2. */
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
;
384 DECLINLINE(PRTUINT128U
) RTUInt128DivRem(PRTUINT128U pQuotient
, PRTUINT128U pRemainder
, PCRTUINT128U pValue1
, PCRTUINT128U pValue2
);
387 * Divides a 128-bit unsigned integer value by another.
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
)
397 return RTUInt128DivRem(pResult
, &Ignored
, pValue1
, pValue2
);
402 * Divides a 128-bit unsigned integer value by another, returning the remainder.
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
)
412 RTUInt128DivRem(&Ignored
, pResult
, pValue1
, pValue2
);
418 * Bitwise AND of two 128-bit unsigned integer values.
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
;
434 * Bitwise OR of two 128-bit unsigned integer values.
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
;
450 * Bitwise XOR of two 128-bit unsigned integer values.
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
;
466 * Shifts a 128-bit unsigned integer value @a cBits to the left.
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
)
478 pResult
->s
.Lo
= pValue
->s
.Lo
<< cBits
;
479 pResult
->s
.Hi
= (pValue
->s
.Hi
<< cBits
) | (pValue
->s
.Lo
>> (64 - cBits
));
484 pResult
->s
.Hi
= pValue
->s
.Lo
<< (cBits
- 64);
491 * Shifts a 128-bit unsigned integer value @a cBits to the right.
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
)
503 pResult
->s
.Hi
= pValue
->s
.Hi
>> cBits
;
504 pResult
->s
.Lo
= (pValue
->s
.Lo
>> cBits
) | (pValue
->s
.Hi
<< (64 - cBits
));
509 pResult
->s
.Lo
= pValue
->s
.Hi
>> (cBits
- 64);
516 * Boolean not (result 0 or 1).
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;
531 * Bitwise not (flips each bit of the 128 bits).
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
;
546 * Assigns one 128-bit unsigned integer value to another.
549 * @param pResult The result variable.
550 * @param pValue The value to assign.
552 DECLINLINE(PRTUINT128U
) RTUInt128Assign(PRTUINT128U pResult
, PCRTUINT128U pValue
)
555 pResult
->s
.Hi
= pValue
->s
.Hi
;
556 pResult
->s
.Lo
= pValue
->s
.Lo
;
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
;
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
)
577 pValueResult
->s
.Lo
= fValue
;
578 pValueResult
->s
.Hi
= 0;
580 pValueResult
->DWords
.dw0
= fValue
;
581 pValueResult
->DWords
.dw1
= 0;
582 pValueResult
->DWords
.dw2
= 0;
583 pValueResult
->DWords
.dw3
= 0;
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
)
599 pValueResult
->s
.Lo
= u8Value
;
600 pValueResult
->s
.Hi
= 0;
602 pValueResult
->DWords
.dw0
= u8Value
;
603 pValueResult
->DWords
.dw1
= 0;
604 pValueResult
->DWords
.dw2
= 0;
605 pValueResult
->DWords
.dw3
= 0;
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
)
621 pValueResult
->s
.Lo
= u16Value
;
622 pValueResult
->s
.Hi
= 0;
624 pValueResult
->DWords
.dw0
= u16Value
;
625 pValueResult
->DWords
.dw1
= 0;
626 pValueResult
->DWords
.dw2
= 0;
627 pValueResult
->DWords
.dw3
= 0;
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
)
643 pValueResult
->s
.Lo
= u32Value
;
644 pValueResult
->s
.Hi
= 0;
646 pValueResult
->DWords
.dw0
= u32Value
;
647 pValueResult
->DWords
.dw1
= 0;
648 pValueResult
->DWords
.dw2
= 0;
649 pValueResult
->DWords
.dw3
= 0;
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;
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
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
;
739 pValueResult
->s
.Hi
= UINT64_C(0) - pValueResult
->s
.Hi
;
745 * Multiplies two 128-bit unsigned integer values, storing the result in the
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
)
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
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
)
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
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
)
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
)
808 pValue1Result
->s
.Hi
&= pValue2
->s
.Hi
;
809 pValue1Result
->s
.Lo
&= pValue2
->s
.Lo
;
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
;
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
829 DECLINLINE(PRTUINT128U
) RTUInt128AssignAndNFirstBits(PRTUINT128U pValueResult
, unsigned cBits
)
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 */
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
)
855 pValue1Result
->s
.Hi
|= pValue2
->s
.Hi
;
856 pValue1Result
->s
.Lo
|= pValue2
->s
.Lo
;
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
;
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
)
878 pValue1Result
->s
.Hi
|= RT_BIT_64(iBit
- 64);
880 pValue1Result
->s
.Lo
|= RT_BIT_64(iBit
);
885 pValue1Result
->DWords
.dw3
|= RT_BIT_32(iBit
- 96);
887 pValue1Result
->DWords
.dw2
|= RT_BIT_32(iBit
- 64);
892 pValue1Result
->DWords
.dw1
|= RT_BIT_32(iBit
- 32);
894 pValue1Result
->DWords
.dw0
|= RT_BIT_32(iBit
);
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
)
913 pValue1Result
->s
.Hi
^= pValue2
->s
.Hi
;
914 pValue1Result
->s
.Lo
^= pValue2
->s
.Lo
;
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
;
921 return pValue1Result
;
926 * Performs a bitwise left shift on a 128-bit unsigned integer value, assigning
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 */
941 RTUInt128SetZero(pValueResult
);
942 else if (cBits
>= 64)
944 pValueResult
->s
.Lo
= 0;
945 pValueResult
->s
.Hi
= InVal
.s
.Lo
<< (cBits
- 64);
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
;
959 RTUInt128SetZero(pValueResult
);
960 else if (cBits
>= 64)
962 pValueResult
->s
.Hi
= 0;
963 pValueResult
->s
.Lo
= InVal
.s
.Hi
>> (cBits
- 64);
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
;
977 * Performs a bitwise left shift on a 128-bit unsigned integer value, assigning
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
994 * @returns pValueResult
995 * @param pValueResult The value and result.
997 DECLINLINE(PRTUINT128U
) RTUInt128AssignBitwiseNot(PRTUINT128U pValueResult
)
1000 pValueResult
->s
.Hi
= ~pValueResult
->s
.Hi
;
1001 pValueResult
->s
.Lo
= ~pValueResult
->s
.Lo
;
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
;
1008 return pValueResult
;
1013 * Performs a boolean NOT on a 128-bit unsigned integer value, assigning the
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
)
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;
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;
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
)
1067 return pValue1
->s
.Hi
< pValue2
->s
.Hi
1068 || ( pValue1
->s
.Hi
== pValue2
->s
.Hi
1069 && pValue1
->s
.Lo
< pValue2
->s
.Lo
);
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
)))));
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
)
1092 return pValue1
->s
.Hi
> pValue2
->s
.Hi
1093 || ( pValue1
->s
.Hi
== pValue2
->s
.Hi
1094 && pValue1
->s
.Lo
> pValue2
->s
.Lo
);
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
)))));
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
)
1117 return pValue1
->s
.Hi
> pValue2
->s
.Hi
1118 || ( pValue1
->s
.Hi
== pValue2
->s
.Hi
1119 && pValue1
->s
.Lo
>= pValue2
->s
.Lo
);
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
)))));
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
)
1142 return pValue1
->s
.Hi
== pValue2
->s
.Hi
1143 && pValue1
->s
.Lo
== pValue2
->s
.Lo
;
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
;
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
)
1178 pValueResult
->s
.Lo
|= RT_BIT_64(iBit
);
1181 pValueResult
->DWords
.dw0
|= RT_BIT_32(iBit
);
1183 pValueResult
->DWords
.dw1
|= RT_BIT_32(iBit
- 32);
1186 else if (iBit
< 128)
1189 pValueResult
->s
.Hi
|= RT_BIT_64(iBit
- 64);
1192 pValueResult
->DWords
.dw2
|= RT_BIT_32(iBit
- 64);
1194 pValueResult
->DWords
.dw3
|= RT_BIT_32(iBit
- 96);
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
)
1213 pValueResult
->s
.Lo
&= ~RT_BIT_64(iBit
);
1216 pValueResult
->DWords
.dw0
&= ~RT_BIT_32(iBit
);
1218 pValueResult
->DWords
.dw1
&= ~RT_BIT_32(iBit
- 32);
1221 else if (iBit
< 128)
1224 pValueResult
->s
.Hi
&= ~RT_BIT_64(iBit
- 64);
1227 pValueResult
->DWords
.dw2
&= ~RT_BIT_32(iBit
- 64);
1229 pValueResult
->DWords
.dw3
&= ~RT_BIT_32(iBit
- 96);
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
)
1249 fRc
= RT_BOOL(pValueResult
->s
.Lo
& RT_BIT_64(iBit
));
1252 fRc
= RT_BOOL(pValueResult
->DWords
.dw0
& RT_BIT_32(iBit
));
1254 fRc
= RT_BOOL(pValueResult
->DWords
.dw1
& RT_BIT_32(iBit
- 32));
1257 else if (iBit
< 128)
1260 fRc
= RT_BOOL(pValueResult
->s
.Hi
& RT_BIT_64(iBit
- 64));
1263 fRc
= RT_BOOL(pValueResult
->DWords
.dw2
& RT_BIT_32(iBit
- 64));
1265 fRc
= RT_BOOL(pValueResult
->DWords
.dw3
& RT_BIT_32(iBit
- 96));
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
;
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);
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);
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
)
1323 return pValue
->s
.Hi
== UINT64_MAX
1324 && pValue
->s
.Lo
== UINT64_MAX
;
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
;
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
)
1343 return pValue
->s
.Hi
== 0
1344 && pValue
->s
.Lo
== 0;
1346 return pValue
->DWords
.dw0
== 0
1347 && pValue
->DWords
.dw1
== 0
1348 && pValue
->DWords
.dw2
== 0
1349 && pValue
->DWords
.dw3
== 0;
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
)
1365 if (pValue
->s
.Hi
!= 0)
1367 if (pValue
->DWords
.dw3
)
1368 cBits
= 96 + ASMBitLastSetU32(pValue
->DWords
.dw3
);
1370 cBits
= 64 + ASMBitLastSetU32(pValue
->DWords
.dw2
);
1374 if (pValue
->DWords
.dw1
)
1375 cBits
= 32 + ASMBitLastSetU32(pValue
->DWords
.dw1
);
1377 cBits
= 0 + ASMBitLastSetU32(pValue
->DWords
.dw0
);
1384 * Divides a 128-bit unsigned integer value by another, returning both quotient
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
)
1398 * Sort out all the special cases first.
1400 /* Divide by zero or 1? */
1405 RTUInt128SetZero(pRemainder
);
1406 RTUInt128SetZero(pQuotient
);
1410 if (pValue2
->s
.Lo
== 1)
1412 RTUInt128SetZero(pRemainder
);
1413 *pQuotient
= *pValue1
;
1416 /** @todo RTUint128DivModBy64 */
1419 /* Dividend is smaller? */
1420 iDiff
= RTUInt128Compare(pValue1
, pValue2
);
1423 *pRemainder
= *pValue1
;
1424 RTUInt128SetZero(pQuotient
);
1427 /* The values are equal? */
1428 else if (iDiff
== 0)
1430 RTUInt128SetZero(pRemainder
);
1431 RTUInt128AssignU64(pQuotient
, 1);
1438 uint32_t iBitAdder
= RTUInt128BitCount(pValue1
) - RTUInt128BitCount(pValue2
);
1439 RTUINT128U NormDivisor
= *pValue2
;
1442 RTUInt128ShiftLeft(&NormDivisor
, pValue2
, iBitAdder
);
1443 if (RTUInt128IsLarger(&NormDivisor
, pValue1
))
1445 RTUInt128AssignShiftRight(&NormDivisor
, 1);
1450 NormDivisor
= *pValue2
;
1452 RTUInt128SetZero(pQuotient
);
1453 *pRemainder
= *pValue1
;
1458 if (RTUInt128IsLargerOrEqual(pRemainder
, pValue2
))
1462 if (RTUInt128IsLargerOrEqual(pRemainder
, &NormDivisor
))
1464 RTUInt128AssignSub(pRemainder
, &NormDivisor
);
1465 RTUInt128AssignOrBit(pQuotient
, iBitAdder
);
1467 if (RTUInt128IsSmaller(pRemainder
, pValue2
))
1469 RTUInt128AssignShiftRight(&NormDivisor
, 1);
1482 #endif /* !IPRT_INCLUDED_uint128_h */