VirtualBox

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

Last change on this file since 53294 was 52335, checked in by vboxsync, 10 years ago

RTBigNum: Added shift APIs, implemented a faster division algorithm, optimized multiplication on x86 & amd64.

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