2 * IPRT - RTUINT64U methods for old 32-bit and 16-bit compilers.
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_uint64_h
37 #define IPRT_INCLUDED_uint64_h
38 #ifndef RT_WITHOUT_PRAGMA_ONCE
42 #include <iprt/cdefs.h>
43 #include <iprt/types.h>
48 /** @defgroup grp_rt_uint64 RTUInt64 - 64-bit Unsigned Integer Methods for ancient compilers
55 * Test if a 128-bit unsigned integer value is zero.
57 * @returns true if they are, false if they aren't.
58 * @param pValue The value to examine.
60 DECLINLINE(bool) RTUInt64IsZero(PCRTUINT64U pValue
)
63 return pValue
->s
.Lo
== 0
66 return pValue
->Words
.w0
== 0
67 && pValue
->Words
.w1
== 0
68 && pValue
->Words
.w2
== 0
69 && pValue
->Words
.w3
== 0;
75 * Checks if the sign-bit is set.
78 * @param pValue The value to examine.
80 DECLINLINE(bool) RTUInt64IsSigned(PCRTUINT64U pValue
)
83 return RT_BOOL(pValue
->DWords
.dw1
& RT_BIT_32(31));
85 return RT_BOOL(pValue
->Words
.w3
& ((uint16_t)1 << 15));
91 * Set a 128-bit unsigned integer value to zero.
94 * @param pResult The result variable.
96 DECLINLINE(PRTUINT64U
) RTUInt64SetZero(PRTUINT64U pResult
)
102 pResult
->Words
.w0
= 0;
103 pResult
->Words
.w1
= 0;
104 pResult
->Words
.w2
= 0;
105 pResult
->Words
.w3
= 0;
112 * Set a 32-bit unsigned integer value to the maximum value.
115 * @param pResult The result variable.
117 DECLINLINE(PRTUINT64U
) RTUInt64SetMax(PRTUINT64U pResult
)
120 pResult
->s
.Hi
= UINT32_MAX
;
121 pResult
->s
.Lo
= UINT32_MAX
;
123 pResult
->Words
.w0
= UINT16_MAX
;
124 pResult
->Words
.w1
= UINT16_MAX
;
125 pResult
->Words
.w2
= UINT16_MAX
;
126 pResult
->Words
.w3
= UINT16_MAX
;
135 * Adds two 64-bit unsigned integer values.
138 * @param pResult The result variable.
139 * @param pValue1 The first value.
140 * @param pValue2 The second value.
142 DECLINLINE(PRTUINT64U
) RTUInt64Add(PRTUINT64U pResult
, PCRTUINT64U pValue1
, PCRTUINT64U pValue2
)
144 pResult
->s
.Hi
= pValue1
->s
.Hi
+ pValue2
->s
.Hi
;
145 pResult
->s
.Lo
= pValue1
->s
.Lo
+ pValue2
->s
.Lo
;
146 if (pResult
->s
.Lo
< pValue1
->s
.Lo
)
153 * Adds a 64-bit and a 32-bit unsigned integer values.
156 * @param pResult The result variable.
157 * @param pValue1 The first value.
158 * @param uValue2 The second value, 32-bit.
160 DECLINLINE(PRTUINT64U
) RTUInt64AddU32(PRTUINT64U pResult
, PCRTUINT64U pValue1
, uint32_t uValue2
)
162 pResult
->s
.Hi
= pValue1
->s
.Hi
;
163 pResult
->s
.Lo
= pValue1
->s
.Lo
+ uValue2
;
164 if (pResult
->s
.Lo
< pValue1
->s
.Lo
)
171 * Subtracts a 64-bit unsigned integer value from another.
174 * @param pResult The result variable.
175 * @param pValue1 The minuend value.
176 * @param pValue2 The subtrahend value.
178 DECLINLINE(PRTUINT64U
) RTUInt64Sub(PRTUINT64U pResult
, PCRTUINT64U pValue1
, PCRTUINT64U pValue2
)
180 pResult
->s
.Lo
= pValue1
->s
.Lo
- pValue2
->s
.Lo
;
181 pResult
->s
.Hi
= pValue1
->s
.Hi
- pValue2
->s
.Hi
;
182 if (pResult
->s
.Lo
> pValue1
->s
.Lo
)
189 * Calculates the negated number (special case of subtraction)
192 * @param pResult The result variable.
193 * @param pValue The value to negate.
195 DECLINLINE(PRTUINT64U
) RTUInt64Neg(PRTUINT64U pResult
, PCRTUINT64U pValue
)
197 pResult
->s
.Lo
= UINT32_C(0) - pValue
->s
.Lo
;
198 pResult
->s
.Hi
= UINT32_C(0) - pValue
->s
.Hi
;
199 if (pResult
->s
.Lo
> UINT32_C(0))
206 * Multiplies two 64-bit unsigned integer values.
209 * @param pResult The result variable.
210 * @param pValue1 The first value.
211 * @param pValue2 The second value.
213 DECLINLINE(PRTUINT64U
) RTUInt64Mul(PRTUINT64U pResult
, PCRTUINT64U pValue1
, PCRTUINT64U pValue2
)
217 /* multiply all words in v1 by v2.w0. */
218 pResult
->s
.Lo
= (uint32_t)pValue1
->Words
.w0
* pValue2
->Words
.w0
;
220 uTmp
.u
= (uint32_t)pValue1
->Words
.w1
* pValue2
->Words
.w0
;
221 pResult
->Words
.w3
= 0;
222 pResult
->Words
.w2
= uTmp
.Words
.w1
;
223 pResult
->Words
.w1
+= uTmp
.Words
.w0
;
224 if (pResult
->Words
.w1
< uTmp
.Words
.w0
)
225 if (pResult
->Words
.w2
++ == UINT16_MAX
)
228 pResult
->s
.Hi
+= (uint32_t)pValue1
->Words
.w2
* pValue2
->Words
.w0
;
229 pResult
->Words
.w3
+= pValue1
->Words
.w3
* pValue2
->Words
.w0
;
231 /* multiply w0, w1 & w2 in v1 by v2.w1. */
232 uTmp
.u
= (uint32_t)pValue1
->Words
.w0
* pValue2
->Words
.w1
;
233 pResult
->Words
.w1
+= uTmp
.Words
.w0
;
234 if (pResult
->Words
.w1
< uTmp
.Words
.w0
)
235 if (pResult
->Words
.w2
++ == UINT16_MAX
)
238 pResult
->Words
.w2
+= uTmp
.Words
.w1
;
239 if (pResult
->Words
.w2
< uTmp
.Words
.w1
)
242 pResult
->s
.Hi
+= (uint32_t)pValue1
->Words
.w1
* pValue2
->Words
.w1
;
243 pResult
->Words
.w3
+= pValue1
->Words
.w2
* pValue2
->Words
.w1
;
245 /* multiply w0 & w1 in v1 by v2.w2. */
246 pResult
->s
.Hi
+= (uint32_t)pValue1
->Words
.w0
* pValue2
->Words
.w2
;
247 pResult
->Words
.w3
+= pValue1
->Words
.w1
* pValue2
->Words
.w2
;
249 /* multiply w0 in v1 by v2.w3. */
250 pResult
->Words
.w3
+= pValue1
->Words
.w0
* pValue2
->Words
.w3
;
257 * Multiplies an 64-bit unsigned integer by a 32-bit unsigned integer value.
260 * @param pResult The result variable.
261 * @param pValue1 The first value.
262 * @param uValue2 The second value, 32-bit.
264 DECLINLINE(PRTUINT64U
) RTUInt64MulByU32(PRTUINT64U pResult
, PCRTUINT64U pValue1
, uint32_t uValue2
)
266 uint16_t const uLoValue2
= (uint16_t)uValue2
;
267 uint16_t const uHiValue2
= (uint16_t)(uValue2
>> 16);
270 /* multiply all words in v1 by uLoValue1. */
271 pResult
->s
.Lo
= (uint32_t)pValue1
->Words
.w0
* uLoValue2
;
273 uTmp
.u
= (uint32_t)pValue1
->Words
.w1
* uLoValue2
;
274 pResult
->Words
.w3
= 0;
275 pResult
->Words
.w2
= uTmp
.Words
.w1
;
276 pResult
->Words
.w1
+= uTmp
.Words
.w0
;
277 if (pResult
->Words
.w1
< uTmp
.Words
.w0
)
278 if (pResult
->Words
.w2
++ == UINT16_MAX
)
281 pResult
->s
.Hi
+= (uint32_t)pValue1
->Words
.w2
* uLoValue2
;
282 pResult
->Words
.w3
+= pValue1
->Words
.w3
* uLoValue2
;
284 /* multiply w0, w1 & w2 in v1 by uHiValue2. */
285 uTmp
.u
= (uint32_t)pValue1
->Words
.w0
* uHiValue2
;
286 pResult
->Words
.w1
+= uTmp
.Words
.w0
;
287 if (pResult
->Words
.w1
< uTmp
.Words
.w0
)
288 if (pResult
->Words
.w2
++ == UINT16_MAX
)
291 pResult
->Words
.w2
+= uTmp
.Words
.w1
;
292 if (pResult
->Words
.w2
< uTmp
.Words
.w1
)
295 pResult
->s
.Hi
+= (uint32_t)pValue1
->Words
.w1
* uHiValue2
;
296 pResult
->Words
.w3
+= pValue1
->Words
.w2
* uHiValue2
;
303 * Multiplies two 32-bit unsigned integer values with 64-bit precision.
306 * @param pResult The result variable.
307 * @param uValue1 The first value. 32-bit.
308 * @param uValue2 The second value, 32-bit.
310 DECLINLINE(PRTUINT64U
) RTUInt64MulU32ByU32(PRTUINT64U pResult
, uint32_t uValue1
, uint32_t uValue2
)
312 uint16_t const uLoValue1
= (uint16_t)uValue1
;
313 uint16_t const uHiValue1
= (uint16_t)(uValue1
>> 16);
314 uint16_t const uLoValue2
= (uint16_t)uValue2
;
315 uint16_t const uHiValue2
= (uint16_t)(uValue2
>> 16);
318 /* Multiply uLoValue1 and uHiValue1 by uLoValue1. */
319 pResult
->s
.Lo
= (uint32_t)uLoValue1
* uLoValue2
;
321 uTmp
.u
= (uint32_t)uHiValue1
* uLoValue2
;
322 pResult
->Words
.w3
= 0;
323 pResult
->Words
.w2
= uTmp
.Words
.w1
;
324 pResult
->Words
.w1
+= uTmp
.Words
.w0
;
325 if (pResult
->Words
.w1
< uTmp
.Words
.w0
)
326 if (pResult
->Words
.w2
++ == UINT16_MAX
)
329 /* Multiply uLoValue1 and uHiValue1 by uHiValue2. */
330 uTmp
.u
= (uint32_t)uLoValue1
* uHiValue2
;
331 pResult
->Words
.w1
+= uTmp
.Words
.w0
;
332 if (pResult
->Words
.w1
< uTmp
.Words
.w0
)
333 if (pResult
->Words
.w2
++ == UINT16_MAX
)
336 pResult
->Words
.w2
+= uTmp
.Words
.w1
;
337 if (pResult
->Words
.w2
< uTmp
.Words
.w1
)
340 pResult
->s
.Hi
+= (uint32_t)uHiValue1
* uHiValue2
;
345 DECLINLINE(PRTUINT64U
) RTUInt64DivRem(PRTUINT64U pQuotient
, PRTUINT64U pRemainder
, PCRTUINT64U pValue1
, PCRTUINT64U pValue2
);
346 DECLINLINE(PRTUINT64U
) RTUInt64DivRemSigned(PRTUINT64U pQuotient
, PRTUINT64U pRemainder
, PCRTUINT64U pValue1
, PCRTUINT64U pValue2
);
349 * Divides a 64-bit unsigned integer value by another.
352 * @param pResult The result variable.
353 * @param pValue1 The dividend value.
354 * @param pValue2 The divisor value.
356 DECLINLINE(PRTUINT64U
) RTUInt64Div(PRTUINT64U pResult
, PCRTUINT64U pValue1
, PCRTUINT64U pValue2
)
359 return RTUInt64DivRem(pResult
, &Ignored
, pValue1
, pValue2
);
364 * Divides a 64-bit unsigned integer value by another, returning the remainder.
367 * @param pResult The result variable (remainder).
368 * @param pValue1 The dividend value.
369 * @param pValue2 The divisor value.
371 DECLINLINE(PRTUINT64U
) RTUInt64Mod(PRTUINT64U pResult
, PCRTUINT64U pValue1
, PCRTUINT64U pValue2
)
374 RTUInt64DivRem(&Ignored
, pResult
, pValue1
, pValue2
);
380 * Divides a 64-bit signed integer value by another.
383 * @param pResult The result variable.
384 * @param pValue1 The dividend value.
385 * @param pValue2 The divisor value.
387 DECLINLINE(PRTUINT64U
) RTUInt64DivSigned(PRTUINT64U pResult
, PCRTUINT64U pValue1
, PCRTUINT64U pValue2
)
390 return RTUInt64DivRemSigned(pResult
, &Ignored
, pValue1
, pValue2
);
395 * Divides a 64-bit unsigned integer value by another, returning the remainder.
398 * @param pResult The result variable (remainder).
399 * @param pValue1 The dividend value.
400 * @param pValue2 The divisor value.
402 DECLINLINE(PRTUINT64U
) RTUInt64ModSigned(PRTUINT64U pResult
, PCRTUINT64U pValue1
, PCRTUINT64U pValue2
)
405 RTUInt64DivRemSigned(&Ignored
, pResult
, pValue1
, pValue2
);
411 * Bitwise AND of two 64-bit unsigned integer values.
414 * @param pResult The result variable.
415 * @param pValue1 The first value.
416 * @param pValue2 The second value.
418 DECLINLINE(PRTUINT64U
) RTUInt64And(PRTUINT64U pResult
, PCRTUINT64U pValue1
, PCRTUINT64U pValue2
)
420 pResult
->s
.Hi
= pValue1
->s
.Hi
& pValue2
->s
.Hi
;
421 pResult
->s
.Lo
= pValue1
->s
.Lo
& pValue2
->s
.Lo
;
427 * Bitwise OR of two 64-bit unsigned integer values.
430 * @param pResult The result variable.
431 * @param pValue1 The first value.
432 * @param pValue2 The second value.
434 DECLINLINE(PRTUINT64U
) RTUInt64Or( PRTUINT64U pResult
, PCRTUINT64U pValue1
, PCRTUINT64U pValue2
)
436 pResult
->s
.Hi
= pValue1
->s
.Hi
| pValue2
->s
.Hi
;
437 pResult
->s
.Lo
= pValue1
->s
.Lo
| pValue2
->s
.Lo
;
443 * Bitwise XOR of two 64-bit unsigned integer values.
446 * @param pResult The result variable.
447 * @param pValue1 The first value.
448 * @param pValue2 The second value.
450 DECLINLINE(PRTUINT64U
) RTUInt64Xor(PRTUINT64U pResult
, PCRTUINT64U pValue1
, PCRTUINT64U pValue2
)
452 pResult
->s
.Hi
= pValue1
->s
.Hi
^ pValue2
->s
.Hi
;
453 pResult
->s
.Lo
= pValue1
->s
.Lo
^ pValue2
->s
.Lo
;
459 * Shifts a 64-bit unsigned integer value @a cBits to the left.
462 * @param pResult The result variable.
463 * @param pValue The value to shift.
464 * @param cBits The number of bits to shift it.
466 DECLINLINE(PRTUINT64U
) RTUInt64ShiftLeft(PRTUINT64U pResult
, PCRTUINT64U pValue
, int cBits
)
471 pResult
->s
.Lo
= pValue
->s
.Lo
<< cBits
;
472 pResult
->s
.Hi
= (pValue
->s
.Hi
<< cBits
) | (pValue
->s
.Lo
>> (32 - cBits
));
477 pResult
->s
.Hi
= pValue
->s
.Lo
<< (cBits
- 32);
484 * Shifts a 64-bit unsigned integer value @a cBits to the right.
487 * @param pResult The result variable.
488 * @param pValue The value to shift.
489 * @param cBits The number of bits to shift it.
491 DECLINLINE(PRTUINT64U
) RTUInt64ShiftRight(PRTUINT64U pResult
, PCRTUINT64U pValue
, int cBits
)
496 pResult
->s
.Hi
= pValue
->s
.Hi
>> cBits
;
497 pResult
->s
.Lo
= (pValue
->s
.Lo
>> cBits
) | (pValue
->s
.Hi
<< (32 - cBits
));
502 pResult
->s
.Lo
= pValue
->s
.Hi
>> (cBits
- 32);
509 * Boolean not (result 0 or 1).
512 * @param pResult The result variable.
513 * @param pValue The value.
515 DECLINLINE(PRTUINT64U
) RTUInt64BooleanNot(PRTUINT64U pResult
, PCRTUINT64U pValue
)
517 pResult
->s
.Lo
= pValue
->s
.Lo
|| pValue
->s
.Hi
? 0 : 1;
524 * Bitwise not (flips each bit of the 64 bits).
527 * @param pResult The result variable.
528 * @param pValue The value.
530 DECLINLINE(PRTUINT64U
) RTUInt64BitwiseNot(PRTUINT64U pResult
, PCRTUINT64U pValue
)
532 pResult
->s
.Hi
= ~pValue
->s
.Hi
;
533 pResult
->s
.Lo
= ~pValue
->s
.Lo
;
539 * Assigns one 64-bit unsigned integer value to another.
542 * @param pResult The result variable.
543 * @param pValue The value to assign.
545 DECLINLINE(PRTUINT64U
) RTUInt64Assign(PRTUINT64U pResult
, PCRTUINT64U pValue
)
548 pResult
->s
.Hi
= pValue
->s
.Hi
;
549 pResult
->s
.Lo
= pValue
->s
.Lo
;
551 pResult
->Words
.w0
= pValue
->Words
.w0
;
552 pResult
->Words
.w1
= pValue
->Words
.w1
;
553 pResult
->Words
.w2
= pValue
->Words
.w2
;
554 pResult
->Words
.w3
= pValue
->Words
.w3
;
561 * Assigns a boolean value to 64-bit unsigned integer.
563 * @returns pValueResult
564 * @param pValueResult The result variable.
565 * @param fValue The boolean value.
567 DECLINLINE(PRTUINT64U
) RTUInt64AssignBoolean(PRTUINT64U pValueResult
, bool fValue
)
570 pValueResult
->s
.Lo
= fValue
;
571 pValueResult
->s
.Hi
= 0;
573 pValueResult
->Words
.w0
= fValue
;
574 pValueResult
->Words
.w1
= 0;
575 pValueResult
->Words
.w2
= 0;
576 pValueResult
->Words
.w3
= 0;
583 * Assigns a 8-bit unsigned integer value to 64-bit unsigned integer.
585 * @returns pValueResult
586 * @param pValueResult The result variable.
587 * @param u8Value The 8-bit unsigned integer value.
589 DECLINLINE(PRTUINT64U
) RTUInt64AssignU8(PRTUINT64U pValueResult
, uint8_t u8Value
)
592 pValueResult
->s
.Lo
= u8Value
;
593 pValueResult
->s
.Hi
= 0;
595 pValueResult
->Words
.w0
= u8Value
;
596 pValueResult
->Words
.w1
= 0;
597 pValueResult
->Words
.w2
= 0;
598 pValueResult
->Words
.w3
= 0;
605 * Assigns a 16-bit unsigned integer value to 64-bit unsigned integer.
607 * @returns pValueResult
608 * @param pValueResult The result variable.
609 * @param u16Value The 16-bit unsigned integer value.
611 DECLINLINE(PRTUINT64U
) RTUInt64AssignU16(PRTUINT64U pValueResult
, uint16_t u16Value
)
614 pValueResult
->s
.Lo
= u16Value
;
615 pValueResult
->s
.Hi
= 0;
617 pValueResult
->Words
.w0
= u16Value
;
618 pValueResult
->Words
.w1
= 0;
619 pValueResult
->Words
.w2
= 0;
620 pValueResult
->Words
.w3
= 0;
627 * Assigns a 32-bit unsigned integer value to 64-bit unsigned integer.
629 * @returns pValueResult
630 * @param pValueResult The result variable.
631 * @param u32Value The 32-bit unsigned integer value.
633 DECLINLINE(PRTUINT64U
) RTUInt64AssignU32(PRTUINT64U pValueResult
, uint32_t u32Value
)
636 pValueResult
->s
.Lo
= u32Value
;
637 pValueResult
->s
.Hi
= 0;
639 pValueResult
->Words
.w0
= (uint16_t)u32Value
;
640 pValueResult
->Words
.w1
= u32Value
>> 16;
641 pValueResult
->Words
.w2
= 0;
642 pValueResult
->Words
.w3
= 0;
649 * Adds two 64-bit unsigned integer values, storing the result in the first.
651 * @returns pValue1Result.
652 * @param pValue1Result The first value and result.
653 * @param pValue2 The second value.
655 DECLINLINE(PRTUINT64U
) RTUInt64AssignAdd(PRTUINT64U pValue1Result
, PCRTUINT64U pValue2
)
657 uint32_t const uTmp
= pValue1Result
->s
.Lo
;
658 pValue1Result
->s
.Lo
+= pValue2
->s
.Lo
;
659 if (pValue1Result
->s
.Lo
< uTmp
)
660 pValue1Result
->s
.Hi
++;
661 pValue1Result
->s
.Hi
+= pValue2
->s
.Hi
;
662 return pValue1Result
;
667 * Subtracts two 64-bit unsigned integer values, storing the result in the
670 * @returns pValue1Result.
671 * @param pValue1Result The minuend value and result.
672 * @param pValue2 The subtrahend value.
674 DECLINLINE(PRTUINT64U
) RTUInt64AssignSub(PRTUINT64U pValue1Result
, PCRTUINT64U pValue2
)
676 uint32_t const uTmp
= pValue1Result
->s
.Lo
;
677 pValue1Result
->s
.Lo
-= pValue2
->s
.Lo
;
678 if (pValue1Result
->s
.Lo
> uTmp
)
679 pValue1Result
->s
.Hi
--;
680 pValue1Result
->s
.Hi
-= pValue2
->s
.Hi
;
681 return pValue1Result
;
686 * Negates a 64-bit unsigned integer value, returning the result in place.
688 * @returns pValueResult.
689 * @param pValueResult The value and result.
691 DECLINLINE(PRTUINT64U
) RTUInt64AssignNeg(PRTUINT64U pValueResult
)
693 pValueResult
->s
.Lo
= UINT32_C(0) - pValueResult
->s
.Lo
;
694 pValueResult
->s
.Hi
= UINT32_C(0) - pValueResult
->s
.Hi
;
695 if (pValueResult
->s
.Lo
> UINT32_C(0))
696 pValueResult
->s
.Hi
--;
702 * Multiplies two 64-bit unsigned integer values, storing the result in the
705 * @returns pValue1Result.
706 * @param pValue1Result The first value and result.
707 * @param pValue2 The second value.
709 DECLINLINE(PRTUINT64U
) RTUInt64AssignMul(PRTUINT64U pValue1Result
, PCRTUINT64U pValue2
)
712 RTUInt64Mul(&Result
, pValue1Result
, pValue2
);
713 *pValue1Result
= Result
;
714 return pValue1Result
;
719 * Divides a 64-bit unsigned integer value by another, storing the result in
722 * @returns pValue1Result.
723 * @param pValue1Result The dividend value and result.
724 * @param pValue2 The divisor value.
726 DECLINLINE(PRTUINT64U
) RTUInt64AssignDiv(PRTUINT64U pValue1Result
, PCRTUINT64U pValue2
)
730 RTUInt64DivRem(&Result
, &Ignored
, pValue1Result
, pValue2
);
731 *pValue1Result
= Result
;
732 return pValue1Result
;
737 * Divides a 64-bit unsigned integer value by another, storing the remainder in
740 * @returns pValue1Result.
741 * @param pValue1Result The dividend value and result (remainder).
742 * @param pValue2 The divisor value.
744 DECLINLINE(PRTUINT64U
) RTUInt64AssignMod(PRTUINT64U pValue1Result
, PCRTUINT64U pValue2
)
748 RTUInt64DivRem(&Ignored
, &Result
, pValue1Result
, pValue2
);
749 *pValue1Result
= Result
;
750 return pValue1Result
;
755 * Performs a bitwise AND of two 64-bit unsigned integer values and assigned
756 * the result to the first one.
758 * @returns pValue1Result.
759 * @param pValue1Result The first value and result.
760 * @param pValue2 The second value.
762 DECLINLINE(PRTUINT64U
) RTUInt64AssignAnd(PRTUINT64U pValue1Result
, PCRTUINT64U pValue2
)
765 pValue1Result
->s
.Hi
&= pValue2
->s
.Hi
;
766 pValue1Result
->s
.Lo
&= pValue2
->s
.Lo
;
768 pValue1Result
->Words
.w0
&= pValue2
->Words
.w0
;
769 pValue1Result
->Words
.w1
&= pValue2
->Words
.w1
;
770 pValue1Result
->Words
.w2
&= pValue2
->Words
.w2
;
771 pValue1Result
->Words
.w3
&= pValue2
->Words
.w3
;
773 return pValue1Result
;
778 * Performs a bitwise AND of a 64-bit unsigned integer value and a mask made
779 * up of the first N bits, assigning the result to the the 64-bit value.
781 * @returns pValueResult.
782 * @param pValueResult The value and result.
783 * @param cBits The number of bits to AND (counting from the first
786 DECLINLINE(PRTUINT64U
) RTUInt64AssignAndNFirstBits(PRTUINT64U pValueResult
, unsigned cBits
)
791 pValueResult
->s
.Lo
&= (RT_BIT_32(cBits
) - 1);
792 pValueResult
->s
.Hi
= 0;
795 pValueResult
->s
.Hi
&= (RT_BIT_32(cBits
- 32) - 1);
801 * Performs a bitwise OR of two 64-bit unsigned integer values and assigned
802 * the result to the first one.
804 * @returns pValue1Result.
805 * @param pValue1Result The first value and result.
806 * @param pValue2 The second value.
808 DECLINLINE(PRTUINT64U
) RTUInt64AssignOr(PRTUINT64U pValue1Result
, PCRTUINT64U pValue2
)
811 pValue1Result
->s
.Hi
|= pValue2
->s
.Hi
;
812 pValue1Result
->s
.Lo
|= pValue2
->s
.Lo
;
814 pValue1Result
->Words
.w0
|= pValue2
->Words
.w0
;
815 pValue1Result
->Words
.w1
|= pValue2
->Words
.w1
;
816 pValue1Result
->Words
.w2
|= pValue2
->Words
.w2
;
817 pValue1Result
->Words
.w3
|= pValue2
->Words
.w3
;
819 return pValue1Result
;
824 * ORs in a bit and assign the result to the input value.
826 * @returns pValue1Result.
827 * @param pValue1Result The first value and result.
828 * @param iBit The bit to set (0 based).
830 DECLINLINE(PRTUINT64U
) RTUInt64AssignOrBit(PRTUINT64U pValue1Result
, unsigned iBit
)
834 pValue1Result
->s
.Hi
|= RT_BIT_32(iBit
- 32);
836 pValue1Result
->s
.Lo
|= RT_BIT_32(iBit
);
841 pValue1Result
->Words
.w3
|= UINT16_C(1) << (iBit
- 48);
843 pValue1Result
->Words
.w2
|= UINT16_C(1) << (iBit
- 32);
848 pValue1Result
->Words
.w1
|= UINT16_C(1) << (iBit
- 16);
850 pValue1Result
->Words
.w0
|= UINT16_C(1) << (iBit
);
853 return pValue1Result
;
859 * Performs a bitwise XOR of two 64-bit unsigned integer values and assigned
860 * the result to the first one.
862 * @returns pValue1Result.
863 * @param pValue1Result The first value and result.
864 * @param pValue2 The second value.
866 DECLINLINE(PRTUINT64U
) RTUInt64AssignXor(PRTUINT64U pValue1Result
, PCRTUINT64U pValue2
)
869 pValue1Result
->s
.Hi
^= pValue2
->s
.Hi
;
870 pValue1Result
->s
.Lo
^= pValue2
->s
.Lo
;
872 pValue1Result
->Words
.w0
^= pValue2
->Words
.w0
;
873 pValue1Result
->Words
.w1
^= pValue2
->Words
.w1
;
874 pValue1Result
->Words
.w2
^= pValue2
->Words
.w2
;
875 pValue1Result
->Words
.w3
^= pValue2
->Words
.w3
;
877 return pValue1Result
;
882 * Performs a bitwise left shift on a 64-bit unsigned integer value, assigning
885 * @returns pValueResult.
886 * @param pValueResult The first value and result.
887 * @param cBits The number of bits to shift.
889 DECLINLINE(PRTUINT64U
) RTUInt64AssignShiftLeft(PRTUINT64U pValueResult
, int cBits
)
891 RTUINT64U
const InVal
= *pValueResult
;
898 pValueResult
->s
.Lo
= 0;
899 pValueResult
->s
.Hi
= InVal
.s
.Lo
<< (cBits
- 32);
903 pValueResult
->s
.Hi
= InVal
.s
.Hi
<< cBits
;
904 pValueResult
->s
.Hi
|= InVal
.s
.Lo
>> (32 - cBits
);
905 pValueResult
->s
.Lo
= InVal
.s
.Lo
<< cBits
;
915 pValueResult
->s
.Hi
= 0;
916 pValueResult
->s
.Lo
= InVal
.s
.Hi
>> (cBits
- 32);
920 pValueResult
->s
.Lo
= InVal
.s
.Lo
>> cBits
;
921 pValueResult
->s
.Lo
|= InVal
.s
.Hi
<< (32 - cBits
);
922 pValueResult
->s
.Hi
= InVal
.s
.Hi
>> cBits
;
930 * Performs a bitwise left shift on a 64-bit unsigned integer value, assigning
933 * @returns pValueResult.
934 * @param pValueResult The first value and result.
935 * @param cBits The number of bits to shift.
937 DECLINLINE(PRTUINT64U
) RTUInt64AssignShiftRight(PRTUINT64U pValueResult
, int cBits
)
939 return RTUInt64AssignShiftLeft(pValueResult
, -cBits
);
944 * Performs a bitwise NOT on a 64-bit unsigned integer value, assigning the
947 * @returns pValueResult
948 * @param pValueResult The value and result.
950 DECLINLINE(PRTUINT64U
) RTUInt64AssignBitwiseNot(PRTUINT64U pValueResult
)
953 pValueResult
->s
.Hi
= ~pValueResult
->s
.Hi
;
954 pValueResult
->s
.Lo
= ~pValueResult
->s
.Lo
;
956 pValueResult
->Words
.w0
= ~pValueResult
->Words
.w0
;
957 pValueResult
->Words
.w1
= ~pValueResult
->Words
.w1
;
958 pValueResult
->Words
.w2
= ~pValueResult
->Words
.w2
;
959 pValueResult
->Words
.w3
= ~pValueResult
->Words
.w3
;
966 * Performs a boolean NOT on a 64-bit unsigned integer value, assigning the
969 * @returns pValueResult
970 * @param pValueResult The value and result.
972 DECLINLINE(PRTUINT64U
) RTUInt64AssignBooleanNot(PRTUINT64U pValueResult
)
974 return RTUInt64AssignBoolean(pValueResult
, RTUInt64IsZero(pValueResult
));
979 * Compares two 64-bit unsigned integer values.
981 * @retval 0 if equal.
982 * @retval -1 if the first value is smaller than the second.
983 * @retval 1 if the first value is larger than the second.
985 * @param pValue1 The first value.
986 * @param pValue2 The second value.
988 DECLINLINE(int) RTUInt64Compare(PCRTUINT64U pValue1
, PCRTUINT64U pValue2
)
991 if (pValue1
->s
.Hi
!= pValue2
->s
.Hi
)
992 return pValue1
->s
.Hi
> pValue2
->s
.Hi
? 1 : -1;
993 if (pValue1
->s
.Lo
!= pValue2
->s
.Lo
)
994 return pValue1
->s
.Lo
> pValue2
->s
.Lo
? 1 : -1;
997 if (pValue1
->Words
.w3
!= pValue2
->Words
.w3
)
998 return pValue1
->Words
.w3
> pValue2
->Words
.w3
? 1 : -1;
999 if (pValue1
->Words
.w2
!= pValue2
->Words
.w2
)
1000 return pValue1
->Words
.w2
> pValue2
->Words
.w2
? 1 : -1;
1001 if (pValue1
->Words
.w1
!= pValue2
->Words
.w1
)
1002 return pValue1
->Words
.w1
> pValue2
->Words
.w1
? 1 : -1;
1003 if (pValue1
->Words
.w0
!= pValue2
->Words
.w0
)
1004 return pValue1
->Words
.w0
> pValue2
->Words
.w0
? 1 : -1;
1011 * Tests if a 64-bit unsigned integer value is smaller than another.
1013 * @returns true if the first value is smaller, false if not.
1014 * @param pValue1 The first value.
1015 * @param pValue2 The second value.
1017 DECLINLINE(bool) RTUInt64IsSmaller(PCRTUINT64U pValue1
, PCRTUINT64U pValue2
)
1020 return pValue1
->s
.Hi
< pValue2
->s
.Hi
1021 || ( pValue1
->s
.Hi
== pValue2
->s
.Hi
1022 && pValue1
->s
.Lo
< pValue2
->s
.Lo
);
1024 return pValue1
->Words
.w3
< pValue2
->Words
.w3
1025 || ( pValue1
->Words
.w3
== pValue2
->Words
.w3
1026 && ( pValue1
->Words
.w2
< pValue2
->Words
.w2
1027 || ( pValue1
->Words
.w2
== pValue2
->Words
.w2
1028 && ( pValue1
->Words
.w1
< pValue2
->Words
.w1
1029 || ( pValue1
->Words
.w1
== pValue2
->Words
.w1
1030 && pValue1
->Words
.w0
< pValue2
->Words
.w0
)))));
1036 * Tests if a 32-bit unsigned integer value is larger than another.
1038 * @returns true if the first value is larger, false if not.
1039 * @param pValue1 The first value.
1040 * @param pValue2 The second value.
1042 DECLINLINE(bool) RTUInt64IsLarger(PCRTUINT64U pValue1
, PCRTUINT64U pValue2
)
1045 return pValue1
->s
.Hi
> pValue2
->s
.Hi
1046 || ( pValue1
->s
.Hi
== pValue2
->s
.Hi
1047 && pValue1
->s
.Lo
> pValue2
->s
.Lo
);
1049 return pValue1
->Words
.w3
> pValue2
->Words
.w3
1050 || ( pValue1
->Words
.w3
== pValue2
->Words
.w3
1051 && ( pValue1
->Words
.w2
> pValue2
->Words
.w2
1052 || ( pValue1
->Words
.w2
== pValue2
->Words
.w2
1053 && ( pValue1
->Words
.w1
> pValue2
->Words
.w1
1054 || ( pValue1
->Words
.w1
== pValue2
->Words
.w1
1055 && pValue1
->Words
.w0
> pValue2
->Words
.w0
)))));
1061 * Tests if a 64-bit unsigned integer value is larger or equal than another.
1063 * @returns true if the first value is larger or equal, false if not.
1064 * @param pValue1 The first value.
1065 * @param pValue2 The second value.
1067 DECLINLINE(bool) RTUInt64IsLargerOrEqual(PCRTUINT64U pValue1
, PCRTUINT64U pValue2
)
1070 return pValue1
->s
.Hi
> pValue2
->s
.Hi
1071 || ( pValue1
->s
.Hi
== pValue2
->s
.Hi
1072 && pValue1
->s
.Lo
>= pValue2
->s
.Lo
);
1074 return pValue1
->Words
.w3
> pValue2
->Words
.w3
1075 || ( pValue1
->Words
.w3
== pValue2
->Words
.w3
1076 && ( pValue1
->Words
.w2
> pValue2
->Words
.w2
1077 || ( pValue1
->Words
.w2
== pValue2
->Words
.w2
1078 && ( pValue1
->Words
.w1
> pValue2
->Words
.w1
1079 || ( pValue1
->Words
.w1
== pValue2
->Words
.w1
1080 && pValue1
->Words
.w0
>= pValue2
->Words
.w0
)))));
1086 * Tests if two 64-bit unsigned integer values not equal.
1088 * @returns true if equal, false if not equal.
1089 * @param pValue1 The first value.
1090 * @param pValue2 The second value.
1092 DECLINLINE(bool) RTUInt64IsEqual(PCRTUINT64U pValue1
, PCRTUINT64U pValue2
)
1095 return pValue1
->s
.Hi
== pValue2
->s
.Hi
1096 && pValue1
->s
.Lo
== pValue2
->s
.Lo
;
1098 return pValue1
->Words
.w0
== pValue2
->Words
.w0
1099 && pValue1
->Words
.w1
== pValue2
->Words
.w1
1100 && pValue1
->Words
.w2
== pValue2
->Words
.w2
1101 && pValue1
->Words
.w3
== pValue2
->Words
.w3
;
1107 * Tests if two 64-bit unsigned integer values are not equal.
1109 * @returns true if not equal, false if equal.
1110 * @param pValue1 The first value.
1111 * @param pValue2 The second value.
1113 DECLINLINE(bool) RTUInt64IsNotEqual(PCRTUINT64U pValue1
, PCRTUINT64U pValue2
)
1115 return !RTUInt64IsEqual(pValue1
, pValue2
);
1120 * Sets a bit in a 64-bit unsigned integer type.
1122 * @returns pValueResult.
1123 * @param pValueResult The input and output value.
1124 * @param iBit The bit to set.
1126 DECLINLINE(PRTUINT64U
) RTUInt64BitSet(PRTUINT64U pValueResult
, unsigned iBit
)
1131 pValueResult
->s
.Lo
|= RT_BIT_32(iBit
);
1134 pValueResult
->Words
.w0
|= UINT16_C(1) << iBit
;
1136 pValueResult
->Words
.w1
|= UINT16_C(1) << (iBit
- 32);
1142 pValueResult
->s
.Hi
|= RT_BIT_32(iBit
- 32);
1145 pValueResult
->Words
.w2
|= UINT16_C(1) << (iBit
- 64);
1147 pValueResult
->Words
.w3
|= UINT16_C(1) << (iBit
- 96);
1150 return pValueResult
;
1155 * Sets a bit in a 64-bit unsigned integer type.
1157 * @returns pValueResult.
1158 * @param pValueResult The input and output value.
1159 * @param iBit The bit to set.
1161 DECLINLINE(PRTUINT64U
) RTUInt64BitClear(PRTUINT64U pValueResult
, unsigned iBit
)
1166 pValueResult
->s
.Lo
&= ~RT_BIT_32(iBit
);
1169 pValueResult
->Words
.w0
&= ~(UINT16_C(1) << (iBit
));
1171 pValueResult
->Words
.w1
&= ~(UINT16_C(1) << (iBit
- 32));
1177 pValueResult
->s
.Hi
&= ~RT_BIT_32(iBit
- 32);
1180 pValueResult
->Words
.w2
&= ~(UINT16_C(1) << (iBit
- 64));
1182 pValueResult
->Words
.w3
&= ~(UINT16_C(1) << (iBit
- 96));
1185 return pValueResult
;
1190 * Tests if a bit in a 64-bit unsigned integer value is set.
1192 * @returns pValueResult.
1193 * @param pValueResult The input and output value.
1194 * @param iBit The bit to test.
1196 DECLINLINE(bool) RTUInt64BitTest(PRTUINT64U pValueResult
, unsigned iBit
)
1202 fRc
= RT_BOOL(pValueResult
->s
.Lo
& RT_BIT_32(iBit
));
1205 fRc
= RT_BOOL(pValueResult
->Words
.w0
& (UINT16_C(1) << (iBit
)));
1207 fRc
= RT_BOOL(pValueResult
->Words
.w1
& (UINT16_C(1) << (iBit
- 16)));
1213 fRc
= RT_BOOL(pValueResult
->s
.Hi
& RT_BIT_32(iBit
- 32));
1216 fRc
= RT_BOOL(pValueResult
->Words
.w2
& (UINT16_C(1) << (iBit
- 32)));
1218 fRc
= RT_BOOL(pValueResult
->Words
.w3
& (UINT16_C(1) << (iBit
- 48)));
1228 * Set a range of bits a 64-bit unsigned integer value.
1230 * @returns pValueResult.
1231 * @param pValueResult The input and output value.
1232 * @param iFirstBit The first bit to test.
1233 * @param cBits The number of bits to set.
1235 DECLINLINE(PRTUINT64U
) RTUInt64BitSetRange(PRTUINT64U pValueResult
, unsigned iFirstBit
, unsigned cBits
)
1237 /* bounds check & fix. */
1240 if (iFirstBit
+ cBits
> 64)
1241 cBits
= 64 - iFirstBit
;
1244 if (iFirstBit
+ cBits
< 32)
1245 pValueResult
->s
.Lo
|= (RT_BIT_32(cBits
) - 1) << iFirstBit
;
1246 else if (iFirstBit
+ cBits
< 64 && iFirstBit
>= 32)
1247 pValueResult
->s
.Hi
|= (RT_BIT_32(cBits
) - 1) << (iFirstBit
- 32);
1250 if (iFirstBit
+ cBits
< 16)
1251 pValueResult
->Words
.w0
|= ((UINT16_C(1) << cBits
) - 1) << iFirstBit
;
1252 else if (iFirstBit
+ cBits
< 32 && iFirstBit
>= 16)
1253 pValueResult
->Words
.w1
|= ((UINT16_C(1) << cBits
) - 1) << (iFirstBit
- 16);
1254 else if (iFirstBit
+ cBits
< 48 && iFirstBit
>= 32)
1255 pValueResult
->Words
.w2
|= ((UINT16_C(1) << cBits
) - 1) << (iFirstBit
- 32);
1256 else if (iFirstBit
+ cBits
< 64 && iFirstBit
>= 48)
1257 pValueResult
->Words
.w3
|= ((UINT16_C(1) << cBits
) - 1) << (iFirstBit
- 48);
1261 RTUInt64BitSet(pValueResult
, iFirstBit
++);
1263 return pValueResult
;
1268 * Test if all the bits of a 64-bit unsigned integer value are set.
1270 * @returns true if they are, false if they aren't.
1271 * @param pValue The input and output value.
1273 DECLINLINE(bool) RTUInt64BitAreAllSet(PRTUINT64U pValue
)
1276 return pValue
->s
.Hi
== UINT32_MAX
1277 && pValue
->s
.Lo
== UINT32_MAX
;
1279 return pValue
->Words
.w0
== UINT16_MAX
1280 && pValue
->Words
.w1
== UINT16_MAX
1281 && pValue
->Words
.w2
== UINT16_MAX
1282 && pValue
->Words
.w3
== UINT16_MAX
;
1288 * Test if all the bits of a 64-bit unsigned integer value are clear.
1290 * @returns true if they are, false if they aren't.
1291 * @param pValue The input and output value.
1293 DECLINLINE(bool) RTUInt64BitAreAllClear(PRTUINT64U pValue
)
1295 return RTUInt64IsZero(pValue
);
1299 DECLINLINE(unsigned) RTUInt64BitCount(PCRTUINT64U pValue
)
1302 if (pValue
->s
.Hi
!= 0)
1305 cBits
= 32 + ASMBitLastSetU32(pValue
->s
.Hi
);
1307 if (pValue
->Words
.w3
)
1308 cBits
= 48 + ASMBitLastSetU16(pValue
->Words
.w3
);
1310 cBits
= 32 + ASMBitLastSetU16(pValue
->Words
.w2
);
1316 cBits
= ASMBitLastSetU32(pValue
->s
.Lo
);
1318 if (pValue
->Words
.w1
)
1319 cBits
= 16 + ASMBitLastSetU16(pValue
->Words
.w1
);
1321 cBits
= 0 + ASMBitLastSetU16(pValue
->Words
.w0
);
1329 * Divides a 64-bit unsigned integer value by another, returning both quotient
1332 * @returns pQuotient, NULL if pValue2 is 0.
1333 * @param pQuotient Where to return the quotient.
1334 * @param pRemainder Where to return the remainder.
1335 * @param pValue1 The dividend value.
1336 * @param pValue2 The divisor value.
1338 DECLINLINE(PRTUINT64U
) RTUInt64DivRem(PRTUINT64U pQuotient
, PRTUINT64U pRemainder
, PCRTUINT64U pValue1
, PCRTUINT64U pValue2
)
1343 * Sort out all the special cases first.
1345 /* Divide by zero or 1? */
1351 if (pValue2
->s
.Lo
== 1)
1353 RTUInt64SetZero(pRemainder
);
1354 *pQuotient
= *pValue1
;
1357 /** @todo RTUInt64DivModByU32 */
1360 /* Dividend is smaller? */
1361 iDiff
= RTUInt64Compare(pValue1
, pValue2
);
1364 *pRemainder
= *pValue1
;
1365 RTUInt64SetZero(pQuotient
);
1368 /* The values are equal? */
1369 else if (iDiff
== 0)
1371 RTUInt64SetZero(pRemainder
);
1372 RTUInt64AssignU8(pQuotient
, 1);
1379 unsigned iBitAdder
= RTUInt64BitCount(pValue1
) - RTUInt64BitCount(pValue2
);
1380 RTUINT64U NormDivisor
= *pValue2
;
1383 RTUInt64ShiftLeft(&NormDivisor
, pValue2
, iBitAdder
);
1384 if (RTUInt64IsLarger(&NormDivisor
, pValue1
))
1386 RTUInt64AssignShiftRight(&NormDivisor
, 1);
1391 NormDivisor
= *pValue2
;
1393 RTUInt64SetZero(pQuotient
);
1394 *pRemainder
= *pValue1
;
1399 if (RTUInt64IsLargerOrEqual(pRemainder
, pValue2
))
1403 if (RTUInt64IsLargerOrEqual(pRemainder
, &NormDivisor
))
1405 RTUInt64AssignSub(pRemainder
, &NormDivisor
);
1406 RTUInt64AssignOrBit(pQuotient
, iBitAdder
);
1408 if (RTUInt64IsSmaller(pRemainder
, pValue2
))
1410 RTUInt64AssignShiftRight(&NormDivisor
, 1);
1420 * Divides a 64-bit signed integer value by another, returning both quotient and
1423 * @returns pQuotient, NULL if pValue2 is 0.
1424 * @param pQuotient Where to return the quotient.
1425 * @param pRemainder Where to return the remainder.
1426 * @param pValue1 The dividend value.
1427 * @param pValue2 The divisor value.
1429 DECLINLINE(PRTUINT64U
) RTUInt64DivRemSigned(PRTUINT64U pQuotient
, PRTUINT64U pRemainder
, PCRTUINT64U pValue1
, PCRTUINT64U pValue2
)
1432 * If both values are positive, we can do a straight unsigned division.
1434 if (!RTUInt64IsSigned(pValue1
))
1436 if (!RTUInt64IsSigned(pValue2
))
1437 return RTUInt64DivRem(pQuotient
, pRemainder
, pValue1
, pValue2
);
1440 * Negative divisor, Positive dividend:
1441 * negate the divisor, do unsigned division, and negate the quotient.
1444 RTUINT64U NegDivisor
;
1445 RTUInt64DivRem(pQuotient
, pRemainder
, pValue1
, RTUInt64Neg(&NegDivisor
, pValue2
));
1446 RTUInt64AssignNeg(pQuotient
);
1451 /* Negate the dividend to get a positive value. */
1452 RTUINT64U NegDividend
;
1453 RTUInt64Neg(&NegDividend
, pValue1
);
1455 if (!RTUInt64IsSigned(pValue2
))
1458 * Negative dividend, positive divisor:
1459 * Negate the dividend (above), do unsigned division, and negate both quotient and remainder
1461 RTUInt64DivRem(pQuotient
, pRemainder
, &NegDividend
, pValue2
);
1462 RTUInt64AssignNeg(pQuotient
);
1467 * Negative dividend, negative divisor:
1468 * Negate both dividend (above) and divisor, do unsigned division, and negate the remainder.
1470 RTUINT64U NegDivisor
;
1471 RTUInt64DivRem(pQuotient
, pRemainder
, &NegDividend
, RTUInt64Neg(&NegDivisor
, pValue2
));
1473 RTUInt64AssignNeg(pRemainder
);
1483 #endif /* !IPRT_INCLUDED_uint64_h */