1241 lines
38 KiB
C
1241 lines
38 KiB
C
/** @file
|
|
* IPRT - RTUINT256U methods.
|
|
*/
|
|
|
|
/*
|
|
* Copyright (C) 2011-2023 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 */
|
|
|