summaryrefslogtreecommitdiffstats
path: root/include/iprt/uint256.h
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-07 16:49:04 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-07 16:49:04 +0000
commit16f504a9dca3fe3b70568f67b7d41241ae485288 (patch)
treec60f36ada0496ba928b7161059ba5ab1ab224f9d /include/iprt/uint256.h
parentInitial commit. (diff)
downloadvirtualbox-16f504a9dca3fe3b70568f67b7d41241ae485288.tar.xz
virtualbox-16f504a9dca3fe3b70568f67b7d41241ae485288.zip
Adding upstream version 7.0.6-dfsg.upstream/7.0.6-dfsgupstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'include/iprt/uint256.h')
-rw-r--r--include/iprt/uint256.h1241
1 files changed, 1241 insertions, 0 deletions
diff --git a/include/iprt/uint256.h b/include/iprt/uint256.h
new file mode 100644
index 00000000..351f7f4e
--- /dev/null
+++ b/include/iprt/uint256.h
@@ -0,0 +1,1241 @@
+/** @file
+ * IPRT - RTUINT256U methods.
+ */
+
+/*
+ * Copyright (C) 2011-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox distribution, in which case the provisions of the
+ * CDDL are applicable instead of those of the GPL.
+ *
+ * You may elect to license modified versions of this file under the
+ * terms and conditions of either the GPL or the CDDL or both.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef IPRT_INCLUDED_uint256_h
+#define IPRT_INCLUDED_uint256_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <iprt/cdefs.h>
+#include <iprt/types.h>
+#include <iprt/asm.h>
+#include <iprt/asm-math.h>
+
+RT_C_DECLS_BEGIN
+
+/** @defgroup grp_rt_uint256 RTUInt256 - 256-bit Unsigned Integer Methods
+ * @ingroup grp_rt
+ * @{
+ */
+
+
+/**
+ * Test if a 256-bit unsigned integer value is zero.
+ *
+ * @returns true if they are, false if they aren't.
+ * @param pValue The input and output value.
+ */
+DECLINLINE(bool) RTUInt256IsZero(PCRTUINT256U pValue)
+{
+#if ARCH_BITS >= 64
+ return pValue->QWords.qw0 == 0
+ && pValue->QWords.qw1 == 0
+ && pValue->QWords.qw2 == 0
+ && pValue->QWords.qw3 == 0;
+#else
+ return pValue->DWords.dw0 == 0
+ && pValue->DWords.dw1 == 0
+ && pValue->DWords.dw2 == 0
+ && pValue->DWords.dw3 == 0
+ && pValue->DWords.dw4 == 0
+ && pValue->DWords.dw5 == 0
+ && pValue->DWords.dw6 == 0
+ && pValue->DWords.dw7 == 0;
+#endif
+}
+
+
+/**
+ * Set a 256-bit unsigned integer value to zero.
+ *
+ * @returns pResult
+ * @param pResult The result variable.
+ */
+DECLINLINE(PRTUINT256U) RTUInt256SetZero(PRTUINT256U pResult)
+{
+#if ARCH_BITS >= 64
+ pResult->QWords.qw0 = 0;
+ pResult->QWords.qw1 = 0;
+ pResult->QWords.qw2 = 0;
+ pResult->QWords.qw3 = 0;
+#else
+ pResult->DWords.dw0 = 0;
+ pResult->DWords.dw1 = 0;
+ pResult->DWords.dw2 = 0;
+ pResult->DWords.dw3 = 0;
+ pResult->DWords.dw4 = 0;
+ pResult->DWords.dw5 = 0;
+ pResult->DWords.dw6 = 0;
+ pResult->DWords.dw7 = 0;
+#endif
+ return pResult;
+}
+
+
+/**
+ * Set a 256-bit unsigned integer value to the maximum value.
+ *
+ * @returns pResult
+ * @param pResult The result variable.
+ */
+DECLINLINE(PRTUINT256U) RTUInt256SetMax(PRTUINT256U pResult)
+{
+#if ARCH_BITS >= 64
+ pResult->QWords.qw0 = UINT64_MAX;
+ pResult->QWords.qw1 = UINT64_MAX;
+ pResult->QWords.qw2 = UINT64_MAX;
+ pResult->QWords.qw3 = UINT64_MAX;
+#else
+ pResult->DWords.dw0 = UINT32_MAX;
+ pResult->DWords.dw1 = UINT32_MAX;
+ pResult->DWords.dw2 = UINT32_MAX;
+ pResult->DWords.dw3 = UINT32_MAX;
+ pResult->DWords.dw4 = UINT32_MAX;
+ pResult->DWords.dw5 = UINT32_MAX;
+ pResult->DWords.dw6 = UINT32_MAX;
+ pResult->DWords.dw7 = UINT32_MAX;
+#endif
+ return pResult;
+}
+
+
+
+
+/**
+ * Adds two 256-bit unsigned integer values.
+ *
+ * @returns pResult
+ * @param pResult The result variable.
+ * @param pValue1 The first value.
+ * @param pValue2 The second value.
+ */
+DECLINLINE(PRTUINT256U) RTUInt256Add(PRTUINT256U pResult, PCRTUINT256U pValue1, PCRTUINT256U pValue2)
+{
+ unsigned uCarry;
+ pResult->QWords.qw0 = pValue1->QWords.qw0 + pValue2->QWords.qw0;
+ uCarry = pResult->QWords.qw0 < pValue1->QWords.qw0;
+
+ pResult->QWords.qw1 = pValue1->QWords.qw1 + pValue2->QWords.qw1 + uCarry;
+ uCarry = uCarry ? pResult->QWords.qw1 <= pValue1->QWords.qw1 : pResult->QWords.qw1 < pValue1->QWords.qw1;
+
+ pResult->QWords.qw2 = pValue1->QWords.qw2 + pValue2->QWords.qw2 + uCarry;
+ uCarry = uCarry ? pResult->QWords.qw2 <= pValue1->QWords.qw2 : pResult->QWords.qw2 < pValue1->QWords.qw2;
+
+ pResult->QWords.qw3 = pValue1->QWords.qw3 + pValue2->QWords.qw3 + uCarry;
+ return pResult;
+}
+
+
+/**
+ * Adds a 256-bit and a 64-bit unsigned integer values.
+ *
+ * @returns pResult
+ * @param pResult The result variable.
+ * @param pValue1 The first value.
+ * @param uValue2 The second value, 64-bit.
+ */
+DECLINLINE(PRTUINT256U) RTUInt256AddU64(PRTUINT256U pResult, PCRTUINT256U pValue1, uint64_t uValue2)
+{
+ pResult->QWords.qw3 = pValue1->QWords.qw3;
+ pResult->QWords.qw2 = pValue1->QWords.qw2;
+ pResult->QWords.qw1 = pValue1->QWords.qw1;
+ pResult->QWords.qw0 = pValue1->QWords.qw0 + uValue2;
+ if (pResult->QWords.qw0 < uValue2)
+ if (pResult->QWords.qw1++ == UINT64_MAX)
+ if (pResult->QWords.qw2++ == UINT64_MAX)
+ pResult->QWords.qw3++;
+ return pResult;
+}
+
+
+/**
+ * Subtracts a 256-bit unsigned integer value from another.
+ *
+ * @returns pResult
+ * @param pResult The result variable.
+ * @param pValue1 The minuend value.
+ * @param pValue2 The subtrahend value.
+ */
+DECLINLINE(PRTUINT256U) RTUInt256Sub(PRTUINT256U pResult, PCRTUINT256U pValue1, PCRTUINT256U pValue2)
+{
+ unsigned uBorrow;
+ pResult->QWords.qw0 = pValue1->QWords.qw0 - pValue2->QWords.qw0;
+ uBorrow = pResult->QWords.qw0 > pValue1->QWords.qw0;
+
+ pResult->QWords.qw1 = pValue1->QWords.qw1 - pValue2->QWords.qw1 - uBorrow;
+ uBorrow = uBorrow ? pResult->QWords.qw1 >= pValue1->QWords.qw1 : pResult->QWords.qw1 > pValue1->QWords.qw1;
+
+ pResult->QWords.qw2 = pValue1->QWords.qw2 - pValue2->QWords.qw2 - uBorrow;
+ uBorrow = uBorrow ? pResult->QWords.qw2 >= pValue1->QWords.qw2 : pResult->QWords.qw2 > pValue1->QWords.qw2;
+
+ pResult->QWords.qw3 = pValue1->QWords.qw3 - pValue2->QWords.qw3 - uBorrow;
+ return pResult;
+}
+
+
+/**
+ * Multiplies two 256-bit unsigned integer values.
+ *
+ * @returns pResult
+ * @param pResult The result variable.
+ * @param pValue1 The first value.
+ * @param pValue2 The second value.
+ */
+RTDECL(PRTUINT256U) RTUInt256Mul(PRTUINT256U pResult, PCRTUINT256U pValue1, PCRTUINT256U pValue2);
+
+/**
+ * Multiplies an 256-bit unsigned integer by a 64-bit unsigned integer value.
+ *
+ * @returns pResult
+ * @param pResult The result variable.
+ * @param pValue1 The first value.
+ * @param uValue2 The second value, 64-bit.
+ */
+RTDECL(PRTUINT256U) RTUInt256MulByU64(PRTUINT256U pResult, PCRTUINT256U pValue1, uint64_t uValue2);
+
+/**
+ * Divides a 256-bit unsigned integer value by another, returning both quotient
+ * and remainder.
+ *
+ * @returns pQuotient, NULL if pValue2 is 0.
+ * @param pQuotient Where to return the quotient.
+ * @param pRemainder Where to return the remainder.
+ * @param pValue1 The dividend value.
+ * @param pValue2 The divisor value.
+ */
+RTDECL(PRTUINT256U) RTUInt256DivRem(PRTUINT256U pQuotient, PRTUINT256U pRemainder, PCRTUINT256U pValue1, PCRTUINT256U pValue2);
+
+/**
+ * Divides a 256-bit unsigned integer value by another.
+ *
+ * @returns pResult
+ * @param pResult The result variable.
+ * @param pValue1 The dividend value.
+ * @param pValue2 The divisor value.
+ */
+DECLINLINE(PRTUINT256U) RTUInt256Div(PRTUINT256U pResult, PCRTUINT256U pValue1, PCRTUINT256U pValue2)
+{
+ RTUINT256U Ignored;
+ return RTUInt256DivRem(pResult, &Ignored, pValue1, pValue2);
+}
+
+
+/**
+ * Divides a 256-bit unsigned integer value by another, returning the remainder.
+ *
+ * @returns pResult
+ * @param pResult The result variable (remainder).
+ * @param pValue1 The dividend value.
+ * @param pValue2 The divisor value.
+ */
+DECLINLINE(PRTUINT256U) RTUInt256Mod(PRTUINT256U pResult, PCRTUINT256U pValue1, PCRTUINT256U pValue2)
+{
+ RTUINT256U Ignored;
+ RTUInt256DivRem(&Ignored, pResult, pValue1, pValue2);
+ return pResult;
+}
+
+
+/**
+ * Bitwise AND of two 256-bit unsigned integer values.
+ *
+ * @returns pResult
+ * @param pResult The result variable.
+ * @param pValue1 The first value.
+ * @param pValue2 The second value.
+ */
+DECLINLINE(PRTUINT256U) RTUInt256And(PRTUINT256U pResult, PCRTUINT256U pValue1, PCRTUINT256U pValue2)
+{
+ pResult->QWords.qw0 = pValue1->QWords.qw0 & pValue2->QWords.qw0;
+ pResult->QWords.qw1 = pValue1->QWords.qw1 & pValue2->QWords.qw1;
+ pResult->QWords.qw2 = pValue1->QWords.qw2 & pValue2->QWords.qw2;
+ pResult->QWords.qw3 = pValue1->QWords.qw3 & pValue2->QWords.qw3;
+ return pResult;
+}
+
+
+/**
+ * Bitwise OR of two 256-bit unsigned integer values.
+ *
+ * @returns pResult
+ * @param pResult The result variable.
+ * @param pValue1 The first value.
+ * @param pValue2 The second value.
+ */
+DECLINLINE(PRTUINT256U) RTUInt256Or( PRTUINT256U pResult, PCRTUINT256U pValue1, PCRTUINT256U pValue2)
+{
+ pResult->QWords.qw0 = pValue1->QWords.qw0 | pValue2->QWords.qw0;
+ pResult->QWords.qw1 = pValue1->QWords.qw1 | pValue2->QWords.qw1;
+ pResult->QWords.qw2 = pValue1->QWords.qw2 | pValue2->QWords.qw2;
+ pResult->QWords.qw3 = pValue1->QWords.qw3 | pValue2->QWords.qw3;
+ return pResult;
+}
+
+
+/**
+ * Bitwise XOR of two 256-bit unsigned integer values.
+ *
+ * @returns pResult
+ * @param pResult The result variable.
+ * @param pValue1 The first value.
+ * @param pValue2 The second value.
+ */
+DECLINLINE(PRTUINT256U) RTUInt256Xor(PRTUINT256U pResult, PCRTUINT256U pValue1, PCRTUINT256U pValue2)
+{
+ pResult->QWords.qw0 = pValue1->QWords.qw0 ^ pValue2->QWords.qw0;
+ pResult->QWords.qw1 = pValue1->QWords.qw1 ^ pValue2->QWords.qw1;
+ pResult->QWords.qw2 = pValue1->QWords.qw2 ^ pValue2->QWords.qw2;
+ pResult->QWords.qw3 = pValue1->QWords.qw3 ^ pValue2->QWords.qw3;
+ return pResult;
+}
+
+
+/**
+ * Shifts a 256-bit unsigned integer value @a cBits to the left.
+ *
+ * @returns pResult
+ * @param pResult The result variable.
+ * @param pValue The value to shift.
+ * @param cBits The number of bits to shift it. This is masked
+ * by 255 before shifting.
+ */
+DECLINLINE(PRTUINT256U) RTUInt256ShiftLeft(PRTUINT256U pResult, PCRTUINT256U pValue, unsigned cBits)
+{
+ /* This is a bit bulky & impractical since we cannot access the data using
+ an array because it is organized according to host endianness. Sigh. */
+ cBits &= 255;
+ if (!(cBits & 0x3f))
+ {
+ if (cBits == 0)
+ *pResult = *pValue;
+ else
+ {
+ pResult->QWords.qw0 = 0;
+ if (cBits == 64)
+ {
+ pResult->QWords.qw1 = pValue->QWords.qw0;
+ pResult->QWords.qw2 = pValue->QWords.qw1;
+ pResult->QWords.qw3 = pValue->QWords.qw2;
+ }
+ else
+ {
+ pResult->QWords.qw1 = 0;
+ if (cBits == 128)
+ {
+ pResult->QWords.qw2 = pValue->QWords.qw0;
+ pResult->QWords.qw3 = pValue->QWords.qw1;
+ }
+ else
+ {
+ pResult->QWords.qw2 = 0;
+ pResult->QWords.qw3 = pValue->QWords.qw0;
+ }
+ }
+ }
+ }
+ else if (cBits < 128)
+ {
+ if (cBits < 64)
+ {
+ pResult->QWords.qw0 = pValue->QWords.qw0 << cBits;
+ pResult->QWords.qw1 = pValue->QWords.qw0 >> (64 - cBits);
+ pResult->QWords.qw1 |= pValue->QWords.qw1 << cBits;
+ pResult->QWords.qw2 = pValue->QWords.qw1 >> (64 - cBits);
+ pResult->QWords.qw2 |= pValue->QWords.qw2 << cBits;
+ pResult->QWords.qw3 = pValue->QWords.qw2 >> (64 - cBits);
+ pResult->QWords.qw3 |= pValue->QWords.qw3 << cBits;
+ }
+ else
+ {
+ cBits -= 64;
+ pResult->QWords.qw0 = 0;
+ pResult->QWords.qw1 = pValue->QWords.qw0 << cBits;
+ pResult->QWords.qw2 = pValue->QWords.qw0 >> (64 - cBits);
+ pResult->QWords.qw2 |= pValue->QWords.qw1 << cBits;
+ pResult->QWords.qw3 = pValue->QWords.qw1 >> (64 - cBits);
+ pResult->QWords.qw3 |= pValue->QWords.qw2 << cBits;
+ }
+ }
+ else
+ {
+ if (cBits < 192)
+ {
+ cBits -= 128;
+ pResult->QWords.qw0 = 0;
+ pResult->QWords.qw1 = 0;
+ pResult->QWords.qw2 = pValue->QWords.qw0 << cBits;
+ pResult->QWords.qw3 = pValue->QWords.qw0 >> (64 - cBits);
+ pResult->QWords.qw3 |= pValue->QWords.qw1 << cBits;
+ }
+ else
+ {
+ cBits -= 192;
+ pResult->QWords.qw0 = 0;
+ pResult->QWords.qw1 = 0;
+ pResult->QWords.qw2 = 0;
+ pResult->QWords.qw3 = pValue->QWords.qw0 << cBits;
+ }
+ }
+ return pResult;
+}
+
+
+/**
+ * Shifts a 256-bit unsigned integer value @a cBits to the right.
+ *
+ * @returns pResult
+ * @param pResult The result variable.
+ * @param pValue The value to shift.
+ * @param cBits The number of bits to shift it. This is masked
+ * by 255 before shifting.
+ */
+DECLINLINE(PRTUINT256U) RTUInt256ShiftRight(PRTUINT256U pResult, PCRTUINT256U pValue, unsigned cBits)
+{
+ /* This is a bit bulky & impractical since we cannot access the data using
+ an array because it is organized according to host endianness. Sigh. */
+ cBits &= 255;
+ if (!(cBits & 0x3f))
+ {
+ if (cBits == 0)
+ *pResult = *pValue;
+ else
+ {
+ if (cBits == 64)
+ {
+ pResult->QWords.qw0 = pValue->QWords.qw1;
+ pResult->QWords.qw1 = pValue->QWords.qw2;
+ pResult->QWords.qw2 = pValue->QWords.qw3;
+ }
+ else
+ {
+ if (cBits == 128)
+ {
+ pResult->QWords.qw0 = pValue->QWords.qw2;
+ pResult->QWords.qw1 = pValue->QWords.qw3;
+ }
+ else
+ {
+ pResult->QWords.qw0 = pValue->QWords.qw3;
+ pResult->QWords.qw1 = 0;
+ }
+ pResult->QWords.qw2 = 0;
+ }
+ pResult->QWords.qw3 = 0;
+ }
+ }
+ else if (cBits < 128)
+ {
+ if (cBits < 64)
+ {
+ pResult->QWords.qw0 = pValue->QWords.qw0 >> cBits;
+ pResult->QWords.qw0 |= pValue->QWords.qw1 << (64 - cBits);
+ pResult->QWords.qw1 = pValue->QWords.qw1 >> cBits;
+ pResult->QWords.qw1 |= pValue->QWords.qw2 << (64 - cBits);
+ pResult->QWords.qw2 = pValue->QWords.qw2 >> cBits;
+ pResult->QWords.qw2 |= pValue->QWords.qw3 << (64 - cBits);
+ pResult->QWords.qw3 = pValue->QWords.qw3 >> cBits;
+ }
+ else
+ {
+ cBits -= 64;
+ pResult->QWords.qw0 = pValue->QWords.qw1 >> cBits;
+ pResult->QWords.qw0 |= pValue->QWords.qw2 << (64 - cBits);
+ pResult->QWords.qw1 = pValue->QWords.qw2 >> cBits;
+ pResult->QWords.qw1 |= pValue->QWords.qw3 << (64 - cBits);
+ pResult->QWords.qw2 = pValue->QWords.qw3 >> cBits;
+ pResult->QWords.qw3 = 0;
+ }
+ }
+ else
+ {
+ if (cBits < 192)
+ {
+ cBits -= 128;
+ pResult->QWords.qw0 = pValue->QWords.qw2 >> cBits;
+ pResult->QWords.qw0 |= pValue->QWords.qw3 << (64 - cBits);
+ pResult->QWords.qw1 = pValue->QWords.qw3 >> cBits;
+ pResult->QWords.qw2 = 0;
+ pResult->QWords.qw3 = 0;
+ }
+ else
+ {
+ cBits -= 192;
+ pResult->QWords.qw0 = pValue->QWords.qw3 >> cBits;
+ pResult->QWords.qw1 = 0;
+ pResult->QWords.qw2 = 0;
+ pResult->QWords.qw3 = 0;
+ }
+ }
+ return pResult;
+}
+
+
+/**
+ * Boolean not (result 0 or 1).
+ *
+ * @returns pResult.
+ * @param pResult The result variable.
+ * @param pValue The value.
+ */
+DECLINLINE(PRTUINT256U) RTUInt256BooleanNot(PRTUINT256U pResult, PCRTUINT256U pValue)
+{
+ pResult->QWords.qw0 = RTUInt256IsZero(pValue);
+ pResult->QWords.qw1 = 0;
+ pResult->QWords.qw2 = 0;
+ pResult->QWords.qw3 = 0;
+ return pResult;
+}
+
+
+/**
+ * Bitwise not (flips each bit of the 256 bits).
+ *
+ * @returns pResult.
+ * @param pResult The result variable.
+ * @param pValue The value.
+ */
+DECLINLINE(PRTUINT256U) RTUInt256BitwiseNot(PRTUINT256U pResult, PCRTUINT256U pValue)
+{
+ pResult->QWords.qw0 = ~pValue->QWords.qw0;
+ pResult->QWords.qw1 = ~pValue->QWords.qw1;
+ pResult->QWords.qw2 = ~pValue->QWords.qw2;
+ pResult->QWords.qw3 = ~pValue->QWords.qw3;
+ return pResult;
+}
+
+
+/**
+ * Assigns one 256-bit unsigned integer value to another.
+ *
+ * @returns pResult
+ * @param pResult The result variable.
+ * @param pValue The value to assign.
+ */
+DECLINLINE(PRTUINT256U) RTUInt256Assign(PRTUINT256U pResult, PCRTUINT256U pValue)
+{
+ pResult->QWords.qw0 = pValue->QWords.qw0;
+ pResult->QWords.qw1 = pValue->QWords.qw1;
+ pResult->QWords.qw2 = pValue->QWords.qw2;
+ pResult->QWords.qw3 = pValue->QWords.qw3;
+ return pResult;
+}
+
+
+/**
+ * Assigns a boolean value to 256-bit unsigned integer.
+ *
+ * @returns pValueResult
+ * @param pValueResult The result variable.
+ * @param fValue The boolean value.
+ */
+DECLINLINE(PRTUINT256U) RTUInt256AssignBoolean(PRTUINT256U pValueResult, bool fValue)
+{
+ pValueResult->QWords.qw0 = fValue;
+ pValueResult->QWords.qw1 = 0;
+ pValueResult->QWords.qw2 = 0;
+ pValueResult->QWords.qw3 = 0;
+ return pValueResult;
+}
+
+
+/**
+ * Assigns a 8-bit unsigned integer value to 256-bit unsigned integer.
+ *
+ * @returns pValueResult
+ * @param pValueResult The result variable.
+ * @param u8Value The 8-bit unsigned integer value.
+ */
+DECLINLINE(PRTUINT256U) RTUInt256AssignU8(PRTUINT256U pValueResult, uint8_t u8Value)
+{
+ pValueResult->QWords.qw0 = u8Value;
+ pValueResult->QWords.qw1 = 0;
+ pValueResult->QWords.qw2 = 0;
+ pValueResult->QWords.qw3 = 0;
+ return pValueResult;
+}
+
+
+/**
+ * Assigns a 16-bit unsigned integer value to 256-bit unsigned integer.
+ *
+ * @returns pValueResult
+ * @param pValueResult The result variable.
+ * @param u16Value The 16-bit unsigned integer value.
+ */
+DECLINLINE(PRTUINT256U) RTUInt256AssignU16(PRTUINT256U pValueResult, uint16_t u16Value)
+{
+ pValueResult->QWords.qw0 = u16Value;
+ pValueResult->QWords.qw1 = 0;
+ pValueResult->QWords.qw2 = 0;
+ pValueResult->QWords.qw3 = 0;
+ return pValueResult;
+}
+
+
+/**
+ * Assigns a 32-bit unsigned integer value to 256-bit unsigned integer.
+ *
+ * @returns pValueResult
+ * @param pValueResult The result variable.
+ * @param u32Value The 32-bit unsigned integer value.
+ */
+DECLINLINE(PRTUINT256U) RTUInt256AssignU32(PRTUINT256U pValueResult, uint32_t u32Value)
+{
+ pValueResult->QWords.qw0 = u32Value;
+ pValueResult->QWords.qw1 = 0;
+ pValueResult->QWords.qw2 = 0;
+ pValueResult->QWords.qw3 = 0;
+ return pValueResult;
+}
+
+
+/**
+ * Assigns a 64-bit unsigned integer value to 256-bit unsigned integer.
+ *
+ * @returns pValueResult
+ * @param pValueResult The result variable.
+ * @param u64Value The 64-bit unsigned integer value.
+ */
+DECLINLINE(PRTUINT256U) RTUInt256AssignU64(PRTUINT256U pValueResult, uint64_t u64Value)
+{
+ pValueResult->QWords.qw0 = u64Value;
+ pValueResult->QWords.qw1 = 0;
+ pValueResult->QWords.qw2 = 0;
+ pValueResult->QWords.qw3 = 0;
+ return pValueResult;
+}
+
+
+/**
+ * Adds two 256-bit unsigned integer values, storing the result in the first.
+ *
+ * @returns pValue1Result.
+ * @param pValue1Result The first value and result.
+ * @param pValue2 The second value.
+ */
+DECLINLINE(PRTUINT256U) RTUInt256AssignAdd(PRTUINT256U pValue1Result, PCRTUINT256U pValue2)
+{
+ RTUINT256U const uTmpValue1 = *pValue1Result; /* lazy bird */
+ return RTUInt256Add(pValue1Result, &uTmpValue1, pValue2);
+}
+
+
+/**
+ * Adds a 64-bit unsigned integer value to a 256-bit unsigned integer values,
+ * storing the result in the 256-bit one.
+ *
+ * @returns pValue1Result.
+ * @param pValue1Result The first value and result.
+ * @param uValue2 The second value, 64-bit.
+ */
+DECLINLINE(PRTUINT256U) RTUInt256AssignAddU64(PRTUINT256U pValue1Result, uint64_t uValue2)
+{
+ RTUINT256U const uTmpValue1 = *pValue1Result; /* lazy bird */
+ return RTUInt256AddU64(pValue1Result, &uTmpValue1, uValue2);
+}
+
+
+/**
+ * Subtracts two 256-bit unsigned integer values, storing the result in the
+ * first.
+ *
+ * @returns pValue1Result.
+ * @param pValue1Result The minuend value and result.
+ * @param pValue2 The subtrahend value.
+ */
+DECLINLINE(PRTUINT256U) RTUInt256AssignSub(PRTUINT256U pValue1Result, PCRTUINT256U pValue2)
+{
+ RTUINT256U const uTmpValue1 = *pValue1Result; /* lazy bird */
+ return RTUInt256Sub(pValue1Result, &uTmpValue1, pValue2);
+}
+
+
+#if 0
+/**
+ * Negates a 256 number, storing the result in the input.
+ *
+ * @returns pValueResult.
+ * @param pValueResult The value to negate.
+ */
+DECLINLINE(PRTUINT256U) RTUInt256AssignNeg(PRTUINT256U pValueResult)
+{
+ /* result = 0 - value */
+ if (pValueResult->s.Lo != 0)
+ {
+ pValueResult->s.Lo = UINT64_C(0) - pValueResult->s.Lo;
+ pValueResult->s.Hi = UINT64_MAX - pValueResult->s.Hi;
+ }
+ else
+ pValueResult->s.Hi = UINT64_C(0) - pValueResult->s.Hi;
+ return pValueResult;
+}
+#endif
+
+
+/**
+ * Multiplies two 256-bit unsigned integer values, storing the result in the
+ * first.
+ *
+ * @returns pValue1Result.
+ * @param pValue1Result The first value and result.
+ * @param pValue2 The second value.
+ */
+DECLINLINE(PRTUINT256U) RTUInt256AssignMul(PRTUINT256U pValue1Result, PCRTUINT256U pValue2)
+{
+ RTUINT256U Result;
+ RTUInt256Mul(&Result, pValue1Result, pValue2);
+ *pValue1Result = Result;
+ return pValue1Result;
+}
+
+
+/**
+ * Divides a 256-bit unsigned integer value by another, storing the result in
+ * the first.
+ *
+ * @returns pValue1Result.
+ * @param pValue1Result The dividend value and result.
+ * @param pValue2 The divisor value.
+ */
+DECLINLINE(PRTUINT256U) RTUInt256AssignDiv(PRTUINT256U pValue1Result, PCRTUINT256U pValue2)
+{
+ RTUINT256U Result;
+ RTUINT256U Ignored;
+ RTUInt256DivRem(&Result, &Ignored, pValue1Result, pValue2);
+ *pValue1Result = Result;
+ return pValue1Result;
+}
+
+
+/**
+ * Divides a 256-bit unsigned integer value by another, storing the remainder in
+ * the first.
+ *
+ * @returns pValue1Result.
+ * @param pValue1Result The dividend value and result (remainder).
+ * @param pValue2 The divisor value.
+ */
+DECLINLINE(PRTUINT256U) RTUInt256AssignMod(PRTUINT256U pValue1Result, PCRTUINT256U pValue2)
+{
+ RTUINT256U Ignored;
+ RTUINT256U Result;
+ RTUInt256DivRem(&Ignored, &Result, pValue1Result, pValue2);
+ *pValue1Result = Result;
+ return pValue1Result;
+}
+
+
+/**
+ * Performs a bitwise AND of two 256-bit unsigned integer values and assigned
+ * the result to the first one.
+ *
+ * @returns pValue1Result.
+ * @param pValue1Result The first value and result.
+ * @param pValue2 The second value.
+ */
+DECLINLINE(PRTUINT256U) RTUInt256AssignAnd(PRTUINT256U pValue1Result, PCRTUINT256U pValue2)
+{
+ pValue1Result->QWords.qw0 &= pValue2->QWords.qw0;
+ pValue1Result->QWords.qw1 &= pValue2->QWords.qw1;
+ pValue1Result->QWords.qw2 &= pValue2->QWords.qw2;
+ pValue1Result->QWords.qw3 &= pValue2->QWords.qw3;
+ return pValue1Result;
+}
+
+
+#if 0
+/**
+ * Performs a bitwise AND of a 256-bit unsigned integer value and a mask made
+ * up of the first N bits, assigning the result to the the 256-bit value.
+ *
+ * @returns pValueResult.
+ * @param pValueResult The value and result.
+ * @param cBits The number of bits to AND (counting from the first
+ * bit).
+ */
+DECLINLINE(PRTUINT256U) RTUInt256AssignAndNFirstBits(PRTUINT256U pValueResult, unsigned cBits)
+{
+ if (cBits <= 64)
+ {
+ if (cBits != 64)
+ pValueResult->s.Lo &= (RT_BIT_64(cBits) - 1);
+ pValueResult->s.Hi = 0;
+ }
+ else if (cBits < 256)
+ pValueResult->s.Hi &= (RT_BIT_64(cBits - 64) - 1);
+/** @todo \#if ARCH_BITS >= 64 */
+ return pValueResult;
+}
+#endif
+
+
+/**
+ * Performs a bitwise OR of two 256-bit unsigned integer values and assigned
+ * the result to the first one.
+ *
+ * @returns pValue1Result.
+ * @param pValue1Result The first value and result.
+ * @param pValue2 The second value.
+ */
+DECLINLINE(PRTUINT256U) RTUInt256AssignOr(PRTUINT256U pValue1Result, PCRTUINT256U pValue2)
+{
+ pValue1Result->QWords.qw0 |= pValue2->QWords.qw0;
+ pValue1Result->QWords.qw1 |= pValue2->QWords.qw1;
+ pValue1Result->QWords.qw2 |= pValue2->QWords.qw2;
+ pValue1Result->QWords.qw3 |= pValue2->QWords.qw3;
+ return pValue1Result;
+}
+
+
+DECLINLINE(PRTUINT256U) RTUInt256BitSet(PRTUINT256U pValueResult, unsigned iBit);
+
+/**
+ * ORs in a bit and assign the result to the input value.
+ *
+ * @returns pValue1Result.
+ * @param pValue1Result The first value and result.
+ * @param iBit The bit to set (0 based).
+ */
+DECLINLINE(PRTUINT256U) RTUInt256AssignOrBit(PRTUINT256U pValue1Result, uint32_t iBit)
+{
+ return RTUInt256BitSet(pValue1Result, (unsigned)iBit);
+}
+
+
+/**
+ * Performs a bitwise XOR of two 256-bit unsigned integer values and assigned
+ * the result to the first one.
+ *
+ * @returns pValue1Result.
+ * @param pValue1Result The first value and result.
+ * @param pValue2 The second value.
+ */
+DECLINLINE(PRTUINT256U) RTUInt256AssignXor(PRTUINT256U pValue1Result, PCRTUINT256U pValue2)
+{
+ pValue1Result->QWords.qw0 ^= pValue2->QWords.qw0;
+ pValue1Result->QWords.qw1 ^= pValue2->QWords.qw1;
+ pValue1Result->QWords.qw2 ^= pValue2->QWords.qw2;
+ pValue1Result->QWords.qw3 ^= pValue2->QWords.qw3;
+ return pValue1Result;
+}
+
+
+/**
+ * Performs a bitwise left shift on a 256-bit unsigned integer value, assigning
+ * the result to it.
+ *
+ * @returns pValueResult.
+ * @param pValueResult The first value and result.
+ * @param cBits The number of bits to shift - signed. Negative
+ * values are translated to right shifts. If the
+ * absolute value is 256 or higher, the value is set to
+ * zero.
+ *
+ * @note This works differently from RTUInt256ShiftLeft and
+ * RTUInt256ShiftRight in that the shift count is signed and not masked
+ * by 255.
+ */
+DECLINLINE(PRTUINT256U) RTUInt256AssignShiftLeft(PRTUINT256U pValueResult, int cBits)
+{
+ if (cBits == 0)
+ return pValueResult;
+ if (cBits > 0)
+ {
+ /* (left shift) */
+ if (cBits < 256)
+ {
+ RTUINT256U const InVal = *pValueResult;
+ return RTUInt256ShiftLeft(pValueResult, &InVal, cBits);
+ }
+ }
+ else if (cBits > -256)
+ {
+ /* (right shift) */
+ cBits = -cBits;
+ RTUINT256U const InVal = *pValueResult;
+ return RTUInt256ShiftRight(pValueResult, &InVal, cBits);
+ }
+ return RTUInt256SetZero(pValueResult);
+}
+
+
+/**
+ * Performs a bitwise left shift on a 256-bit unsigned integer value, assigning
+ * the result to it.
+ *
+ * @returns pValueResult.
+ * @param pValueResult The first value and result.
+ * @param cBits The number of bits to shift - signed. Negative
+ * values are translated to left shifts. If the
+ * absolute value is 256 or higher, the value is set to
+ * zero.
+ *
+ * @note This works differently from RTUInt256ShiftRight and
+ * RTUInt256ShiftLeft in that the shift count is signed and not masked
+ * by 255.
+ */
+DECLINLINE(PRTUINT256U) RTUInt256AssignShiftRight(PRTUINT256U pValueResult, int cBits)
+{
+ if (cBits == 0)
+ return pValueResult;
+ if (cBits > 0)
+ {
+ /* (right shift) */
+ if (cBits < 256)
+ {
+ RTUINT256U const InVal = *pValueResult;
+ return RTUInt256ShiftRight(pValueResult, &InVal, cBits);
+ }
+ }
+ else if (cBits > -256)
+ {
+ /* (left shift) */
+ cBits = -cBits;
+ RTUINT256U const InVal = *pValueResult;
+ return RTUInt256ShiftLeft(pValueResult, &InVal, cBits);
+ }
+ return RTUInt256SetZero(pValueResult);
+}
+
+
+/**
+ * Performs a bitwise NOT on a 256-bit unsigned integer value, assigning the
+ * result to it.
+ *
+ * @returns pValueResult
+ * @param pValueResult The value and result.
+ */
+DECLINLINE(PRTUINT256U) RTUInt256AssignBitwiseNot(PRTUINT256U pValueResult)
+{
+ pValueResult->QWords.qw0 = ~pValueResult->QWords.qw0;
+ pValueResult->QWords.qw1 = ~pValueResult->QWords.qw1;
+ pValueResult->QWords.qw2 = ~pValueResult->QWords.qw2;
+ pValueResult->QWords.qw3 = ~pValueResult->QWords.qw3;
+ return pValueResult;
+}
+
+
+/**
+ * Performs a boolean NOT on a 256-bit unsigned integer value, assigning the
+ * result to it.
+ *
+ * @returns pValueResult
+ * @param pValueResult The value and result.
+ */
+DECLINLINE(PRTUINT256U) RTUInt256AssignBooleanNot(PRTUINT256U pValueResult)
+{
+ return RTUInt256AssignBoolean(pValueResult, RTUInt256IsZero(pValueResult));
+}
+
+
+/**
+ * Compares two 256-bit unsigned integer values.
+ *
+ * @retval 0 if equal.
+ * @retval -1 if the first value is smaller than the second.
+ * @retval 1 if the first value is larger than the second.
+ *
+ * @param pValue1 The first value.
+ * @param pValue2 The second value.
+ */
+DECLINLINE(int) RTUInt256Compare(PCRTUINT256U pValue1, PCRTUINT256U pValue2)
+{
+ if (pValue1->QWords.qw3 != pValue2->QWords.qw3)
+ return pValue1->QWords.qw3 > pValue2->QWords.qw3 ? 1 : -1;
+ if (pValue1->QWords.qw2 != pValue2->QWords.qw2)
+ return pValue1->QWords.qw2 > pValue2->QWords.qw2 ? 1 : -1;
+ if (pValue1->QWords.qw1 != pValue2->QWords.qw1)
+ return pValue1->QWords.qw1 > pValue2->QWords.qw1 ? 1 : -1;
+ if (pValue1->QWords.qw0 != pValue2->QWords.qw0)
+ return pValue1->QWords.qw3 > pValue2->QWords.qw3 ? 1 : -1;
+ return 0;
+}
+
+
+/**
+ * Tests if a 256-bit unsigned integer value is smaller than another.
+ *
+ * @returns true if the first value is smaller, false if not.
+ * @param pValue1 The first value.
+ * @param pValue2 The second value.
+ */
+DECLINLINE(bool) RTUInt256IsSmaller(PCRTUINT256U pValue1, PCRTUINT256U pValue2)
+{
+ return pValue1->QWords.qw3 < pValue2->QWords.qw3
+ || ( pValue1->QWords.qw3 == pValue2->QWords.qw3
+ && ( pValue1->QWords.qw2 < pValue2->QWords.qw2
+ || ( pValue1->QWords.qw2 == pValue2->QWords.qw2
+ && ( pValue1->QWords.qw1 < pValue2->QWords.qw1
+ || ( pValue1->QWords.qw1 == pValue2->QWords.qw1
+ && pValue1->QWords.qw0 < pValue2->QWords.qw0)))));
+}
+
+
+/**
+ * Tests if a 256-bit unsigned integer value is larger than another.
+ *
+ * @returns true if the first value is larger, false if not.
+ * @param pValue1 The first value.
+ * @param pValue2 The second value.
+ */
+DECLINLINE(bool) RTUInt256IsLarger(PCRTUINT256U pValue1, PCRTUINT256U pValue2)
+{
+ return pValue1->QWords.qw3 > pValue2->QWords.qw3
+ || ( pValue1->QWords.qw3 == pValue2->QWords.qw3
+ && ( pValue1->QWords.qw2 > pValue2->QWords.qw2
+ || ( pValue1->QWords.qw2 == pValue2->QWords.qw2
+ && ( pValue1->QWords.qw1 > pValue2->QWords.qw1
+ || ( pValue1->QWords.qw1 == pValue2->QWords.qw1
+ && pValue1->QWords.qw0 > pValue2->QWords.qw0)))));
+}
+
+
+/**
+ * Tests if a 256-bit unsigned integer value is larger or equal than another.
+ *
+ * @returns true if the first value is larger or equal, false if not.
+ * @param pValue1 The first value.
+ * @param pValue2 The second value.
+ */
+DECLINLINE(bool) RTUInt256IsLargerOrEqual(PCRTUINT256U pValue1, PCRTUINT256U pValue2)
+{
+ return pValue1->QWords.qw3 > pValue2->QWords.qw3
+ || ( pValue1->QWords.qw3 == pValue2->QWords.qw3
+ && ( pValue1->QWords.qw2 > pValue2->QWords.qw2
+ || ( pValue1->QWords.qw2 == pValue2->QWords.qw2
+ && ( pValue1->QWords.qw1 > pValue2->QWords.qw1
+ || ( pValue1->QWords.qw1 == pValue2->QWords.qw1
+ && pValue1->QWords.qw0 >= pValue2->DWords.dw0)))));
+}
+
+
+/**
+ * Tests if two 256-bit unsigned integer values not equal.
+ *
+ * @returns true if equal, false if not equal.
+ * @param pValue1 The first value.
+ * @param pValue2 The second value.
+ */
+DECLINLINE(bool) RTUInt256IsEqual(PCRTUINT256U pValue1, PCRTUINT256U pValue2)
+{
+ return pValue1->QWords.qw0 == pValue2->QWords.qw0
+ && pValue1->QWords.qw1 == pValue2->QWords.qw1
+ && pValue1->QWords.qw2 == pValue2->QWords.qw2
+ && pValue1->QWords.qw3 == pValue2->QWords.qw3;
+}
+
+
+/**
+ * Tests if two 256-bit unsigned integer values are not equal.
+ *
+ * @returns true if not equal, false if equal.
+ * @param pValue1 The first value.
+ * @param pValue2 The second value.
+ */
+DECLINLINE(bool) RTUInt256IsNotEqual(PCRTUINT256U pValue1, PCRTUINT256U pValue2)
+{
+ return !RTUInt256IsEqual(pValue1, pValue2);
+}
+
+
+/**
+ * Sets a bit in a 256-bit unsigned integer type.
+ *
+ * @returns pValueResult.
+ * @param pValueResult The input and output value.
+ * @param iBit The bit to set.
+ */
+DECLINLINE(PRTUINT256U) RTUInt256BitSet(PRTUINT256U pValueResult, unsigned iBit)
+{
+ if (iBit < 256)
+ {
+ unsigned idxQWord = iBit >> 6;
+#ifdef RT_BIG_ENDIAN
+ idxQWord = RT_ELEMENTS(pValueResult->au64) - idxQWord;
+#endif
+ iBit &= 0x3f;
+ pValueResult->au64[idxQWord] |= RT_BIT_64(iBit);
+ }
+ return pValueResult;
+}
+
+
+/**
+ * Sets a bit in a 256-bit unsigned integer type.
+ *
+ * @returns pValueResult.
+ * @param pValueResult The input and output value.
+ * @param iBit The bit to set.
+ */
+DECLINLINE(PRTUINT256U) RTUInt256BitClear(PRTUINT256U pValueResult, unsigned iBit)
+{
+ if (iBit < 256)
+ {
+ unsigned idxQWord = iBit >> 6;
+#ifdef RT_BIG_ENDIAN
+ idxQWord = RT_ELEMENTS(pValueResult->au64) - idxQWord;
+#endif
+ iBit &= 0x3f;
+ pValueResult->au64[idxQWord] &= ~RT_BIT_64(iBit);
+ }
+ return pValueResult;
+}
+
+
+/**
+ * Tests if a bit in a 256-bit unsigned integer value is set.
+ *
+ * @returns pValueResult.
+ * @param pValueResult The input and output value.
+ * @param iBit The bit to test.
+ */
+DECLINLINE(bool) RTUInt256BitTest(PRTUINT256U pValueResult, unsigned iBit)
+{
+ bool fRc;
+ if (iBit < 256)
+ {
+ unsigned idxQWord = iBit >> 6;
+#ifdef RT_BIG_ENDIAN
+ idxQWord = RT_ELEMENTS(pValueResult->au64) - idxQWord;
+#endif
+ iBit &= 0x3f;
+ fRc = RT_BOOL(pValueResult->au64[idxQWord] & RT_BIT_64(iBit));
+ }
+ else
+ fRc = false;
+ return fRc;
+}
+
+
+/**
+ * Set a range of bits a 256-bit unsigned integer value.
+ *
+ * @returns pValueResult.
+ * @param pValueResult The input and output value.
+ * @param iFirstBit The first bit to test.
+ * @param cBits The number of bits to set.
+ */
+DECLINLINE(PRTUINT256U) RTUInt256BitSetRange(PRTUINT256U pValueResult, unsigned iFirstBit, unsigned cBits)
+{
+ /* bounds check & fix. */
+ if (iFirstBit < 256)
+ {
+ if (iFirstBit + cBits > 256)
+ cBits = 256 - iFirstBit;
+
+ /* Work the au64 array: */
+#ifdef RT_BIG_ENDIAN
+ int idxQWord = RT_ELEMENTS(pValueResult->au64) - (iFirstBit >> 6);
+ int const idxInc = -1;
+#else
+ int idxQWord = iFirstBit >> 6;
+ int const idxInc = 1;
+#endif
+ while (cBits > 0)
+ {
+ unsigned iQWordFirstBit = iFirstBit & 0x3f;
+ unsigned cQWordBits = cBits + iQWordFirstBit >= 64 ? 64 - iQWordFirstBit : cBits;
+ pValueResult->au64[idxQWord] |= cQWordBits < 64 ? (RT_BIT_64(cQWordBits) - 1) << iQWordFirstBit : UINT64_MAX;
+
+ idxQWord += idxInc;
+ iFirstBit += cQWordBits;
+ cBits -= cQWordBits;
+ }
+ }
+ return pValueResult;
+}
+
+
+/**
+ * Test if all the bits of a 256-bit unsigned integer value are set.
+ *
+ * @returns true if they are, false if they aren't.
+ * @param pValue The input and output value.
+ */
+DECLINLINE(bool) RTUInt256BitAreAllSet(PRTUINT256U pValue)
+{
+ return pValue->QWords.qw0 == UINT64_MAX
+ && pValue->QWords.qw1 == UINT64_MAX
+ && pValue->QWords.qw2 == UINT64_MAX
+ && pValue->QWords.qw3 == UINT64_MAX;
+}
+
+
+/**
+ * Test if all the bits of a 256-bit unsigned integer value are clear.
+ *
+ * @returns true if they are, false if they aren't.
+ * @param pValue The input and output value.
+ */
+DECLINLINE(bool) RTUInt256BitAreAllClear(PRTUINT256U pValue)
+{
+ return RTUInt256IsZero(pValue);
+}
+
+
+/**
+ * Number of significant bits in the value.
+ *
+ * This is the same a ASMBitLastSetU64 and ASMBitLastSetU32.
+ *
+ * @returns 0 if zero, 1-base index of the last bit set.
+ * @param pValue The value to examine.
+ */
+DECLINLINE(uint32_t) RTUInt256BitCount(PCRTUINT256U pValue)
+{
+ uint64_t u64;
+ uint32_t cBits;
+ if ((u64 = pValue->QWords.qw3) != 0)
+ cBits = 192;
+ else if ((u64 = pValue->QWords.qw2) != 0)
+ cBits = 128;
+ else if ((u64 = pValue->QWords.qw1) != 0)
+ cBits = 64;
+ else
+ {
+ u64 = pValue->QWords.qw0;
+ cBits = 0;
+ }
+ return cBits + ASMBitLastSetU64(u64);
+}
+
+
+/** @} */
+
+RT_C_DECLS_END
+
+#endif /* !IPRT_INCLUDED_uint256_h */
+