VirtualBox

source: vbox/trunk/include/iprt/uint128.h@ 87835

Last change on this file since 87835 was 82968, checked in by vboxsync, 5 years ago

Copyright year updates by scm.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 39.8 KB
Line 
1/** @file
2 * IPRT - RTUINT128U & uint128_t methods.
3 */
4
5/*
6 * Copyright (C) 2011-2020 Oracle Corporation
7 *
8 * This file is part of VirtualBox Open Source Edition (OSE), as
9 * available from http://www.virtualbox.org. This file is free software;
10 * you can redistribute it and/or modify it under the terms of the GNU
11 * General Public License (GPL) as published by the Free Software
12 * Foundation, in version 2 as it comes in the "COPYING" file of the
13 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
14 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
15 *
16 * The contents of this file may alternatively be used under the terms
17 * of the Common Development and Distribution License Version 1.0
18 * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
19 * VirtualBox OSE distribution, in which case the provisions of the
20 * CDDL are applicable instead of those of the GPL.
21 *
22 * You may elect to license modified versions of this file under the
23 * terms and conditions of either the GPL or the CDDL or both.
24 */
25
26#ifndef IPRT_INCLUDED_uint128_h
27#define IPRT_INCLUDED_uint128_h
28#ifndef RT_WITHOUT_PRAGMA_ONCE
29# pragma once
30#endif
31
32#include <iprt/cdefs.h>
33#include <iprt/types.h>
34#include <iprt/asm.h>
35#ifdef RT_ARCH_AMD64
36# include <iprt/asm-math.h>
37#endif
38
39RT_C_DECLS_BEGIN
40
41/** @defgroup grp_rt_uint128 RTUInt128 - 128-bit Unsigned Integer Methods
42 * @ingroup grp_rt
43 * @{
44 */
45
46
47/**
48 * Test if a 128-bit unsigned integer value is zero.
49 *
50 * @returns true if they are, false if they aren't.
51 * @param pValue The input and output value.
52 */
53DECLINLINE(bool) RTUInt128IsZero(PRTUINT128U pValue)
54{
55#if ARCH_BITS >= 64
56 return pValue->s.Hi == 0
57 && pValue->s.Lo == 0;
58#else
59 return pValue->DWords.dw0 == 0
60 && pValue->DWords.dw1 == 0
61 && pValue->DWords.dw2 == 0
62 && pValue->DWords.dw3 == 0;
63#endif
64}
65
66
67/**
68 * Set a 128-bit unsigned integer value to zero.
69 *
70 * @returns pResult
71 * @param pResult The result variable.
72 */
73DECLINLINE(PRTUINT128U) RTUInt128SetZero(PRTUINT128U pResult)
74{
75#if ARCH_BITS >= 64
76 pResult->s.Hi = 0;
77 pResult->s.Lo = 0;
78#else
79 pResult->DWords.dw0 = 0;
80 pResult->DWords.dw1 = 0;
81 pResult->DWords.dw2 = 0;
82 pResult->DWords.dw3 = 0;
83#endif
84 return pResult;
85}
86
87
88/**
89 * Set a 128-bit unsigned integer value to the maximum value.
90 *
91 * @returns pResult
92 * @param pResult The result variable.
93 */
94DECLINLINE(PRTUINT128U) RTUInt128SetMax(PRTUINT128U pResult)
95{
96#if ARCH_BITS >= 64
97 pResult->s.Hi = UINT64_MAX;
98 pResult->s.Lo = UINT64_MAX;
99#else
100 pResult->DWords.dw0 = UINT32_MAX;
101 pResult->DWords.dw1 = UINT32_MAX;
102 pResult->DWords.dw2 = UINT32_MAX;
103 pResult->DWords.dw3 = UINT32_MAX;
104#endif
105 return pResult;
106}
107
108
109
110
111/**
112 * Adds two 128-bit unsigned integer values.
113 *
114 * @returns pResult
115 * @param pResult The result variable.
116 * @param pValue1 The first value.
117 * @param pValue2 The second value.
118 */
119DECLINLINE(PRTUINT128U) RTUInt128Add(PRTUINT128U pResult, PCRTUINT128U pValue1, PCRTUINT128U pValue2)
120{
121 pResult->s.Hi = pValue1->s.Hi + pValue2->s.Hi;
122 pResult->s.Lo = pValue1->s.Lo + pValue2->s.Lo;
123 if (pResult->s.Lo < pValue1->s.Lo)
124 pResult->s.Hi++;
125 return pResult;
126}
127
128
129/**
130 * Adds a 128-bit and a 64-bit unsigned integer values.
131 *
132 * @returns pResult
133 * @param pResult The result variable.
134 * @param pValue1 The first value.
135 * @param uValue2 The second value, 64-bit.
136 */
137DECLINLINE(PRTUINT128U) RTUInt128AddU64(PRTUINT128U pResult, PCRTUINT128U pValue1, uint64_t uValue2)
138{
139 pResult->s.Hi = pValue1->s.Hi;
140 pResult->s.Lo = pValue1->s.Lo + uValue2;
141 if (pResult->s.Lo < pValue1->s.Lo)
142 pResult->s.Hi++;
143 return pResult;
144}
145
146
147/**
148 * Subtracts a 128-bit unsigned integer value from another.
149 *
150 * @returns pResult
151 * @param pResult The result variable.
152 * @param pValue1 The minuend value.
153 * @param pValue2 The subtrahend value.
154 */
155DECLINLINE(PRTUINT128U) RTUInt128Sub(PRTUINT128U pResult, PCRTUINT128U pValue1, PCRTUINT128U pValue2)
156{
157 pResult->s.Lo = pValue1->s.Lo - pValue2->s.Lo;
158 pResult->s.Hi = pValue1->s.Hi - pValue2->s.Hi;
159 if (pResult->s.Lo > pValue1->s.Lo)
160 pResult->s.Hi--;
161 return pResult;
162}
163
164
165/**
166 * Multiplies two 128-bit unsigned integer values.
167 *
168 * @returns pResult
169 * @param pResult The result variable.
170 * @param pValue1 The first value.
171 * @param pValue2 The second value.
172 */
173DECLINLINE(PRTUINT128U) RTUInt128Mul(PRTUINT128U pResult, PCRTUINT128U pValue1, PCRTUINT128U pValue2)
174{
175 RTUINT64U uTmp;
176
177 /* multiply all dwords in v1 by v2.dw0. */
178 pResult->s.Lo = (uint64_t)pValue1->DWords.dw0 * pValue2->DWords.dw0;
179
180 uTmp.u = (uint64_t)pValue1->DWords.dw1 * pValue2->DWords.dw0;
181 pResult->DWords.dw3 = 0;
182 pResult->DWords.dw2 = uTmp.DWords.dw1;
183 pResult->DWords.dw1 += uTmp.DWords.dw0;
184 if (pResult->DWords.dw1 < uTmp.DWords.dw0)
185 if (pResult->DWords.dw2++ == UINT32_MAX)
186 pResult->DWords.dw3++;
187
188 pResult->s.Hi += (uint64_t)pValue1->DWords.dw2 * pValue2->DWords.dw0;
189 pResult->DWords.dw3 += pValue1->DWords.dw3 * pValue2->DWords.dw0;
190
191 /* multiply dw0, dw1 & dw2 in v1 by v2.dw1. */
192 uTmp.u = (uint64_t)pValue1->DWords.dw0 * pValue2->DWords.dw1;
193 pResult->DWords.dw1 += uTmp.DWords.dw0;
194 if (pResult->DWords.dw1 < uTmp.DWords.dw0)
195 if (pResult->DWords.dw2++ == UINT32_MAX)
196 pResult->DWords.dw3++;
197
198 pResult->DWords.dw2 += uTmp.DWords.dw1;
199 if (pResult->DWords.dw2 < uTmp.DWords.dw1)
200 pResult->DWords.dw3++;
201
202 pResult->s.Hi += (uint64_t)pValue1->DWords.dw1 * pValue2->DWords.dw1;
203 pResult->DWords.dw3 += pValue1->DWords.dw2 * pValue2->DWords.dw1;
204
205 /* multiply dw0 & dw1 in v1 by v2.dw2. */
206 pResult->s.Hi += (uint64_t)pValue1->DWords.dw0 * pValue2->DWords.dw2;
207 pResult->DWords.dw3 += pValue1->DWords.dw1 * pValue2->DWords.dw2;
208
209 /* multiply dw0 in v1 by v2.dw3. */
210 pResult->DWords.dw3 += pValue1->DWords.dw0 * pValue2->DWords.dw3;
211
212 return pResult;
213}
214
215
216/**
217 * Multiplies an 128-bit unsigned integer by a 64-bit unsigned integer value.
218 *
219 * @returns pResult
220 * @param pResult The result variable.
221 * @param pValue1 The first value.
222 * @param uValue2 The second value, 64-bit.
223 */
224#if defined(RT_ARCH_AMD64)
225RTDECL(PRTUINT128U) RTUInt128MulByU64(PRTUINT128U pResult, PCRTUINT128U pValue1, uint64_t uValue2);
226#else
227DECLINLINE(PRTUINT128U) RTUInt128MulByU64(PRTUINT128U pResult, PCRTUINT128U pValue1, uint64_t uValue2)
228{
229 uint32_t const uLoValue2 = (uint32_t)uValue2;
230 uint32_t const uHiValue2 = (uint32_t)(uValue2 >> 32);
231 RTUINT64U uTmp;
232
233 /* multiply all dwords in v1 by uLoValue1. */
234 pResult->s.Lo = (uint64_t)pValue1->DWords.dw0 * uLoValue2;
235
236 uTmp.u = (uint64_t)pValue1->DWords.dw1 * uLoValue2;
237 pResult->DWords.dw3 = 0;
238 pResult->DWords.dw2 = uTmp.DWords.dw1;
239 pResult->DWords.dw1 += uTmp.DWords.dw0;
240 if (pResult->DWords.dw1 < uTmp.DWords.dw0)
241 if (pResult->DWords.dw2++ == UINT32_MAX)
242 pResult->DWords.dw3++;
243
244 pResult->s.Hi += (uint64_t)pValue1->DWords.dw2 * uLoValue2;
245 pResult->DWords.dw3 += pValue1->DWords.dw3 * uLoValue2;
246
247 /* multiply dw0, dw1 & dw2 in v1 by uHiValue2. */
248 uTmp.u = (uint64_t)pValue1->DWords.dw0 * uHiValue2;
249 pResult->DWords.dw1 += uTmp.DWords.dw0;
250 if (pResult->DWords.dw1 < uTmp.DWords.dw0)
251 if (pResult->DWords.dw2++ == UINT32_MAX)
252 pResult->DWords.dw3++;
253
254 pResult->DWords.dw2 += uTmp.DWords.dw1;
255 if (pResult->DWords.dw2 < uTmp.DWords.dw1)
256 pResult->DWords.dw3++;
257
258 pResult->s.Hi += (uint64_t)pValue1->DWords.dw1 * uHiValue2;
259 pResult->DWords.dw3 += pValue1->DWords.dw2 * uHiValue2;
260
261 return pResult;
262}
263#endif
264
265
266/**
267 * Multiplies two 64-bit unsigned integer values with 128-bit precision.
268 *
269 * @returns pResult
270 * @param pResult The result variable.
271 * @param uValue1 The first value. 64-bit.
272 * @param uValue2 The second value, 64-bit.
273 */
274DECLINLINE(PRTUINT128U) RTUInt128MulU64ByU64(PRTUINT128U pResult, uint64_t uValue1, uint64_t uValue2)
275{
276#ifdef RT_ARCH_AMD64
277 pResult->s.Lo = ASMMult2xU64Ret2xU64(uValue1, uValue2, &pResult->s.Hi);
278#else
279 uint32_t const uLoValue1 = (uint32_t)uValue1;
280 uint32_t const uHiValue1 = (uint32_t)(uValue1 >> 32);
281 uint32_t const uLoValue2 = (uint32_t)uValue2;
282 uint32_t const uHiValue2 = (uint32_t)(uValue2 >> 32);
283 RTUINT64U uTmp;
284
285 /* Multiply uLoValue1 and uHiValue1 by uLoValue1. */
286 pResult->s.Lo = (uint64_t)uLoValue1 * uLoValue2;
287
288 uTmp.u = (uint64_t)uHiValue1 * uLoValue2;
289 pResult->DWords.dw3 = 0;
290 pResult->DWords.dw2 = uTmp.DWords.dw1;
291 pResult->DWords.dw1 += uTmp.DWords.dw0;
292 if (pResult->DWords.dw1 < uTmp.DWords.dw0)
293 if (pResult->DWords.dw2++ == UINT32_MAX)
294 pResult->DWords.dw3++;
295
296 /* Multiply uLoValue1 and uHiValue1 by uHiValue2. */
297 uTmp.u = (uint64_t)uLoValue1 * uHiValue2;
298 pResult->DWords.dw1 += uTmp.DWords.dw0;
299 if (pResult->DWords.dw1 < uTmp.DWords.dw0)
300 if (pResult->DWords.dw2++ == UINT32_MAX)
301 pResult->DWords.dw3++;
302
303 pResult->DWords.dw2 += uTmp.DWords.dw1;
304 if (pResult->DWords.dw2 < uTmp.DWords.dw1)
305 pResult->DWords.dw3++;
306
307 pResult->s.Hi += (uint64_t)uHiValue1 * uHiValue2;
308#endif
309 return pResult;
310}
311
312
313DECLINLINE(PRTUINT128U) RTUInt128DivRem(PRTUINT128U pQuotient, PRTUINT128U pRemainder, PCRTUINT128U pValue1, PCRTUINT128U pValue2);
314
315/**
316 * Divides a 128-bit unsigned integer value by another.
317 *
318 * @returns pResult
319 * @param pResult The result variable.
320 * @param pValue1 The dividend value.
321 * @param pValue2 The divisor value.
322 */
323DECLINLINE(PRTUINT128U) RTUInt128Div(PRTUINT128U pResult, PCRTUINT128U pValue1, PCRTUINT128U pValue2)
324{
325 RTUINT128U Ignored;
326 return RTUInt128DivRem(pResult, &Ignored, pValue1, pValue2);
327}
328
329
330/**
331 * Divides a 128-bit unsigned integer value by another, returning the remainder.
332 *
333 * @returns pResult
334 * @param pResult The result variable (remainder).
335 * @param pValue1 The dividend value.
336 * @param pValue2 The divisor value.
337 */
338DECLINLINE(PRTUINT128U) RTUInt128Mod(PRTUINT128U pResult, PCRTUINT128U pValue1, PCRTUINT128U pValue2)
339{
340 RTUINT128U Ignored;
341 RTUInt128DivRem(&Ignored, pResult, pValue1, pValue2);
342 return pResult;
343}
344
345
346/**
347 * Bitwise AND of two 128-bit unsigned integer values.
348 *
349 * @returns pResult
350 * @param pResult The result variable.
351 * @param pValue1 The first value.
352 * @param pValue2 The second value.
353 */
354DECLINLINE(PRTUINT128U) RTUInt128And(PRTUINT128U pResult, PCRTUINT128U pValue1, PCRTUINT128U pValue2)
355{
356 pResult->s.Hi = pValue1->s.Hi & pValue2->s.Hi;
357 pResult->s.Lo = pValue1->s.Lo & pValue2->s.Lo;
358 return pResult;
359}
360
361
362/**
363 * Bitwise OR of two 128-bit unsigned integer values.
364 *
365 * @returns pResult
366 * @param pResult The result variable.
367 * @param pValue1 The first value.
368 * @param pValue2 The second value.
369 */
370DECLINLINE(PRTUINT128U) RTUInt128Or( PRTUINT128U pResult, PCRTUINT128U pValue1, PCRTUINT128U pValue2)
371{
372 pResult->s.Hi = pValue1->s.Hi | pValue2->s.Hi;
373 pResult->s.Lo = pValue1->s.Lo | pValue2->s.Lo;
374 return pResult;
375}
376
377
378/**
379 * Bitwise XOR of two 128-bit unsigned integer values.
380 *
381 * @returns pResult
382 * @param pResult The result variable.
383 * @param pValue1 The first value.
384 * @param pValue2 The second value.
385 */
386DECLINLINE(PRTUINT128U) RTUInt128Xor(PRTUINT128U pResult, PCRTUINT128U pValue1, PCRTUINT128U pValue2)
387{
388 pResult->s.Hi = pValue1->s.Hi ^ pValue2->s.Hi;
389 pResult->s.Lo = pValue1->s.Lo ^ pValue2->s.Lo;
390 return pResult;
391}
392
393
394/**
395 * Shifts a 128-bit unsigned integer value @a cBits to the left.
396 *
397 * @returns pResult
398 * @param pResult The result variable.
399 * @param pValue The value to shift.
400 * @param cBits The number of bits to shift it.
401 */
402DECLINLINE(PRTUINT128U) RTUInt128ShiftLeft(PRTUINT128U pResult, PCRTUINT128U pValue, int cBits)
403{
404 cBits &= 127;
405 if (cBits < 64)
406 {
407 pResult->s.Lo = pValue->s.Lo << cBits;
408 pResult->s.Hi = (pValue->s.Hi << cBits) | (pValue->s.Lo >> (64 - cBits));
409 }
410 else
411 {
412 pResult->s.Lo = 0;
413 pResult->s.Hi = pValue->s.Lo << (cBits - 64);
414 }
415 return pResult;
416}
417
418
419/**
420 * Shifts a 128-bit unsigned integer value @a cBits to the right.
421 *
422 * @returns pResult
423 * @param pResult The result variable.
424 * @param pValue The value to shift.
425 * @param cBits The number of bits to shift it.
426 */
427DECLINLINE(PRTUINT128U) RTUInt128ShiftRight(PRTUINT128U pResult, PCRTUINT128U pValue, int cBits)
428{
429 cBits &= 127;
430 if (cBits < 64)
431 {
432 pResult->s.Hi = pValue->s.Hi >> cBits;
433 pResult->s.Lo = (pValue->s.Lo >> cBits) | (pValue->s.Hi << (64 - cBits));
434 }
435 else
436 {
437 pResult->s.Hi = 0;
438 pResult->s.Lo = pValue->s.Hi >> (cBits - 64);
439 }
440 return pResult;
441}
442
443
444/**
445 * Boolean not (result 0 or 1).
446 *
447 * @returns pResult.
448 * @param pResult The result variable.
449 * @param pValue The value.
450 */
451DECLINLINE(PRTUINT128U) RTUInt128BooleanNot(PRTUINT128U pResult, PCRTUINT128U pValue)
452{
453 pResult->s.Lo = pValue->s.Lo || pValue->s.Hi ? 0 : 1;
454 pResult->s.Hi = 0;
455 return pResult;
456}
457
458
459/**
460 * Bitwise not (flips each bit of the 128 bits).
461 *
462 * @returns pResult.
463 * @param pResult The result variable.
464 * @param pValue The value.
465 */
466DECLINLINE(PRTUINT128U) RTUInt128BitwiseNot(PRTUINT128U pResult, PCRTUINT128U pValue)
467{
468 pResult->s.Hi = ~pValue->s.Hi;
469 pResult->s.Lo = ~pValue->s.Lo;
470 return pResult;
471}
472
473
474/**
475 * Assigns one 128-bit unsigned integer value to another.
476 *
477 * @returns pResult
478 * @param pResult The result variable.
479 * @param pValue The value to assign.
480 */
481DECLINLINE(PRTUINT128U) RTUInt128Assign(PRTUINT128U pResult, PCRTUINT128U pValue)
482{
483#if ARCH_BITS >= 64
484 pResult->s.Hi = pValue->s.Hi;
485 pResult->s.Lo = pValue->s.Lo;
486#else
487 pResult->DWords.dw0 = pValue->DWords.dw0;
488 pResult->DWords.dw1 = pValue->DWords.dw1;
489 pResult->DWords.dw2 = pValue->DWords.dw2;
490 pResult->DWords.dw3 = pValue->DWords.dw3;
491#endif
492 return pResult;
493}
494
495
496/**
497 * Assigns a boolean value to 128-bit unsigned integer.
498 *
499 * @returns pValueResult
500 * @param pValueResult The result variable.
501 * @param fValue The boolean value.
502 */
503DECLINLINE(PRTUINT128U) RTUInt128AssignBoolean(PRTUINT128U pValueResult, bool fValue)
504{
505#if ARCH_BITS >= 64
506 pValueResult->s.Lo = fValue;
507 pValueResult->s.Hi = 0;
508#else
509 pValueResult->DWords.dw0 = fValue;
510 pValueResult->DWords.dw1 = 0;
511 pValueResult->DWords.dw2 = 0;
512 pValueResult->DWords.dw3 = 0;
513#endif
514 return pValueResult;
515}
516
517
518/**
519 * Assigns a 8-bit unsigned integer value to 128-bit unsigned integer.
520 *
521 * @returns pValueResult
522 * @param pValueResult The result variable.
523 * @param u8Value The 8-bit unsigned integer value.
524 */
525DECLINLINE(PRTUINT128U) RTUInt128AssignU8(PRTUINT128U pValueResult, uint8_t u8Value)
526{
527#if ARCH_BITS >= 64
528 pValueResult->s.Lo = u8Value;
529 pValueResult->s.Hi = 0;
530#else
531 pValueResult->DWords.dw0 = u8Value;
532 pValueResult->DWords.dw1 = 0;
533 pValueResult->DWords.dw2 = 0;
534 pValueResult->DWords.dw3 = 0;
535#endif
536 return pValueResult;
537}
538
539
540/**
541 * Assigns a 16-bit unsigned integer value to 128-bit unsigned integer.
542 *
543 * @returns pValueResult
544 * @param pValueResult The result variable.
545 * @param u16Value The 16-bit unsigned integer value.
546 */
547DECLINLINE(PRTUINT128U) RTUInt128AssignU16(PRTUINT128U pValueResult, uint16_t u16Value)
548{
549#if ARCH_BITS >= 64
550 pValueResult->s.Lo = u16Value;
551 pValueResult->s.Hi = 0;
552#else
553 pValueResult->DWords.dw0 = u16Value;
554 pValueResult->DWords.dw1 = 0;
555 pValueResult->DWords.dw2 = 0;
556 pValueResult->DWords.dw3 = 0;
557#endif
558 return pValueResult;
559}
560
561
562/**
563 * Assigns a 32-bit unsigned integer value to 128-bit unsigned integer.
564 *
565 * @returns pValueResult
566 * @param pValueResult The result variable.
567 * @param u32Value The 32-bit unsigned integer value.
568 */
569DECLINLINE(PRTUINT128U) RTUInt128AssignU32(PRTUINT128U pValueResult, uint32_t u32Value)
570{
571#if ARCH_BITS >= 64
572 pValueResult->s.Lo = u32Value;
573 pValueResult->s.Hi = 0;
574#else
575 pValueResult->DWords.dw0 = u32Value;
576 pValueResult->DWords.dw1 = 0;
577 pValueResult->DWords.dw2 = 0;
578 pValueResult->DWords.dw3 = 0;
579#endif
580 return pValueResult;
581}
582
583
584/**
585 * Assigns a 64-bit unsigned integer value to 128-bit unsigned integer.
586 *
587 * @returns pValueResult
588 * @param pValueResult The result variable.
589 * @param u64Value The 64-bit unsigned integer value.
590 */
591DECLINLINE(PRTUINT128U) RTUInt128AssignU64(PRTUINT128U pValueResult, uint64_t u64Value)
592{
593 pValueResult->s.Lo = u64Value;
594 pValueResult->s.Hi = 0;
595 return pValueResult;
596}
597
598
599/**
600 * Adds two 128-bit unsigned integer values, storing the result in the first.
601 *
602 * @returns pValue1Result.
603 * @param pValue1Result The first value and result.
604 * @param pValue2 The second value.
605 */
606DECLINLINE(PRTUINT128U) RTUInt128AssignAdd(PRTUINT128U pValue1Result, PCRTUINT128U pValue2)
607{
608 uint64_t const uTmp = pValue1Result->s.Lo;
609 pValue1Result->s.Lo += pValue2->s.Lo;
610 if (pValue1Result->s.Lo < uTmp)
611 pValue1Result->s.Hi++;
612 pValue1Result->s.Hi += pValue2->s.Hi;
613 return pValue1Result;
614}
615
616
617/**
618 * Adds a 64-bit unsigned integer value to a 128-bit unsigned integer values,
619 * storing the result in the 128-bit one.
620 *
621 * @returns pValue1Result.
622 * @param pValue1Result The first value and result.
623 * @param uValue2 The second value, 64-bit.
624 */
625DECLINLINE(PRTUINT128U) RTUInt128AssignAddU64(PRTUINT128U pValue1Result, uint64_t uValue2)
626{
627 pValue1Result->s.Lo += uValue2;
628 if (pValue1Result->s.Lo < uValue2)
629 pValue1Result->s.Hi++;
630 return pValue1Result;
631}
632
633
634/**
635 * Subtracts two 128-bit unsigned integer values, storing the result in the
636 * first.
637 *
638 * @returns pValue1Result.
639 * @param pValue1Result The minuend value and result.
640 * @param pValue2 The subtrahend value.
641 */
642DECLINLINE(PRTUINT128U) RTUInt128AssignSub(PRTUINT128U pValue1Result, PCRTUINT128U pValue2)
643{
644 uint64_t const uTmp = pValue1Result->s.Lo;
645 pValue1Result->s.Lo -= pValue2->s.Lo;
646 if (pValue1Result->s.Lo > uTmp)
647 pValue1Result->s.Hi--;
648 pValue1Result->s.Hi -= pValue2->s.Hi;
649 return pValue1Result;
650}
651
652
653/**
654 * Negates a 128 number, storing the result in the input.
655 *
656 * @returns pValueResult.
657 * @param pValueResult The value to negate.
658 */
659DECLINLINE(PRTUINT128U) RTUInt128AssignNeg(PRTUINT128U pValueResult)
660{
661 /* result = 0 - value */
662 if (pValueResult->s.Lo != 0)
663 {
664 pValueResult->s.Lo = UINT64_C(0) - pValueResult->s.Lo;
665 pValueResult->s.Hi = UINT64_MAX - pValueResult->s.Hi;
666 }
667 else
668 pValueResult->s.Hi = UINT64_C(0) - pValueResult->s.Hi;
669 return pValueResult;
670}
671
672
673/**
674 * Multiplies two 128-bit unsigned integer values, storing the result in the
675 * first.
676 *
677 * @returns pValue1Result.
678 * @param pValue1Result The first value and result.
679 * @param pValue2 The second value.
680 */
681DECLINLINE(PRTUINT128U) RTUInt128AssignMul(PRTUINT128U pValue1Result, PCRTUINT128U pValue2)
682{
683 RTUINT128U Result;
684 RTUInt128Mul(&Result, pValue1Result, pValue2);
685 *pValue1Result = Result;
686 return pValue1Result;
687}
688
689
690/**
691 * Divides a 128-bit unsigned integer value by another, storing the result in
692 * the first.
693 *
694 * @returns pValue1Result.
695 * @param pValue1Result The dividend value and result.
696 * @param pValue2 The divisor value.
697 */
698DECLINLINE(PRTUINT128U) RTUInt128AssignDiv(PRTUINT128U pValue1Result, PCRTUINT128U pValue2)
699{
700 RTUINT128U Result;
701 RTUINT128U Ignored;
702 RTUInt128DivRem(&Result, &Ignored, pValue1Result, pValue2);
703 *pValue1Result = Result;
704 return pValue1Result;
705}
706
707
708/**
709 * Divides a 128-bit unsigned integer value by another, storing the remainder in
710 * the first.
711 *
712 * @returns pValue1Result.
713 * @param pValue1Result The dividend value and result (remainder).
714 * @param pValue2 The divisor value.
715 */
716DECLINLINE(PRTUINT128U) RTUInt128AssignMod(PRTUINT128U pValue1Result, PCRTUINT128U pValue2)
717{
718 RTUINT128U Ignored;
719 RTUINT128U Result;
720 RTUInt128DivRem(&Ignored, &Result, pValue1Result, pValue2);
721 *pValue1Result = Result;
722 return pValue1Result;
723}
724
725
726/**
727 * Performs a bitwise AND of two 128-bit unsigned integer values and assigned
728 * the result to the first one.
729 *
730 * @returns pValue1Result.
731 * @param pValue1Result The first value and result.
732 * @param pValue2 The second value.
733 */
734DECLINLINE(PRTUINT128U) RTUInt128AssignAnd(PRTUINT128U pValue1Result, PCRTUINT128U pValue2)
735{
736#if ARCH_BITS >= 64
737 pValue1Result->s.Hi &= pValue2->s.Hi;
738 pValue1Result->s.Lo &= pValue2->s.Lo;
739#else
740 pValue1Result->DWords.dw0 &= pValue2->DWords.dw0;
741 pValue1Result->DWords.dw1 &= pValue2->DWords.dw1;
742 pValue1Result->DWords.dw2 &= pValue2->DWords.dw2;
743 pValue1Result->DWords.dw3 &= pValue2->DWords.dw3;
744#endif
745 return pValue1Result;
746}
747
748
749/**
750 * Performs a bitwise AND of a 128-bit unsigned integer value and a mask made
751 * up of the first N bits, assigning the result to the the 128-bit value.
752 *
753 * @returns pValueResult.
754 * @param pValueResult The value and result.
755 * @param cBits The number of bits to AND (counting from the first
756 * bit).
757 */
758DECLINLINE(PRTUINT128U) RTUInt128AssignAndNFirstBits(PRTUINT128U pValueResult, unsigned cBits)
759{
760 if (cBits <= 64)
761 {
762 if (cBits != 64)
763 pValueResult->s.Lo &= (RT_BIT_64(cBits) - 1);
764 pValueResult->s.Hi = 0;
765 }
766 else if (cBits < 128)
767 pValueResult->s.Hi &= (RT_BIT_64(cBits - 64) - 1);
768/** @todo \#if ARCH_BITS >= 64 */
769 return pValueResult;
770}
771
772
773/**
774 * Performs a bitwise OR of two 128-bit unsigned integer values and assigned
775 * the result to the first one.
776 *
777 * @returns pValue1Result.
778 * @param pValue1Result The first value and result.
779 * @param pValue2 The second value.
780 */
781DECLINLINE(PRTUINT128U) RTUInt128AssignOr(PRTUINT128U pValue1Result, PCRTUINT128U pValue2)
782{
783#if ARCH_BITS >= 64
784 pValue1Result->s.Hi |= pValue2->s.Hi;
785 pValue1Result->s.Lo |= pValue2->s.Lo;
786#else
787 pValue1Result->DWords.dw0 |= pValue2->DWords.dw0;
788 pValue1Result->DWords.dw1 |= pValue2->DWords.dw1;
789 pValue1Result->DWords.dw2 |= pValue2->DWords.dw2;
790 pValue1Result->DWords.dw3 |= pValue2->DWords.dw3;
791#endif
792 return pValue1Result;
793}
794
795
796/**
797 * ORs in a bit and assign the result to the input value.
798 *
799 * @returns pValue1Result.
800 * @param pValue1Result The first value and result.
801 * @param iBit The bit to set (0 based).
802 */
803DECLINLINE(PRTUINT128U) RTUInt128AssignOrBit(PRTUINT128U pValue1Result, uint32_t iBit)
804{
805#if ARCH_BITS >= 64
806 if (iBit >= 64)
807 pValue1Result->s.Hi |= RT_BIT_64(iBit - 64);
808 else
809 pValue1Result->s.Lo |= RT_BIT_64(iBit);
810#else
811 if (iBit >= 64)
812 {
813 if (iBit >= 96)
814 pValue1Result->DWords.dw3 |= RT_BIT_32(iBit - 96);
815 else
816 pValue1Result->DWords.dw2 |= RT_BIT_32(iBit - 64);
817 }
818 else
819 {
820 if (iBit >= 32)
821 pValue1Result->DWords.dw1 |= RT_BIT_32(iBit - 32);
822 else
823 pValue1Result->DWords.dw0 |= RT_BIT_32(iBit);
824 }
825#endif
826 return pValue1Result;
827}
828
829
830
831/**
832 * Performs a bitwise XOR of two 128-bit unsigned integer values and assigned
833 * the result to the first one.
834 *
835 * @returns pValue1Result.
836 * @param pValue1Result The first value and result.
837 * @param pValue2 The second value.
838 */
839DECLINLINE(PRTUINT128U) RTUInt128AssignXor(PRTUINT128U pValue1Result, PCRTUINT128U pValue2)
840{
841#if ARCH_BITS >= 64
842 pValue1Result->s.Hi ^= pValue2->s.Hi;
843 pValue1Result->s.Lo ^= pValue2->s.Lo;
844#else
845 pValue1Result->DWords.dw0 ^= pValue2->DWords.dw0;
846 pValue1Result->DWords.dw1 ^= pValue2->DWords.dw1;
847 pValue1Result->DWords.dw2 ^= pValue2->DWords.dw2;
848 pValue1Result->DWords.dw3 ^= pValue2->DWords.dw3;
849#endif
850 return pValue1Result;
851}
852
853
854/**
855 * Performs a bitwise left shift on a 128-bit unsigned integer value, assigning
856 * the result to it.
857 *
858 * @returns pValueResult.
859 * @param pValueResult The first value and result.
860 * @param cBits The number of bits to shift.
861 */
862DECLINLINE(PRTUINT128U) RTUInt128AssignShiftLeft(PRTUINT128U pValueResult, int cBits)
863{
864 RTUINT128U const InVal = *pValueResult;
865/** @todo \#if ARCH_BITS >= 64 */
866 if (cBits > 0)
867 {
868 /* (left shift) */
869 if (cBits >= 128)
870 RTUInt128SetZero(pValueResult);
871 else if (cBits >= 64)
872 {
873 pValueResult->s.Lo = 0;
874 pValueResult->s.Hi = InVal.s.Lo << (cBits - 64);
875 }
876 else
877 {
878 pValueResult->s.Hi = InVal.s.Hi << cBits;
879 pValueResult->s.Hi |= InVal.s.Lo >> (64 - cBits);
880 pValueResult->s.Lo = InVal.s.Lo << cBits;
881 }
882 }
883 else if (cBits < 0)
884 {
885 /* (right shift) */
886 cBits = -cBits;
887 if (cBits >= 128)
888 RTUInt128SetZero(pValueResult);
889 else if (cBits >= 64)
890 {
891 pValueResult->s.Hi = 0;
892 pValueResult->s.Lo = InVal.s.Hi >> (cBits - 64);
893 }
894 else
895 {
896 pValueResult->s.Lo = InVal.s.Lo >> cBits;
897 pValueResult->s.Lo |= InVal.s.Hi << (64 - cBits);
898 pValueResult->s.Hi = InVal.s.Hi >> cBits;
899 }
900 }
901 return pValueResult;
902}
903
904
905/**
906 * Performs a bitwise left shift on a 128-bit unsigned integer value, assigning
907 * the result to it.
908 *
909 * @returns pValueResult.
910 * @param pValueResult The first value and result.
911 * @param cBits The number of bits to shift.
912 */
913DECLINLINE(PRTUINT128U) RTUInt128AssignShiftRight(PRTUINT128U pValueResult, int cBits)
914{
915 return RTUInt128AssignShiftLeft(pValueResult, -cBits);
916}
917
918
919/**
920 * Performs a bitwise NOT on a 128-bit unsigned integer value, assigning the
921 * result to it.
922 *
923 * @returns pValueResult
924 * @param pValueResult The value and result.
925 */
926DECLINLINE(PRTUINT128U) RTUInt128AssignBitwiseNot(PRTUINT128U pValueResult)
927{
928#if ARCH_BITS >= 64
929 pValueResult->s.Hi = ~pValueResult->s.Hi;
930 pValueResult->s.Lo = ~pValueResult->s.Lo;
931#else
932 pValueResult->DWords.dw0 = ~pValueResult->DWords.dw0;
933 pValueResult->DWords.dw1 = ~pValueResult->DWords.dw1;
934 pValueResult->DWords.dw2 = ~pValueResult->DWords.dw2;
935 pValueResult->DWords.dw3 = ~pValueResult->DWords.dw3;
936#endif
937 return pValueResult;
938}
939
940
941/**
942 * Performs a boolean NOT on a 128-bit unsigned integer value, assigning the
943 * result to it.
944 *
945 * @returns pValueResult
946 * @param pValueResult The value and result.
947 */
948DECLINLINE(PRTUINT128U) RTUInt128AssignBooleanNot(PRTUINT128U pValueResult)
949{
950 return RTUInt128AssignBoolean(pValueResult, RTUInt128IsZero(pValueResult));
951}
952
953
954/**
955 * Compares two 128-bit unsigned integer values.
956 *
957 * @retval 0 if equal.
958 * @retval -1 if the first value is smaller than the second.
959 * @retval 1 if the first value is larger than the second.
960 *
961 * @param pValue1 The first value.
962 * @param pValue2 The second value.
963 */
964DECLINLINE(int) RTUInt128Compare(PCRTUINT128U pValue1, PCRTUINT128U pValue2)
965{
966#if ARCH_BITS >= 64
967 if (pValue1->s.Hi != pValue2->s.Hi)
968 return pValue1->s.Hi > pValue2->s.Hi ? 1 : -1;
969 if (pValue1->s.Lo != pValue2->s.Lo)
970 return pValue1->s.Lo > pValue2->s.Lo ? 1 : -1;
971 return 0;
972#else
973 if (pValue1->DWords.dw3 != pValue2->DWords.dw3)
974 return pValue1->DWords.dw3 > pValue2->DWords.dw3 ? 1 : -1;
975 if (pValue1->DWords.dw2 != pValue2->DWords.dw2)
976 return pValue1->DWords.dw2 > pValue2->DWords.dw2 ? 1 : -1;
977 if (pValue1->DWords.dw1 != pValue2->DWords.dw1)
978 return pValue1->DWords.dw1 > pValue2->DWords.dw1 ? 1 : -1;
979 if (pValue1->DWords.dw0 != pValue2->DWords.dw0)
980 return pValue1->DWords.dw0 > pValue2->DWords.dw0 ? 1 : -1;
981 return 0;
982#endif
983}
984
985
986/**
987 * Tests if a 128-bit unsigned integer value is smaller than another.
988 *
989 * @returns true if the first value is smaller, false if not.
990 * @param pValue1 The first value.
991 * @param pValue2 The second value.
992 */
993DECLINLINE(bool) RTUInt128IsSmaller(PCRTUINT128U pValue1, PCRTUINT128U pValue2)
994{
995#if ARCH_BITS >= 64
996 return pValue1->s.Hi < pValue2->s.Hi
997 || ( pValue1->s.Hi == pValue2->s.Hi
998 && pValue1->s.Lo < pValue2->s.Lo);
999#else
1000 return pValue1->DWords.dw3 < pValue2->DWords.dw3
1001 || ( pValue1->DWords.dw3 == pValue2->DWords.dw3
1002 && ( pValue1->DWords.dw2 < pValue2->DWords.dw2
1003 || ( pValue1->DWords.dw2 == pValue2->DWords.dw2
1004 && ( pValue1->DWords.dw1 < pValue2->DWords.dw1
1005 || ( pValue1->DWords.dw1 == pValue2->DWords.dw1
1006 && pValue1->DWords.dw0 < pValue2->DWords.dw0)))));
1007#endif
1008}
1009
1010
1011/**
1012 * Tests if a 128-bit unsigned integer value is larger than another.
1013 *
1014 * @returns true if the first value is larger, false if not.
1015 * @param pValue1 The first value.
1016 * @param pValue2 The second value.
1017 */
1018DECLINLINE(bool) RTUInt128IsLarger(PCRTUINT128U pValue1, PCRTUINT128U pValue2)
1019{
1020#if ARCH_BITS >= 64
1021 return pValue1->s.Hi > pValue2->s.Hi
1022 || ( pValue1->s.Hi == pValue2->s.Hi
1023 && pValue1->s.Lo > pValue2->s.Lo);
1024#else
1025 return pValue1->DWords.dw3 > pValue2->DWords.dw3
1026 || ( pValue1->DWords.dw3 == pValue2->DWords.dw3
1027 && ( pValue1->DWords.dw2 > pValue2->DWords.dw2
1028 || ( pValue1->DWords.dw2 == pValue2->DWords.dw2
1029 && ( pValue1->DWords.dw1 > pValue2->DWords.dw1
1030 || ( pValue1->DWords.dw1 == pValue2->DWords.dw1
1031 && pValue1->DWords.dw0 > pValue2->DWords.dw0)))));
1032#endif
1033}
1034
1035
1036/**
1037 * Tests if a 128-bit unsigned integer value is larger or equal than another.
1038 *
1039 * @returns true if the first value is larger or equal, false if not.
1040 * @param pValue1 The first value.
1041 * @param pValue2 The second value.
1042 */
1043DECLINLINE(bool) RTUInt128IsLargerOrEqual(PCRTUINT128U pValue1, PCRTUINT128U pValue2)
1044{
1045#if ARCH_BITS >= 64
1046 return pValue1->s.Hi > pValue2->s.Hi
1047 || ( pValue1->s.Hi == pValue2->s.Hi
1048 && pValue1->s.Lo >= pValue2->s.Lo);
1049#else
1050 return pValue1->DWords.dw3 > pValue2->DWords.dw3
1051 || ( pValue1->DWords.dw3 == pValue2->DWords.dw3
1052 && ( pValue1->DWords.dw2 > pValue2->DWords.dw2
1053 || ( pValue1->DWords.dw2 == pValue2->DWords.dw2
1054 && ( pValue1->DWords.dw1 > pValue2->DWords.dw1
1055 || ( pValue1->DWords.dw1 == pValue2->DWords.dw1
1056 && pValue1->DWords.dw0 >= pValue2->DWords.dw0)))));
1057#endif
1058}
1059
1060
1061/**
1062 * Tests if two 128-bit unsigned integer values not equal.
1063 *
1064 * @returns true if equal, false if not equal.
1065 * @param pValue1 The first value.
1066 * @param pValue2 The second value.
1067 */
1068DECLINLINE(bool) RTUInt128IsEqual(PCRTUINT128U pValue1, PCRTUINT128U pValue2)
1069{
1070#if ARCH_BITS >= 64
1071 return pValue1->s.Hi == pValue2->s.Hi
1072 && pValue1->s.Lo == pValue2->s.Lo;
1073#else
1074 return pValue1->DWords.dw0 == pValue2->DWords.dw0
1075 && pValue1->DWords.dw1 == pValue2->DWords.dw1
1076 && pValue1->DWords.dw2 == pValue2->DWords.dw2
1077 && pValue1->DWords.dw3 == pValue2->DWords.dw3;
1078#endif
1079}
1080
1081
1082/**
1083 * Tests if two 128-bit unsigned integer values are not equal.
1084 *
1085 * @returns true if not equal, false if equal.
1086 * @param pValue1 The first value.
1087 * @param pValue2 The second value.
1088 */
1089DECLINLINE(bool) RTUInt128IsNotEqual(PCRTUINT128U pValue1, PCRTUINT128U pValue2)
1090{
1091 return !RTUInt128IsEqual(pValue1, pValue2);
1092}
1093
1094
1095/**
1096 * Sets a bit in a 128-bit unsigned integer type.
1097 *
1098 * @returns pValueResult.
1099 * @param pValueResult The input and output value.
1100 * @param iBit The bit to set.
1101 */
1102DECLINLINE(PRTUINT128U) RTUInt128BitSet(PRTUINT128U pValueResult, unsigned iBit)
1103{
1104 if (iBit < 64)
1105 {
1106#if ARCH_BITS >= 64
1107 pValueResult->s.Lo |= RT_BIT_64(iBit);
1108#else
1109 if (iBit < 32)
1110 pValueResult->DWords.dw0 |= RT_BIT_32(iBit);
1111 else
1112 pValueResult->DWords.dw1 |= RT_BIT_32(iBit - 32);
1113#endif
1114 }
1115 else if (iBit < 128)
1116 {
1117#if ARCH_BITS >= 64
1118 pValueResult->s.Hi |= RT_BIT_64(iBit - 64);
1119#else
1120 if (iBit < 96)
1121 pValueResult->DWords.dw2 |= RT_BIT_32(iBit - 64);
1122 else
1123 pValueResult->DWords.dw3 |= RT_BIT_32(iBit - 96);
1124#endif
1125 }
1126 return pValueResult;
1127}
1128
1129
1130/**
1131 * Sets a bit in a 128-bit unsigned integer type.
1132 *
1133 * @returns pValueResult.
1134 * @param pValueResult The input and output value.
1135 * @param iBit The bit to set.
1136 */
1137DECLINLINE(PRTUINT128U) RTUInt128BitClear(PRTUINT128U pValueResult, unsigned iBit)
1138{
1139 if (iBit < 64)
1140 {
1141#if ARCH_BITS >= 64
1142 pValueResult->s.Lo &= ~RT_BIT_64(iBit);
1143#else
1144 if (iBit < 32)
1145 pValueResult->DWords.dw0 &= ~RT_BIT_32(iBit);
1146 else
1147 pValueResult->DWords.dw1 &= ~RT_BIT_32(iBit - 32);
1148#endif
1149 }
1150 else if (iBit < 128)
1151 {
1152#if ARCH_BITS >= 64
1153 pValueResult->s.Hi &= ~RT_BIT_64(iBit - 64);
1154#else
1155 if (iBit < 96)
1156 pValueResult->DWords.dw2 &= ~RT_BIT_32(iBit - 64);
1157 else
1158 pValueResult->DWords.dw3 &= ~RT_BIT_32(iBit - 96);
1159#endif
1160 }
1161 return pValueResult;
1162}
1163
1164
1165/**
1166 * Tests if a bit in a 128-bit unsigned integer value is set.
1167 *
1168 * @returns pValueResult.
1169 * @param pValueResult The input and output value.
1170 * @param iBit The bit to test.
1171 */
1172DECLINLINE(bool) RTUInt128BitTest(PRTUINT128U pValueResult, unsigned iBit)
1173{
1174 bool fRc;
1175 if (iBit < 64)
1176 {
1177#if ARCH_BITS >= 64
1178 fRc = RT_BOOL(pValueResult->s.Lo & RT_BIT_64(iBit));
1179#else
1180 if (iBit < 32)
1181 fRc = RT_BOOL(pValueResult->DWords.dw0 & RT_BIT_32(iBit));
1182 else
1183 fRc = RT_BOOL(pValueResult->DWords.dw1 & RT_BIT_32(iBit - 32));
1184#endif
1185 }
1186 else if (iBit < 128)
1187 {
1188#if ARCH_BITS >= 64
1189 fRc = RT_BOOL(pValueResult->s.Hi & RT_BIT_64(iBit - 64));
1190#else
1191 if (iBit < 96)
1192 fRc = RT_BOOL(pValueResult->DWords.dw2 & RT_BIT_32(iBit - 64));
1193 else
1194 fRc = RT_BOOL(pValueResult->DWords.dw3 & RT_BIT_32(iBit - 96));
1195#endif
1196 }
1197 else
1198 fRc = false;
1199 return fRc;
1200}
1201
1202
1203/**
1204 * Set a range of bits a 128-bit unsigned integer value.
1205 *
1206 * @returns pValueResult.
1207 * @param pValueResult The input and output value.
1208 * @param iFirstBit The first bit to test.
1209 * @param cBits The number of bits to set.
1210 */
1211DECLINLINE(PRTUINT128U) RTUInt128BitSetRange(PRTUINT128U pValueResult, unsigned iFirstBit, unsigned cBits)
1212{
1213 /* bounds check & fix. */
1214 if (iFirstBit < 128)
1215 {
1216 if (iFirstBit + cBits > 128)
1217 cBits = 128 - iFirstBit;
1218
1219#if ARCH_BITS >= 64
1220 if (iFirstBit + cBits < 64)
1221 pValueResult->s.Lo |= (RT_BIT_64(cBits) - 1) << iFirstBit;
1222 else if (iFirstBit + cBits < 128 && iFirstBit >= 64)
1223 pValueResult->s.Hi |= (RT_BIT_64(cBits) - 1) << (iFirstBit - 64);
1224 else
1225#else
1226 if (iFirstBit + cBits < 32)
1227 pValueResult->DWords.dw0 |= (RT_BIT_32(cBits) - 1) << iFirstBit;
1228 else if (iFirstBit + cBits < 64 && iFirstBit >= 32)
1229 pValueResult->DWords.dw1 |= (RT_BIT_32(cBits) - 1) << (iFirstBit - 32);
1230 else if (iFirstBit + cBits < 96 && iFirstBit >= 64)
1231 pValueResult->DWords.dw2 |= (RT_BIT_32(cBits) - 1) << (iFirstBit - 64);
1232 else if (iFirstBit + cBits < 128 && iFirstBit >= 96)
1233 pValueResult->DWords.dw3 |= (RT_BIT_32(cBits) - 1) << (iFirstBit - 96);
1234 else
1235#endif
1236 while (cBits-- > 0)
1237 RTUInt128BitSet(pValueResult, iFirstBit++);
1238 }
1239 return pValueResult;
1240}
1241
1242
1243/**
1244 * Test if all the bits of a 128-bit unsigned integer value are set.
1245 *
1246 * @returns true if they are, false if they aren't.
1247 * @param pValue The input and output value.
1248 */
1249DECLINLINE(bool) RTUInt128BitAreAllSet(PRTUINT128U pValue)
1250{
1251#if ARCH_BITS >= 64
1252 return pValue->s.Hi == UINT64_MAX
1253 && pValue->s.Lo == UINT64_MAX;
1254#else
1255 return pValue->DWords.dw0 == UINT32_MAX
1256 && pValue->DWords.dw1 == UINT32_MAX
1257 && pValue->DWords.dw2 == UINT32_MAX
1258 && pValue->DWords.dw3 == UINT32_MAX;
1259#endif
1260}
1261
1262
1263/**
1264 * Test if all the bits of a 128-bit unsigned integer value are clear.
1265 *
1266 * @returns true if they are, false if they aren't.
1267 * @param pValue The input and output value.
1268 */
1269DECLINLINE(bool) RTUInt128BitAreAllClear(PRTUINT128U pValue)
1270{
1271#if ARCH_BITS >= 64
1272 return pValue->s.Hi == 0
1273 && pValue->s.Lo == 0;
1274#else
1275 return pValue->DWords.dw0 == 0
1276 && pValue->DWords.dw1 == 0
1277 && pValue->DWords.dw2 == 0
1278 && pValue->DWords.dw3 == 0;
1279#endif
1280}
1281
1282
1283DECLINLINE(uint32_t) RTUInt128BitCount(PCRTUINT128U pValue)
1284{
1285 uint32_t cBits;
1286 if (pValue->s.Hi != 0)
1287 {
1288 if (pValue->DWords.dw3)
1289 cBits = 96 + ASMBitLastSetU32(pValue->DWords.dw3);
1290 else
1291 cBits = 64 + ASMBitLastSetU32(pValue->DWords.dw2);
1292 }
1293 else
1294 {
1295 if (pValue->DWords.dw1)
1296 cBits = 32 + ASMBitLastSetU32(pValue->DWords.dw1);
1297 else
1298 cBits = 0 + ASMBitLastSetU32(pValue->DWords.dw0);
1299 }
1300 return cBits;
1301}
1302
1303
1304/**
1305 * Divides a 128-bit unsigned integer value by another, returning both quotient
1306 * and remainder.
1307 *
1308 * @returns pQuotient, NULL if pValue2 is 0.
1309 * @param pQuotient Where to return the quotient.
1310 * @param pRemainder Where to return the remainder.
1311 * @param pValue1 The dividend value.
1312 * @param pValue2 The divisor value.
1313 */
1314DECLINLINE(PRTUINT128U) RTUInt128DivRem(PRTUINT128U pQuotient, PRTUINT128U pRemainder, PCRTUINT128U pValue1, PCRTUINT128U pValue2)
1315{
1316 int iDiff;
1317
1318 /*
1319 * Sort out all the special cases first.
1320 */
1321 /* Divide by zero or 1? */
1322 if (!pValue2->s.Hi)
1323 {
1324 if (!pValue2->s.Lo)
1325 return NULL;
1326
1327 if (pValue2->s.Lo == 1)
1328 {
1329 RTUInt128SetZero(pRemainder);
1330 *pQuotient = *pValue1;
1331 return pQuotient;
1332 }
1333 /** @todo RTUint128DivModBy64 */
1334 }
1335
1336 /* Dividend is smaller? */
1337 iDiff = RTUInt128Compare(pValue1, pValue2);
1338 if (iDiff < 0)
1339 {
1340 *pRemainder = *pValue1;
1341 RTUInt128SetZero(pQuotient);
1342 }
1343
1344 /* The values are equal? */
1345 else if (iDiff == 0)
1346 {
1347 RTUInt128SetZero(pRemainder);
1348 RTUInt128AssignU64(pQuotient, 1);
1349 }
1350 else
1351 {
1352 /*
1353 * Prepare.
1354 */
1355 uint32_t iBitAdder = RTUInt128BitCount(pValue1) - RTUInt128BitCount(pValue2);
1356 RTUINT128U NormDivisor = *pValue2;
1357 if (iBitAdder)
1358 {
1359 RTUInt128ShiftLeft(&NormDivisor, pValue2, iBitAdder);
1360 if (RTUInt128IsLarger(&NormDivisor, pValue1))
1361 {
1362 RTUInt128AssignShiftRight(&NormDivisor, 1);
1363 iBitAdder--;
1364 }
1365 }
1366 else
1367 NormDivisor = *pValue2;
1368
1369 RTUInt128SetZero(pQuotient);
1370 *pRemainder = *pValue1;
1371
1372 /*
1373 * Do the division.
1374 */
1375 if (RTUInt128IsLargerOrEqual(pRemainder, pValue2))
1376 {
1377 for (;;)
1378 {
1379 if (RTUInt128IsLargerOrEqual(pRemainder, &NormDivisor))
1380 {
1381 RTUInt128AssignSub(pRemainder, &NormDivisor);
1382 RTUInt128AssignOrBit(pQuotient, iBitAdder);
1383 }
1384 if (RTUInt128IsSmaller(pRemainder, pValue2))
1385 break;
1386 RTUInt128AssignShiftRight(&NormDivisor, 1);
1387 iBitAdder--;
1388 }
1389 }
1390 }
1391 return pQuotient;
1392}
1393
1394
1395/** @} */
1396
1397RT_C_DECLS_END
1398
1399#endif /* !IPRT_INCLUDED_uint128_h */
1400
Note: See TracBrowser for help on using the repository browser.

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