VirtualBox

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

最後變更 在這個檔案從94511是 94511,由 vboxsync 提交於 3 年 前

IPRT: Added RTUInt128MulEx and RTUInt128MulU64Ex as well as a limited RTUInt256Xxx Api. bugref:9898

  • 屬性 svn:eol-style 設為 native
  • 屬性 svn:keywords 設為 Author Date Id Revision
檔案大小: 42.3 KB
 
1/** @file
2 * IPRT - RTUINT128U & uint128_t methods.
3 */
4
5/*
6 * Copyright (C) 2011-2022 Oracle Corporation
7 *
8 * This file is part of VirtualBox Open Source Edition (OSE), as
9 * available from http://www.alldomusa.eu.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(PCRTUINT128U 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
313/**
314 * Multiplies an 128-bit unsigned integer by a 64-bit unsigned integer value,
315 * returning a 256-bit result (top 64 bits are zero).
316 *
317 * @returns pResult
318 * @param pResult The result variable.
319 * @param pValue1 The first value.
320 * @param uValue2 The second value, 64-bit.
321 */
322#if defined(RT_ARCH_AMD64)
323RTDECL(PRTUINT256U) RTUInt128MulByU64Ex(PRTUINT256U pResult, PCRTUINT128U pValue1, uint64_t uValue2);
324#else
325DECLINLINE(PRTUINT256U) RTUInt128MulByU64Ex(PRTUINT256U pResult, PCRTUINT128U pValue1, uint64_t uValue2)
326{
327 /* multiply the two qwords in pValue1 by uValue2. */
328 uint64_t uTmp = 0;
329 pResult->QWords.qw0 = ASMMult2xU64Ret2xU64(pValue1->s.Lo, uValue2, &uTmp);
330 pResult->QWords.qw1 = ASMMult2xU64Ret2xU64(pValue1->s.Hi, uValue2, &pResult->QWords.qw2);
331 pResult->QWords.qw3 = 0;
332 pResult->QWords.qw1 += uTmp;
333 if (pResult->QWords.qw1 < uTmp)
334 pResult->QWords.qw2++; /* This cannot overflow AFAIK: 0xffff*0xffff = 0xFFFE0001 */
335
336 return pResult;
337}
338#endif
339
340
341/**
342 * Multiplies two 128-bit unsigned integer values, returning a 256-bit result.
343 *
344 * @returns pResult
345 * @param pResult The result variable.
346 * @param pValue1 The first value.
347 * @param pValue2 The second value.
348 */
349DECLINLINE(PRTUINT256U) RTUInt128MulEx(PRTUINT256U pResult, PCRTUINT128U pValue1, PCRTUINT128U pValue2)
350{
351 RTUInt128MulByU64Ex(pResult, pValue1, pValue2->s.Lo);
352 if (pValue2->s.Hi)
353 {
354 /* Multiply the two qwords in pValue1 by the high part of uValue2. */
355 uint64_t uTmpHi = 0;
356 uint64_t uTmpLo = ASMMult2xU64Ret2xU64(pValue1->s.Lo, pValue2->s.Hi, &uTmpHi);
357 pResult->QWords.qw1 += uTmpLo;
358 if (pResult->QWords.qw1 < uTmpLo)
359 if (++pResult->QWords.qw2 == 0)
360 pResult->QWords.qw3++; /* (cannot overflow, was == 0) */
361 pResult->QWords.qw2 += uTmpHi;
362 if (pResult->QWords.qw2 < uTmpHi)
363 pResult->QWords.qw3++; /* (cannot overflow, was <= 1) */
364
365 uTmpLo = ASMMult2xU64Ret2xU64(pValue1->s.Hi, pValue2->s.Hi, &uTmpHi);
366 pResult->QWords.qw2 += uTmpLo;
367 if (pResult->QWords.qw2 < uTmpLo)
368 pResult->QWords.qw3++; /* (cannot overflow, was <= 2) */
369 pResult->QWords.qw3 += uTmpHi;
370 }
371
372 return pResult;
373}
374
375
376DECLINLINE(PRTUINT128U) RTUInt128DivRem(PRTUINT128U pQuotient, PRTUINT128U pRemainder, PCRTUINT128U pValue1, PCRTUINT128U pValue2);
377
378/**
379 * Divides a 128-bit unsigned integer value by another.
380 *
381 * @returns pResult
382 * @param pResult The result variable.
383 * @param pValue1 The dividend value.
384 * @param pValue2 The divisor value.
385 */
386DECLINLINE(PRTUINT128U) RTUInt128Div(PRTUINT128U pResult, PCRTUINT128U pValue1, PCRTUINT128U pValue2)
387{
388 RTUINT128U Ignored;
389 return RTUInt128DivRem(pResult, &Ignored, pValue1, pValue2);
390}
391
392
393/**
394 * Divides a 128-bit unsigned integer value by another, returning the remainder.
395 *
396 * @returns pResult
397 * @param pResult The result variable (remainder).
398 * @param pValue1 The dividend value.
399 * @param pValue2 The divisor value.
400 */
401DECLINLINE(PRTUINT128U) RTUInt128Mod(PRTUINT128U pResult, PCRTUINT128U pValue1, PCRTUINT128U pValue2)
402{
403 RTUINT128U Ignored;
404 RTUInt128DivRem(&Ignored, pResult, pValue1, pValue2);
405 return pResult;
406}
407
408
409/**
410 * Bitwise AND of two 128-bit unsigned integer values.
411 *
412 * @returns pResult
413 * @param pResult The result variable.
414 * @param pValue1 The first value.
415 * @param pValue2 The second value.
416 */
417DECLINLINE(PRTUINT128U) RTUInt128And(PRTUINT128U pResult, PCRTUINT128U pValue1, PCRTUINT128U pValue2)
418{
419 pResult->s.Hi = pValue1->s.Hi & pValue2->s.Hi;
420 pResult->s.Lo = pValue1->s.Lo & pValue2->s.Lo;
421 return pResult;
422}
423
424
425/**
426 * Bitwise OR of two 128-bit unsigned integer values.
427 *
428 * @returns pResult
429 * @param pResult The result variable.
430 * @param pValue1 The first value.
431 * @param pValue2 The second value.
432 */
433DECLINLINE(PRTUINT128U) RTUInt128Or( PRTUINT128U pResult, PCRTUINT128U pValue1, PCRTUINT128U pValue2)
434{
435 pResult->s.Hi = pValue1->s.Hi | pValue2->s.Hi;
436 pResult->s.Lo = pValue1->s.Lo | pValue2->s.Lo;
437 return pResult;
438}
439
440
441/**
442 * Bitwise XOR of two 128-bit unsigned integer values.
443 *
444 * @returns pResult
445 * @param pResult The result variable.
446 * @param pValue1 The first value.
447 * @param pValue2 The second value.
448 */
449DECLINLINE(PRTUINT128U) RTUInt128Xor(PRTUINT128U pResult, PCRTUINT128U pValue1, PCRTUINT128U pValue2)
450{
451 pResult->s.Hi = pValue1->s.Hi ^ pValue2->s.Hi;
452 pResult->s.Lo = pValue1->s.Lo ^ pValue2->s.Lo;
453 return pResult;
454}
455
456
457/**
458 * Shifts a 128-bit unsigned integer value @a cBits to the left.
459 *
460 * @returns pResult
461 * @param pResult The result variable.
462 * @param pValue The value to shift.
463 * @param cBits The number of bits to shift it.
464 */
465DECLINLINE(PRTUINT128U) RTUInt128ShiftLeft(PRTUINT128U pResult, PCRTUINT128U pValue, int cBits)
466{
467 cBits &= 127;
468 if (cBits < 64)
469 {
470 pResult->s.Lo = pValue->s.Lo << cBits;
471 pResult->s.Hi = (pValue->s.Hi << cBits) | (pValue->s.Lo >> (64 - cBits));
472 }
473 else
474 {
475 pResult->s.Lo = 0;
476 pResult->s.Hi = pValue->s.Lo << (cBits - 64);
477 }
478 return pResult;
479}
480
481
482/**
483 * Shifts a 128-bit unsigned integer value @a cBits to the right.
484 *
485 * @returns pResult
486 * @param pResult The result variable.
487 * @param pValue The value to shift.
488 * @param cBits The number of bits to shift it.
489 */
490DECLINLINE(PRTUINT128U) RTUInt128ShiftRight(PRTUINT128U pResult, PCRTUINT128U pValue, int cBits)
491{
492 cBits &= 127;
493 if (cBits < 64)
494 {
495 pResult->s.Hi = pValue->s.Hi >> cBits;
496 pResult->s.Lo = (pValue->s.Lo >> cBits) | (pValue->s.Hi << (64 - cBits));
497 }
498 else
499 {
500 pResult->s.Hi = 0;
501 pResult->s.Lo = pValue->s.Hi >> (cBits - 64);
502 }
503 return pResult;
504}
505
506
507/**
508 * Boolean not (result 0 or 1).
509 *
510 * @returns pResult.
511 * @param pResult The result variable.
512 * @param pValue The value.
513 */
514DECLINLINE(PRTUINT128U) RTUInt128BooleanNot(PRTUINT128U pResult, PCRTUINT128U pValue)
515{
516 pResult->s.Lo = pValue->s.Lo || pValue->s.Hi ? 0 : 1;
517 pResult->s.Hi = 0;
518 return pResult;
519}
520
521
522/**
523 * Bitwise not (flips each bit of the 128 bits).
524 *
525 * @returns pResult.
526 * @param pResult The result variable.
527 * @param pValue The value.
528 */
529DECLINLINE(PRTUINT128U) RTUInt128BitwiseNot(PRTUINT128U pResult, PCRTUINT128U pValue)
530{
531 pResult->s.Hi = ~pValue->s.Hi;
532 pResult->s.Lo = ~pValue->s.Lo;
533 return pResult;
534}
535
536
537/**
538 * Assigns one 128-bit unsigned integer value to another.
539 *
540 * @returns pResult
541 * @param pResult The result variable.
542 * @param pValue The value to assign.
543 */
544DECLINLINE(PRTUINT128U) RTUInt128Assign(PRTUINT128U pResult, PCRTUINT128U pValue)
545{
546#if ARCH_BITS >= 64
547 pResult->s.Hi = pValue->s.Hi;
548 pResult->s.Lo = pValue->s.Lo;
549#else
550 pResult->DWords.dw0 = pValue->DWords.dw0;
551 pResult->DWords.dw1 = pValue->DWords.dw1;
552 pResult->DWords.dw2 = pValue->DWords.dw2;
553 pResult->DWords.dw3 = pValue->DWords.dw3;
554#endif
555 return pResult;
556}
557
558
559/**
560 * Assigns a boolean value to 128-bit unsigned integer.
561 *
562 * @returns pValueResult
563 * @param pValueResult The result variable.
564 * @param fValue The boolean value.
565 */
566DECLINLINE(PRTUINT128U) RTUInt128AssignBoolean(PRTUINT128U pValueResult, bool fValue)
567{
568#if ARCH_BITS >= 64
569 pValueResult->s.Lo = fValue;
570 pValueResult->s.Hi = 0;
571#else
572 pValueResult->DWords.dw0 = fValue;
573 pValueResult->DWords.dw1 = 0;
574 pValueResult->DWords.dw2 = 0;
575 pValueResult->DWords.dw3 = 0;
576#endif
577 return pValueResult;
578}
579
580
581/**
582 * Assigns a 8-bit unsigned integer value to 128-bit unsigned integer.
583 *
584 * @returns pValueResult
585 * @param pValueResult The result variable.
586 * @param u8Value The 8-bit unsigned integer value.
587 */
588DECLINLINE(PRTUINT128U) RTUInt128AssignU8(PRTUINT128U pValueResult, uint8_t u8Value)
589{
590#if ARCH_BITS >= 64
591 pValueResult->s.Lo = u8Value;
592 pValueResult->s.Hi = 0;
593#else
594 pValueResult->DWords.dw0 = u8Value;
595 pValueResult->DWords.dw1 = 0;
596 pValueResult->DWords.dw2 = 0;
597 pValueResult->DWords.dw3 = 0;
598#endif
599 return pValueResult;
600}
601
602
603/**
604 * Assigns a 16-bit unsigned integer value to 128-bit unsigned integer.
605 *
606 * @returns pValueResult
607 * @param pValueResult The result variable.
608 * @param u16Value The 16-bit unsigned integer value.
609 */
610DECLINLINE(PRTUINT128U) RTUInt128AssignU16(PRTUINT128U pValueResult, uint16_t u16Value)
611{
612#if ARCH_BITS >= 64
613 pValueResult->s.Lo = u16Value;
614 pValueResult->s.Hi = 0;
615#else
616 pValueResult->DWords.dw0 = u16Value;
617 pValueResult->DWords.dw1 = 0;
618 pValueResult->DWords.dw2 = 0;
619 pValueResult->DWords.dw3 = 0;
620#endif
621 return pValueResult;
622}
623
624
625/**
626 * Assigns a 32-bit unsigned integer value to 128-bit unsigned integer.
627 *
628 * @returns pValueResult
629 * @param pValueResult The result variable.
630 * @param u32Value The 32-bit unsigned integer value.
631 */
632DECLINLINE(PRTUINT128U) RTUInt128AssignU32(PRTUINT128U pValueResult, uint32_t u32Value)
633{
634#if ARCH_BITS >= 64
635 pValueResult->s.Lo = u32Value;
636 pValueResult->s.Hi = 0;
637#else
638 pValueResult->DWords.dw0 = u32Value;
639 pValueResult->DWords.dw1 = 0;
640 pValueResult->DWords.dw2 = 0;
641 pValueResult->DWords.dw3 = 0;
642#endif
643 return pValueResult;
644}
645
646
647/**
648 * Assigns a 64-bit unsigned integer value to 128-bit unsigned integer.
649 *
650 * @returns pValueResult
651 * @param pValueResult The result variable.
652 * @param u64Value The 64-bit unsigned integer value.
653 */
654DECLINLINE(PRTUINT128U) RTUInt128AssignU64(PRTUINT128U pValueResult, uint64_t u64Value)
655{
656 pValueResult->s.Lo = u64Value;
657 pValueResult->s.Hi = 0;
658 return pValueResult;
659}
660
661
662/**
663 * Adds two 128-bit unsigned integer values, storing the result in the first.
664 *
665 * @returns pValue1Result.
666 * @param pValue1Result The first value and result.
667 * @param pValue2 The second value.
668 */
669DECLINLINE(PRTUINT128U) RTUInt128AssignAdd(PRTUINT128U pValue1Result, PCRTUINT128U pValue2)
670{
671 uint64_t const uTmp = pValue1Result->s.Lo;
672 pValue1Result->s.Lo += pValue2->s.Lo;
673 if (pValue1Result->s.Lo < uTmp)
674 pValue1Result->s.Hi++;
675 pValue1Result->s.Hi += pValue2->s.Hi;
676 return pValue1Result;
677}
678
679
680/**
681 * Adds a 64-bit unsigned integer value to a 128-bit unsigned integer values,
682 * storing the result in the 128-bit one.
683 *
684 * @returns pValue1Result.
685 * @param pValue1Result The first value and result.
686 * @param uValue2 The second value, 64-bit.
687 */
688DECLINLINE(PRTUINT128U) RTUInt128AssignAddU64(PRTUINT128U pValue1Result, uint64_t uValue2)
689{
690 pValue1Result->s.Lo += uValue2;
691 if (pValue1Result->s.Lo < uValue2)
692 pValue1Result->s.Hi++;
693 return pValue1Result;
694}
695
696
697/**
698 * Subtracts two 128-bit unsigned integer values, storing the result in the
699 * first.
700 *
701 * @returns pValue1Result.
702 * @param pValue1Result The minuend value and result.
703 * @param pValue2 The subtrahend value.
704 */
705DECLINLINE(PRTUINT128U) RTUInt128AssignSub(PRTUINT128U pValue1Result, PCRTUINT128U pValue2)
706{
707 uint64_t const uTmp = pValue1Result->s.Lo;
708 pValue1Result->s.Lo -= pValue2->s.Lo;
709 if (pValue1Result->s.Lo > uTmp)
710 pValue1Result->s.Hi--;
711 pValue1Result->s.Hi -= pValue2->s.Hi;
712 return pValue1Result;
713}
714
715
716/**
717 * Negates a 128 number, storing the result in the input.
718 *
719 * @returns pValueResult.
720 * @param pValueResult The value to negate.
721 */
722DECLINLINE(PRTUINT128U) RTUInt128AssignNeg(PRTUINT128U pValueResult)
723{
724 /* result = 0 - value */
725 if (pValueResult->s.Lo != 0)
726 {
727 pValueResult->s.Lo = UINT64_C(0) - pValueResult->s.Lo;
728 pValueResult->s.Hi = UINT64_MAX - pValueResult->s.Hi;
729 }
730 else
731 pValueResult->s.Hi = UINT64_C(0) - pValueResult->s.Hi;
732 return pValueResult;
733}
734
735
736/**
737 * Multiplies two 128-bit unsigned integer values, storing the result in the
738 * first.
739 *
740 * @returns pValue1Result.
741 * @param pValue1Result The first value and result.
742 * @param pValue2 The second value.
743 */
744DECLINLINE(PRTUINT128U) RTUInt128AssignMul(PRTUINT128U pValue1Result, PCRTUINT128U pValue2)
745{
746 RTUINT128U Result;
747 RTUInt128Mul(&Result, pValue1Result, pValue2);
748 *pValue1Result = Result;
749 return pValue1Result;
750}
751
752
753/**
754 * Divides a 128-bit unsigned integer value by another, storing the result in
755 * the first.
756 *
757 * @returns pValue1Result.
758 * @param pValue1Result The dividend value and result.
759 * @param pValue2 The divisor value.
760 */
761DECLINLINE(PRTUINT128U) RTUInt128AssignDiv(PRTUINT128U pValue1Result, PCRTUINT128U pValue2)
762{
763 RTUINT128U Result;
764 RTUINT128U Ignored;
765 RTUInt128DivRem(&Result, &Ignored, pValue1Result, pValue2);
766 *pValue1Result = Result;
767 return pValue1Result;
768}
769
770
771/**
772 * Divides a 128-bit unsigned integer value by another, storing the remainder in
773 * the first.
774 *
775 * @returns pValue1Result.
776 * @param pValue1Result The dividend value and result (remainder).
777 * @param pValue2 The divisor value.
778 */
779DECLINLINE(PRTUINT128U) RTUInt128AssignMod(PRTUINT128U pValue1Result, PCRTUINT128U pValue2)
780{
781 RTUINT128U Ignored;
782 RTUINT128U Result;
783 RTUInt128DivRem(&Ignored, &Result, pValue1Result, pValue2);
784 *pValue1Result = Result;
785 return pValue1Result;
786}
787
788
789/**
790 * Performs a bitwise AND of two 128-bit unsigned integer values and assigned
791 * the result to the first one.
792 *
793 * @returns pValue1Result.
794 * @param pValue1Result The first value and result.
795 * @param pValue2 The second value.
796 */
797DECLINLINE(PRTUINT128U) RTUInt128AssignAnd(PRTUINT128U pValue1Result, PCRTUINT128U pValue2)
798{
799#if ARCH_BITS >= 64
800 pValue1Result->s.Hi &= pValue2->s.Hi;
801 pValue1Result->s.Lo &= pValue2->s.Lo;
802#else
803 pValue1Result->DWords.dw0 &= pValue2->DWords.dw0;
804 pValue1Result->DWords.dw1 &= pValue2->DWords.dw1;
805 pValue1Result->DWords.dw2 &= pValue2->DWords.dw2;
806 pValue1Result->DWords.dw3 &= pValue2->DWords.dw3;
807#endif
808 return pValue1Result;
809}
810
811
812/**
813 * Performs a bitwise AND of a 128-bit unsigned integer value and a mask made
814 * up of the first N bits, assigning the result to the the 128-bit value.
815 *
816 * @returns pValueResult.
817 * @param pValueResult The value and result.
818 * @param cBits The number of bits to AND (counting from the first
819 * bit).
820 */
821DECLINLINE(PRTUINT128U) RTUInt128AssignAndNFirstBits(PRTUINT128U pValueResult, unsigned cBits)
822{
823 if (cBits <= 64)
824 {
825 if (cBits != 64)
826 pValueResult->s.Lo &= (RT_BIT_64(cBits) - 1);
827 pValueResult->s.Hi = 0;
828 }
829 else if (cBits < 128)
830 pValueResult->s.Hi &= (RT_BIT_64(cBits - 64) - 1);
831/** @todo \#if ARCH_BITS >= 64 */
832 return pValueResult;
833}
834
835
836/**
837 * Performs a bitwise OR of two 128-bit unsigned integer values and assigned
838 * the result to the first one.
839 *
840 * @returns pValue1Result.
841 * @param pValue1Result The first value and result.
842 * @param pValue2 The second value.
843 */
844DECLINLINE(PRTUINT128U) RTUInt128AssignOr(PRTUINT128U pValue1Result, PCRTUINT128U pValue2)
845{
846#if ARCH_BITS >= 64
847 pValue1Result->s.Hi |= pValue2->s.Hi;
848 pValue1Result->s.Lo |= pValue2->s.Lo;
849#else
850 pValue1Result->DWords.dw0 |= pValue2->DWords.dw0;
851 pValue1Result->DWords.dw1 |= pValue2->DWords.dw1;
852 pValue1Result->DWords.dw2 |= pValue2->DWords.dw2;
853 pValue1Result->DWords.dw3 |= pValue2->DWords.dw3;
854#endif
855 return pValue1Result;
856}
857
858
859/**
860 * ORs in a bit and assign the result to the input value.
861 *
862 * @returns pValue1Result.
863 * @param pValue1Result The first value and result.
864 * @param iBit The bit to set (0 based).
865 */
866DECLINLINE(PRTUINT128U) RTUInt128AssignOrBit(PRTUINT128U pValue1Result, uint32_t iBit)
867{
868#if ARCH_BITS >= 64
869 if (iBit >= 64)
870 pValue1Result->s.Hi |= RT_BIT_64(iBit - 64);
871 else
872 pValue1Result->s.Lo |= RT_BIT_64(iBit);
873#else
874 if (iBit >= 64)
875 {
876 if (iBit >= 96)
877 pValue1Result->DWords.dw3 |= RT_BIT_32(iBit - 96);
878 else
879 pValue1Result->DWords.dw2 |= RT_BIT_32(iBit - 64);
880 }
881 else
882 {
883 if (iBit >= 32)
884 pValue1Result->DWords.dw1 |= RT_BIT_32(iBit - 32);
885 else
886 pValue1Result->DWords.dw0 |= RT_BIT_32(iBit);
887 }
888#endif
889 return pValue1Result;
890}
891
892
893
894/**
895 * Performs a bitwise XOR of two 128-bit unsigned integer values and assigned
896 * the result to the first one.
897 *
898 * @returns pValue1Result.
899 * @param pValue1Result The first value and result.
900 * @param pValue2 The second value.
901 */
902DECLINLINE(PRTUINT128U) RTUInt128AssignXor(PRTUINT128U pValue1Result, PCRTUINT128U pValue2)
903{
904#if ARCH_BITS >= 64
905 pValue1Result->s.Hi ^= pValue2->s.Hi;
906 pValue1Result->s.Lo ^= pValue2->s.Lo;
907#else
908 pValue1Result->DWords.dw0 ^= pValue2->DWords.dw0;
909 pValue1Result->DWords.dw1 ^= pValue2->DWords.dw1;
910 pValue1Result->DWords.dw2 ^= pValue2->DWords.dw2;
911 pValue1Result->DWords.dw3 ^= pValue2->DWords.dw3;
912#endif
913 return pValue1Result;
914}
915
916
917/**
918 * Performs a bitwise left shift on a 128-bit unsigned integer value, assigning
919 * the result to it.
920 *
921 * @returns pValueResult.
922 * @param pValueResult The first value and result.
923 * @param cBits The number of bits to shift.
924 */
925DECLINLINE(PRTUINT128U) RTUInt128AssignShiftLeft(PRTUINT128U pValueResult, int cBits)
926{
927 RTUINT128U const InVal = *pValueResult;
928/** @todo \#if ARCH_BITS >= 64 */
929 if (cBits > 0)
930 {
931 /* (left shift) */
932 if (cBits >= 128)
933 RTUInt128SetZero(pValueResult);
934 else if (cBits >= 64)
935 {
936 pValueResult->s.Lo = 0;
937 pValueResult->s.Hi = InVal.s.Lo << (cBits - 64);
938 }
939 else
940 {
941 pValueResult->s.Hi = InVal.s.Hi << cBits;
942 pValueResult->s.Hi |= InVal.s.Lo >> (64 - cBits);
943 pValueResult->s.Lo = InVal.s.Lo << cBits;
944 }
945 }
946 else if (cBits < 0)
947 {
948 /* (right shift) */
949 cBits = -cBits;
950 if (cBits >= 128)
951 RTUInt128SetZero(pValueResult);
952 else if (cBits >= 64)
953 {
954 pValueResult->s.Hi = 0;
955 pValueResult->s.Lo = InVal.s.Hi >> (cBits - 64);
956 }
957 else
958 {
959 pValueResult->s.Lo = InVal.s.Lo >> cBits;
960 pValueResult->s.Lo |= InVal.s.Hi << (64 - cBits);
961 pValueResult->s.Hi = InVal.s.Hi >> cBits;
962 }
963 }
964 return pValueResult;
965}
966
967
968/**
969 * Performs a bitwise left shift on a 128-bit unsigned integer value, assigning
970 * the result to it.
971 *
972 * @returns pValueResult.
973 * @param pValueResult The first value and result.
974 * @param cBits The number of bits to shift.
975 */
976DECLINLINE(PRTUINT128U) RTUInt128AssignShiftRight(PRTUINT128U pValueResult, int cBits)
977{
978 return RTUInt128AssignShiftLeft(pValueResult, -cBits);
979}
980
981
982/**
983 * Performs a bitwise NOT on a 128-bit unsigned integer value, assigning the
984 * result to it.
985 *
986 * @returns pValueResult
987 * @param pValueResult The value and result.
988 */
989DECLINLINE(PRTUINT128U) RTUInt128AssignBitwiseNot(PRTUINT128U pValueResult)
990{
991#if ARCH_BITS >= 64
992 pValueResult->s.Hi = ~pValueResult->s.Hi;
993 pValueResult->s.Lo = ~pValueResult->s.Lo;
994#else
995 pValueResult->DWords.dw0 = ~pValueResult->DWords.dw0;
996 pValueResult->DWords.dw1 = ~pValueResult->DWords.dw1;
997 pValueResult->DWords.dw2 = ~pValueResult->DWords.dw2;
998 pValueResult->DWords.dw3 = ~pValueResult->DWords.dw3;
999#endif
1000 return pValueResult;
1001}
1002
1003
1004/**
1005 * Performs a boolean NOT on a 128-bit unsigned integer value, assigning the
1006 * result to it.
1007 *
1008 * @returns pValueResult
1009 * @param pValueResult The value and result.
1010 */
1011DECLINLINE(PRTUINT128U) RTUInt128AssignBooleanNot(PRTUINT128U pValueResult)
1012{
1013 return RTUInt128AssignBoolean(pValueResult, RTUInt128IsZero(pValueResult));
1014}
1015
1016
1017/**
1018 * Compares two 128-bit unsigned integer values.
1019 *
1020 * @retval 0 if equal.
1021 * @retval -1 if the first value is smaller than the second.
1022 * @retval 1 if the first value is larger than the second.
1023 *
1024 * @param pValue1 The first value.
1025 * @param pValue2 The second value.
1026 */
1027DECLINLINE(int) RTUInt128Compare(PCRTUINT128U pValue1, PCRTUINT128U pValue2)
1028{
1029#if ARCH_BITS >= 64
1030 if (pValue1->s.Hi != pValue2->s.Hi)
1031 return pValue1->s.Hi > pValue2->s.Hi ? 1 : -1;
1032 if (pValue1->s.Lo != pValue2->s.Lo)
1033 return pValue1->s.Lo > pValue2->s.Lo ? 1 : -1;
1034 return 0;
1035#else
1036 if (pValue1->DWords.dw3 != pValue2->DWords.dw3)
1037 return pValue1->DWords.dw3 > pValue2->DWords.dw3 ? 1 : -1;
1038 if (pValue1->DWords.dw2 != pValue2->DWords.dw2)
1039 return pValue1->DWords.dw2 > pValue2->DWords.dw2 ? 1 : -1;
1040 if (pValue1->DWords.dw1 != pValue2->DWords.dw1)
1041 return pValue1->DWords.dw1 > pValue2->DWords.dw1 ? 1 : -1;
1042 if (pValue1->DWords.dw0 != pValue2->DWords.dw0)
1043 return pValue1->DWords.dw0 > pValue2->DWords.dw0 ? 1 : -1;
1044 return 0;
1045#endif
1046}
1047
1048
1049/**
1050 * Tests if a 128-bit unsigned integer value is smaller than another.
1051 *
1052 * @returns true if the first value is smaller, false if not.
1053 * @param pValue1 The first value.
1054 * @param pValue2 The second value.
1055 */
1056DECLINLINE(bool) RTUInt128IsSmaller(PCRTUINT128U pValue1, PCRTUINT128U pValue2)
1057{
1058#if ARCH_BITS >= 64
1059 return pValue1->s.Hi < pValue2->s.Hi
1060 || ( pValue1->s.Hi == pValue2->s.Hi
1061 && pValue1->s.Lo < pValue2->s.Lo);
1062#else
1063 return pValue1->DWords.dw3 < pValue2->DWords.dw3
1064 || ( pValue1->DWords.dw3 == pValue2->DWords.dw3
1065 && ( pValue1->DWords.dw2 < pValue2->DWords.dw2
1066 || ( pValue1->DWords.dw2 == pValue2->DWords.dw2
1067 && ( pValue1->DWords.dw1 < pValue2->DWords.dw1
1068 || ( pValue1->DWords.dw1 == pValue2->DWords.dw1
1069 && pValue1->DWords.dw0 < pValue2->DWords.dw0)))));
1070#endif
1071}
1072
1073
1074/**
1075 * Tests if a 128-bit unsigned integer value is larger than another.
1076 *
1077 * @returns true if the first value is larger, false if not.
1078 * @param pValue1 The first value.
1079 * @param pValue2 The second value.
1080 */
1081DECLINLINE(bool) RTUInt128IsLarger(PCRTUINT128U pValue1, PCRTUINT128U pValue2)
1082{
1083#if ARCH_BITS >= 64
1084 return pValue1->s.Hi > pValue2->s.Hi
1085 || ( pValue1->s.Hi == pValue2->s.Hi
1086 && pValue1->s.Lo > pValue2->s.Lo);
1087#else
1088 return pValue1->DWords.dw3 > pValue2->DWords.dw3
1089 || ( pValue1->DWords.dw3 == pValue2->DWords.dw3
1090 && ( pValue1->DWords.dw2 > pValue2->DWords.dw2
1091 || ( pValue1->DWords.dw2 == pValue2->DWords.dw2
1092 && ( pValue1->DWords.dw1 > pValue2->DWords.dw1
1093 || ( pValue1->DWords.dw1 == pValue2->DWords.dw1
1094 && pValue1->DWords.dw0 > pValue2->DWords.dw0)))));
1095#endif
1096}
1097
1098
1099/**
1100 * Tests if a 128-bit unsigned integer value is larger or equal than another.
1101 *
1102 * @returns true if the first value is larger or equal, false if not.
1103 * @param pValue1 The first value.
1104 * @param pValue2 The second value.
1105 */
1106DECLINLINE(bool) RTUInt128IsLargerOrEqual(PCRTUINT128U pValue1, PCRTUINT128U pValue2)
1107{
1108#if ARCH_BITS >= 64
1109 return pValue1->s.Hi > pValue2->s.Hi
1110 || ( pValue1->s.Hi == pValue2->s.Hi
1111 && pValue1->s.Lo >= pValue2->s.Lo);
1112#else
1113 return pValue1->DWords.dw3 > pValue2->DWords.dw3
1114 || ( pValue1->DWords.dw3 == pValue2->DWords.dw3
1115 && ( pValue1->DWords.dw2 > pValue2->DWords.dw2
1116 || ( pValue1->DWords.dw2 == pValue2->DWords.dw2
1117 && ( pValue1->DWords.dw1 > pValue2->DWords.dw1
1118 || ( pValue1->DWords.dw1 == pValue2->DWords.dw1
1119 && pValue1->DWords.dw0 >= pValue2->DWords.dw0)))));
1120#endif
1121}
1122
1123
1124/**
1125 * Tests if two 128-bit unsigned integer values not equal.
1126 *
1127 * @returns true if equal, false if not equal.
1128 * @param pValue1 The first value.
1129 * @param pValue2 The second value.
1130 */
1131DECLINLINE(bool) RTUInt128IsEqual(PCRTUINT128U pValue1, PCRTUINT128U pValue2)
1132{
1133#if ARCH_BITS >= 64
1134 return pValue1->s.Hi == pValue2->s.Hi
1135 && pValue1->s.Lo == pValue2->s.Lo;
1136#else
1137 return pValue1->DWords.dw0 == pValue2->DWords.dw0
1138 && pValue1->DWords.dw1 == pValue2->DWords.dw1
1139 && pValue1->DWords.dw2 == pValue2->DWords.dw2
1140 && pValue1->DWords.dw3 == pValue2->DWords.dw3;
1141#endif
1142}
1143
1144
1145/**
1146 * Tests if two 128-bit unsigned integer values are not equal.
1147 *
1148 * @returns true if not equal, false if equal.
1149 * @param pValue1 The first value.
1150 * @param pValue2 The second value.
1151 */
1152DECLINLINE(bool) RTUInt128IsNotEqual(PCRTUINT128U pValue1, PCRTUINT128U pValue2)
1153{
1154 return !RTUInt128IsEqual(pValue1, pValue2);
1155}
1156
1157
1158/**
1159 * Sets a bit in a 128-bit unsigned integer type.
1160 *
1161 * @returns pValueResult.
1162 * @param pValueResult The input and output value.
1163 * @param iBit The bit to set.
1164 */
1165DECLINLINE(PRTUINT128U) RTUInt128BitSet(PRTUINT128U pValueResult, unsigned iBit)
1166{
1167 if (iBit < 64)
1168 {
1169#if ARCH_BITS >= 64
1170 pValueResult->s.Lo |= RT_BIT_64(iBit);
1171#else
1172 if (iBit < 32)
1173 pValueResult->DWords.dw0 |= RT_BIT_32(iBit);
1174 else
1175 pValueResult->DWords.dw1 |= RT_BIT_32(iBit - 32);
1176#endif
1177 }
1178 else if (iBit < 128)
1179 {
1180#if ARCH_BITS >= 64
1181 pValueResult->s.Hi |= RT_BIT_64(iBit - 64);
1182#else
1183 if (iBit < 96)
1184 pValueResult->DWords.dw2 |= RT_BIT_32(iBit - 64);
1185 else
1186 pValueResult->DWords.dw3 |= RT_BIT_32(iBit - 96);
1187#endif
1188 }
1189 return pValueResult;
1190}
1191
1192
1193/**
1194 * Sets a bit in a 128-bit unsigned integer type.
1195 *
1196 * @returns pValueResult.
1197 * @param pValueResult The input and output value.
1198 * @param iBit The bit to set.
1199 */
1200DECLINLINE(PRTUINT128U) RTUInt128BitClear(PRTUINT128U pValueResult, unsigned iBit)
1201{
1202 if (iBit < 64)
1203 {
1204#if ARCH_BITS >= 64
1205 pValueResult->s.Lo &= ~RT_BIT_64(iBit);
1206#else
1207 if (iBit < 32)
1208 pValueResult->DWords.dw0 &= ~RT_BIT_32(iBit);
1209 else
1210 pValueResult->DWords.dw1 &= ~RT_BIT_32(iBit - 32);
1211#endif
1212 }
1213 else if (iBit < 128)
1214 {
1215#if ARCH_BITS >= 64
1216 pValueResult->s.Hi &= ~RT_BIT_64(iBit - 64);
1217#else
1218 if (iBit < 96)
1219 pValueResult->DWords.dw2 &= ~RT_BIT_32(iBit - 64);
1220 else
1221 pValueResult->DWords.dw3 &= ~RT_BIT_32(iBit - 96);
1222#endif
1223 }
1224 return pValueResult;
1225}
1226
1227
1228/**
1229 * Tests if a bit in a 128-bit unsigned integer value is set.
1230 *
1231 * @returns pValueResult.
1232 * @param pValueResult The input and output value.
1233 * @param iBit The bit to test.
1234 */
1235DECLINLINE(bool) RTUInt128BitTest(PRTUINT128U pValueResult, unsigned iBit)
1236{
1237 bool fRc;
1238 if (iBit < 64)
1239 {
1240#if ARCH_BITS >= 64
1241 fRc = RT_BOOL(pValueResult->s.Lo & RT_BIT_64(iBit));
1242#else
1243 if (iBit < 32)
1244 fRc = RT_BOOL(pValueResult->DWords.dw0 & RT_BIT_32(iBit));
1245 else
1246 fRc = RT_BOOL(pValueResult->DWords.dw1 & RT_BIT_32(iBit - 32));
1247#endif
1248 }
1249 else if (iBit < 128)
1250 {
1251#if ARCH_BITS >= 64
1252 fRc = RT_BOOL(pValueResult->s.Hi & RT_BIT_64(iBit - 64));
1253#else
1254 if (iBit < 96)
1255 fRc = RT_BOOL(pValueResult->DWords.dw2 & RT_BIT_32(iBit - 64));
1256 else
1257 fRc = RT_BOOL(pValueResult->DWords.dw3 & RT_BIT_32(iBit - 96));
1258#endif
1259 }
1260 else
1261 fRc = false;
1262 return fRc;
1263}
1264
1265
1266/**
1267 * Set a range of bits a 128-bit unsigned integer value.
1268 *
1269 * @returns pValueResult.
1270 * @param pValueResult The input and output value.
1271 * @param iFirstBit The first bit to test.
1272 * @param cBits The number of bits to set.
1273 */
1274DECLINLINE(PRTUINT128U) RTUInt128BitSetRange(PRTUINT128U pValueResult, unsigned iFirstBit, unsigned cBits)
1275{
1276 /* bounds check & fix. */
1277 if (iFirstBit < 128)
1278 {
1279 if (iFirstBit + cBits > 128)
1280 cBits = 128 - iFirstBit;
1281
1282#if ARCH_BITS >= 64
1283 if (iFirstBit + cBits < 64)
1284 pValueResult->s.Lo |= (RT_BIT_64(cBits) - 1) << iFirstBit;
1285 else if (iFirstBit + cBits < 128 && iFirstBit >= 64)
1286 pValueResult->s.Hi |= (RT_BIT_64(cBits) - 1) << (iFirstBit - 64);
1287 else
1288#else
1289 if (iFirstBit + cBits < 32)
1290 pValueResult->DWords.dw0 |= (RT_BIT_32(cBits) - 1) << iFirstBit;
1291 else if (iFirstBit + cBits < 64 && iFirstBit >= 32)
1292 pValueResult->DWords.dw1 |= (RT_BIT_32(cBits) - 1) << (iFirstBit - 32);
1293 else if (iFirstBit + cBits < 96 && iFirstBit >= 64)
1294 pValueResult->DWords.dw2 |= (RT_BIT_32(cBits) - 1) << (iFirstBit - 64);
1295 else if (iFirstBit + cBits < 128 && iFirstBit >= 96)
1296 pValueResult->DWords.dw3 |= (RT_BIT_32(cBits) - 1) << (iFirstBit - 96);
1297 else
1298#endif
1299 while (cBits-- > 0)
1300 RTUInt128BitSet(pValueResult, iFirstBit++);
1301 }
1302 return pValueResult;
1303}
1304
1305
1306/**
1307 * Test if all the bits of a 128-bit unsigned integer value are set.
1308 *
1309 * @returns true if they are, false if they aren't.
1310 * @param pValue The input and output value.
1311 */
1312DECLINLINE(bool) RTUInt128BitAreAllSet(PRTUINT128U pValue)
1313{
1314#if ARCH_BITS >= 64
1315 return pValue->s.Hi == UINT64_MAX
1316 && pValue->s.Lo == UINT64_MAX;
1317#else
1318 return pValue->DWords.dw0 == UINT32_MAX
1319 && pValue->DWords.dw1 == UINT32_MAX
1320 && pValue->DWords.dw2 == UINT32_MAX
1321 && pValue->DWords.dw3 == UINT32_MAX;
1322#endif
1323}
1324
1325
1326/**
1327 * Test if all the bits of a 128-bit unsigned integer value are clear.
1328 *
1329 * @returns true if they are, false if they aren't.
1330 * @param pValue The input and output value.
1331 */
1332DECLINLINE(bool) RTUInt128BitAreAllClear(PRTUINT128U pValue)
1333{
1334#if ARCH_BITS >= 64
1335 return pValue->s.Hi == 0
1336 && pValue->s.Lo == 0;
1337#else
1338 return pValue->DWords.dw0 == 0
1339 && pValue->DWords.dw1 == 0
1340 && pValue->DWords.dw2 == 0
1341 && pValue->DWords.dw3 == 0;
1342#endif
1343}
1344
1345
1346/**
1347 * Number of significant bits in the value.
1348 *
1349 * This is the same a ASMBitLastSetU64 and ASMBitLastSetU32.
1350 *
1351 * @returns 0 if zero, 1-base index of the last bit set.
1352 * @param pValue The value to examine.
1353 */
1354DECLINLINE(uint32_t) RTUInt128BitCount(PCRTUINT128U pValue)
1355{
1356 uint32_t cBits;
1357 if (pValue->s.Hi != 0)
1358 {
1359 if (pValue->DWords.dw3)
1360 cBits = 96 + ASMBitLastSetU32(pValue->DWords.dw3);
1361 else
1362 cBits = 64 + ASMBitLastSetU32(pValue->DWords.dw2);
1363 }
1364 else
1365 {
1366 if (pValue->DWords.dw1)
1367 cBits = 32 + ASMBitLastSetU32(pValue->DWords.dw1);
1368 else
1369 cBits = 0 + ASMBitLastSetU32(pValue->DWords.dw0);
1370 }
1371 return cBits;
1372}
1373
1374
1375/**
1376 * Divides a 128-bit unsigned integer value by another, returning both quotient
1377 * and remainder.
1378 *
1379 * @returns pQuotient, NULL if pValue2 is 0.
1380 * @param pQuotient Where to return the quotient.
1381 * @param pRemainder Where to return the remainder.
1382 * @param pValue1 The dividend value.
1383 * @param pValue2 The divisor value.
1384 */
1385DECLINLINE(PRTUINT128U) RTUInt128DivRem(PRTUINT128U pQuotient, PRTUINT128U pRemainder, PCRTUINT128U pValue1, PCRTUINT128U pValue2)
1386{
1387 int iDiff;
1388
1389 /*
1390 * Sort out all the special cases first.
1391 */
1392 /* Divide by zero or 1? */
1393 if (!pValue2->s.Hi)
1394 {
1395 if (!pValue2->s.Lo)
1396 return NULL;
1397
1398 if (pValue2->s.Lo == 1)
1399 {
1400 RTUInt128SetZero(pRemainder);
1401 *pQuotient = *pValue1;
1402 return pQuotient;
1403 }
1404 /** @todo RTUint128DivModBy64 */
1405 }
1406
1407 /* Dividend is smaller? */
1408 iDiff = RTUInt128Compare(pValue1, pValue2);
1409 if (iDiff < 0)
1410 {
1411 *pRemainder = *pValue1;
1412 RTUInt128SetZero(pQuotient);
1413 }
1414
1415 /* The values are equal? */
1416 else if (iDiff == 0)
1417 {
1418 RTUInt128SetZero(pRemainder);
1419 RTUInt128AssignU64(pQuotient, 1);
1420 }
1421 else
1422 {
1423 /*
1424 * Prepare.
1425 */
1426 uint32_t iBitAdder = RTUInt128BitCount(pValue1) - RTUInt128BitCount(pValue2);
1427 RTUINT128U NormDivisor = *pValue2;
1428 if (iBitAdder)
1429 {
1430 RTUInt128ShiftLeft(&NormDivisor, pValue2, iBitAdder);
1431 if (RTUInt128IsLarger(&NormDivisor, pValue1))
1432 {
1433 RTUInt128AssignShiftRight(&NormDivisor, 1);
1434 iBitAdder--;
1435 }
1436 }
1437 else
1438 NormDivisor = *pValue2;
1439
1440 RTUInt128SetZero(pQuotient);
1441 *pRemainder = *pValue1;
1442
1443 /*
1444 * Do the division.
1445 */
1446 if (RTUInt128IsLargerOrEqual(pRemainder, pValue2))
1447 {
1448 for (;;)
1449 {
1450 if (RTUInt128IsLargerOrEqual(pRemainder, &NormDivisor))
1451 {
1452 RTUInt128AssignSub(pRemainder, &NormDivisor);
1453 RTUInt128AssignOrBit(pQuotient, iBitAdder);
1454 }
1455 if (RTUInt128IsSmaller(pRemainder, pValue2))
1456 break;
1457 RTUInt128AssignShiftRight(&NormDivisor, 1);
1458 iBitAdder--;
1459 }
1460 }
1461 }
1462 return pQuotient;
1463}
1464
1465
1466/** @} */
1467
1468RT_C_DECLS_END
1469
1470#endif /* !IPRT_INCLUDED_uint128_h */
1471
注意: 瀏覽 TracBrowser 來幫助您使用儲存庫瀏覽器

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