VirtualBox

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

Last change on this file since 73768 was 69105, checked in by vboxsync, 7 years ago

include/iprt/: (C) year

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

© 2023 Oracle
ContactPrivacy policyTerms of Use