VirtualBox

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

Last change on this file since 95612 was 94513, checked in by vboxsync, 3 years ago

IPRT: Added RTUInt128MulEx and RTUInt128MulU64Ex as well as a limited RTUInt256Xxx Api. [build fix] bugref:9898

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