2005-09-08 00:09:32 +00:00
|
|
|
/* COPYRIGHT: See COPYING in the top level directory
|
|
|
|
* PROJECT: ReactOS system libraries
|
2004-05-31 19:33:59 +00:00
|
|
|
* FILE: lib/rtl/largeint.c
|
|
|
|
* PURPOSE: Large integer operations
|
2007-10-19 23:21:45 +00:00
|
|
|
* PROGRAMMERS:
|
2004-05-31 19:33:59 +00:00
|
|
|
*/
|
|
|
|
|
|
|
|
/* INCLUDES *****************************************************************/
|
|
|
|
|
2005-07-26 08:39:07 +00:00
|
|
|
#include <rtl.h>
|
2004-05-31 19:33:59 +00:00
|
|
|
|
|
|
|
#define NDEBUG
|
|
|
|
#include <debug.h>
|
|
|
|
|
|
|
|
/* FUNCTIONS *****************************************************************/
|
|
|
|
|
2011-08-19 21:14:11 +00:00
|
|
|
/* HACK: ld is too stupid to understand that we need the functions
|
|
|
|
when we export them, so we force it to be linked this way. */
|
|
|
|
#ifdef __GNUC__
|
2011-02-10 11:47:17 +00:00
|
|
|
#undef RtlUshortByteSwap
|
2011-08-19 21:14:11 +00:00
|
|
|
USHORT FASTCALL RtlUshortByteSwap(USHORT Source);
|
|
|
|
PVOID Dummy = RtlUshortByteSwap;
|
|
|
|
#endif
|
2011-02-10 11:47:17 +00:00
|
|
|
|
2004-05-31 19:33:59 +00:00
|
|
|
/*
|
|
|
|
* @implemented
|
|
|
|
*/
|
|
|
|
LARGE_INTEGER
|
2005-10-19 17:03:38 +00:00
|
|
|
NTAPI
|
2004-05-31 19:33:59 +00:00
|
|
|
RtlConvertLongToLargeInteger (
|
|
|
|
LONG SignedInteger
|
|
|
|
)
|
|
|
|
{
|
|
|
|
LARGE_INTEGER RC;
|
|
|
|
|
|
|
|
RC.QuadPart = SignedInteger;
|
|
|
|
|
|
|
|
return RC;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* @implemented
|
|
|
|
*/
|
|
|
|
LARGE_INTEGER
|
2005-10-19 17:03:38 +00:00
|
|
|
NTAPI
|
2004-05-31 19:33:59 +00:00
|
|
|
RtlConvertUlongToLargeInteger (
|
|
|
|
ULONG UnsignedInteger
|
|
|
|
)
|
|
|
|
{
|
|
|
|
LARGE_INTEGER RC;
|
|
|
|
|
|
|
|
RC.QuadPart = UnsignedInteger;
|
|
|
|
|
|
|
|
return RC;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* @implemented
|
|
|
|
*/
|
|
|
|
LARGE_INTEGER
|
2005-10-19 17:03:38 +00:00
|
|
|
NTAPI
|
2004-05-31 19:33:59 +00:00
|
|
|
RtlEnlargedIntegerMultiply (
|
|
|
|
LONG Multiplicand,
|
|
|
|
LONG Multiplier
|
|
|
|
)
|
|
|
|
{
|
|
|
|
LARGE_INTEGER RC;
|
|
|
|
|
|
|
|
RC.QuadPart = (LONGLONG) Multiplicand * Multiplier;
|
|
|
|
|
|
|
|
return RC;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* @implemented
|
|
|
|
*/
|
|
|
|
ULONG
|
2005-10-19 17:03:38 +00:00
|
|
|
NTAPI
|
2004-05-31 19:33:59 +00:00
|
|
|
RtlEnlargedUnsignedDivide (
|
|
|
|
ULARGE_INTEGER Dividend,
|
|
|
|
ULONG Divisor,
|
|
|
|
PULONG Remainder
|
|
|
|
)
|
|
|
|
{
|
|
|
|
if (Remainder)
|
2007-03-02 07:21:33 +00:00
|
|
|
*Remainder = (ULONG)(Dividend.QuadPart % Divisor);
|
2004-05-31 19:33:59 +00:00
|
|
|
|
|
|
|
return (ULONG)(Dividend.QuadPart / Divisor);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* @implemented
|
|
|
|
*/
|
|
|
|
LARGE_INTEGER
|
2005-10-19 17:03:38 +00:00
|
|
|
NTAPI
|
2004-05-31 19:33:59 +00:00
|
|
|
RtlEnlargedUnsignedMultiply (
|
|
|
|
ULONG Multiplicand,
|
|
|
|
ULONG Multiplier
|
|
|
|
)
|
|
|
|
{
|
|
|
|
LARGE_INTEGER RC;
|
|
|
|
|
|
|
|
RC.QuadPart = (ULONGLONG) Multiplicand * Multiplier;
|
|
|
|
|
|
|
|
return RC;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* @implemented
|
|
|
|
*/
|
|
|
|
LARGE_INTEGER
|
2005-10-19 17:03:38 +00:00
|
|
|
NTAPI
|
2004-05-31 19:33:59 +00:00
|
|
|
RtlExtendedIntegerMultiply (
|
|
|
|
LARGE_INTEGER Multiplicand,
|
|
|
|
LONG Multiplier
|
|
|
|
)
|
|
|
|
{
|
|
|
|
LARGE_INTEGER RC;
|
|
|
|
|
|
|
|
RC.QuadPart = Multiplicand.QuadPart * Multiplier;
|
|
|
|
|
|
|
|
return RC;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* @implemented
|
|
|
|
*/
|
|
|
|
LARGE_INTEGER
|
2005-10-19 17:03:38 +00:00
|
|
|
NTAPI
|
2004-05-31 19:33:59 +00:00
|
|
|
RtlExtendedLargeIntegerDivide (
|
|
|
|
LARGE_INTEGER Dividend,
|
|
|
|
ULONG Divisor,
|
|
|
|
PULONG Remainder
|
|
|
|
)
|
|
|
|
{
|
|
|
|
LARGE_INTEGER RC;
|
|
|
|
|
|
|
|
if (Remainder)
|
2007-03-02 07:21:33 +00:00
|
|
|
*Remainder = (ULONG)(Dividend.QuadPart % Divisor);
|
2004-05-31 19:33:59 +00:00
|
|
|
|
|
|
|
RC.QuadPart = Dividend.QuadPart / Divisor;
|
|
|
|
|
|
|
|
return RC;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/******************************************************************************
|
|
|
|
* RtlExtendedMagicDivide
|
|
|
|
*
|
|
|
|
* Allows replacing a division by a longlong constant with a multiplication by
|
|
|
|
* the inverse constant.
|
|
|
|
*
|
|
|
|
* RETURNS
|
|
|
|
* (Dividend * MagicDivisor) >> (64 + ShiftCount)
|
|
|
|
*
|
|
|
|
* NOTES
|
|
|
|
* If the divisor of a division is constant, the constants MagicDivisor and
|
|
|
|
* shift must be chosen such that
|
|
|
|
* MagicDivisor = 2^(64 + ShiftCount) / Divisor.
|
|
|
|
*
|
|
|
|
* Then we have RtlExtendedMagicDivide(Dividend,MagicDivisor,ShiftCount) ==
|
|
|
|
* Dividend * MagicDivisor / 2^(64 + ShiftCount) == Dividend / Divisor.
|
|
|
|
*
|
|
|
|
* The Parameter MagicDivisor although defined as LONGLONG is used as
|
|
|
|
* ULONGLONG.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#define LOWER_32(A) ((A) & 0xffffffff)
|
|
|
|
#define UPPER_32(A) ((A) >> 32)
|
|
|
|
|
|
|
|
/*
|
|
|
|
* @implemented
|
|
|
|
*/
|
2005-10-19 17:03:38 +00:00
|
|
|
LARGE_INTEGER NTAPI
|
2004-05-31 19:33:59 +00:00
|
|
|
RtlExtendedMagicDivide (LARGE_INTEGER Dividend,
|
|
|
|
LARGE_INTEGER MagicDivisor,
|
|
|
|
CCHAR ShiftCount)
|
|
|
|
{
|
|
|
|
ULONGLONG dividend_high;
|
|
|
|
ULONGLONG dividend_low;
|
|
|
|
ULONGLONG inverse_divisor_high;
|
|
|
|
ULONGLONG inverse_divisor_low;
|
|
|
|
ULONGLONG ah_bl;
|
|
|
|
ULONGLONG al_bh;
|
|
|
|
LARGE_INTEGER result;
|
|
|
|
BOOLEAN positive;
|
|
|
|
|
|
|
|
if (Dividend.QuadPart < 0)
|
|
|
|
{
|
|
|
|
dividend_high = UPPER_32((ULONGLONG) -Dividend.QuadPart);
|
|
|
|
dividend_low = LOWER_32((ULONGLONG) -Dividend.QuadPart);
|
|
|
|
positive = FALSE;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
dividend_high = UPPER_32((ULONGLONG) Dividend.QuadPart);
|
|
|
|
dividend_low = LOWER_32((ULONGLONG) Dividend.QuadPart);
|
|
|
|
positive = TRUE;
|
|
|
|
}
|
|
|
|
inverse_divisor_high = UPPER_32((ULONGLONG) MagicDivisor.QuadPart);
|
|
|
|
inverse_divisor_low = LOWER_32((ULONGLONG) MagicDivisor.QuadPart);
|
|
|
|
|
|
|
|
ah_bl = dividend_high * inverse_divisor_low;
|
|
|
|
al_bh = dividend_low * inverse_divisor_high;
|
|
|
|
|
|
|
|
result.QuadPart =
|
|
|
|
(LONGLONG) ((dividend_high * inverse_divisor_high +
|
|
|
|
UPPER_32(ah_bl) +
|
|
|
|
UPPER_32(al_bh) +
|
|
|
|
UPPER_32(LOWER_32(ah_bl) + LOWER_32(al_bh) +
|
|
|
|
UPPER_32(dividend_low * inverse_divisor_low))) >> ShiftCount);
|
|
|
|
if (!positive)
|
|
|
|
{
|
|
|
|
result.QuadPart = -result.QuadPart;
|
|
|
|
}
|
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* @implemented
|
|
|
|
*/
|
|
|
|
LARGE_INTEGER
|
2005-10-19 17:03:38 +00:00
|
|
|
NTAPI
|
2004-05-31 19:33:59 +00:00
|
|
|
RtlLargeIntegerAdd (
|
|
|
|
LARGE_INTEGER Addend1,
|
|
|
|
LARGE_INTEGER Addend2
|
|
|
|
)
|
|
|
|
{
|
|
|
|
LARGE_INTEGER RC;
|
|
|
|
|
|
|
|
RC.QuadPart = Addend1.QuadPart + Addend2.QuadPart;
|
|
|
|
|
|
|
|
return RC;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* @implemented
|
|
|
|
*/
|
|
|
|
LARGE_INTEGER
|
2005-10-19 17:03:38 +00:00
|
|
|
NTAPI
|
2004-05-31 19:33:59 +00:00
|
|
|
RtlLargeIntegerArithmeticShift (
|
|
|
|
LARGE_INTEGER LargeInteger,
|
|
|
|
CCHAR ShiftCount
|
|
|
|
)
|
|
|
|
{
|
|
|
|
LARGE_INTEGER RC;
|
|
|
|
CHAR Shift;
|
|
|
|
|
|
|
|
Shift = ShiftCount % 64;
|
|
|
|
|
|
|
|
if (Shift < 32)
|
|
|
|
{
|
|
|
|
RC.QuadPart = LargeInteger.QuadPart >> Shift;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* copy the sign bit */
|
2004-12-11 15:23:51 +00:00
|
|
|
RC.u.HighPart = (LargeInteger.u.HighPart & 0x80000000);
|
2004-05-31 19:33:59 +00:00
|
|
|
RC.u.LowPart = LargeInteger.u.HighPart >> Shift;
|
|
|
|
}
|
|
|
|
|
|
|
|
return RC;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* @implemented
|
|
|
|
*/
|
|
|
|
LARGE_INTEGER
|
2005-10-19 17:03:38 +00:00
|
|
|
NTAPI
|
2004-05-31 19:33:59 +00:00
|
|
|
RtlLargeIntegerDivide (
|
|
|
|
LARGE_INTEGER Dividend,
|
|
|
|
LARGE_INTEGER Divisor,
|
|
|
|
PLARGE_INTEGER Remainder
|
|
|
|
)
|
|
|
|
{
|
|
|
|
LARGE_INTEGER RC;
|
|
|
|
|
|
|
|
if (Remainder)
|
|
|
|
Remainder->QuadPart = Dividend.QuadPart % Divisor.QuadPart;
|
|
|
|
|
|
|
|
RC.QuadPart = Dividend.QuadPart / Divisor.QuadPart;
|
|
|
|
|
|
|
|
return RC;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* @implemented
|
|
|
|
*/
|
|
|
|
LARGE_INTEGER
|
2005-10-19 17:03:38 +00:00
|
|
|
NTAPI
|
2004-05-31 19:33:59 +00:00
|
|
|
RtlLargeIntegerNegate (
|
|
|
|
LARGE_INTEGER Subtrahend
|
|
|
|
)
|
|
|
|
{
|
|
|
|
LARGE_INTEGER RC;
|
|
|
|
|
|
|
|
RC.QuadPart = - Subtrahend.QuadPart;
|
|
|
|
|
|
|
|
return RC;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* @implemented
|
|
|
|
*/
|
|
|
|
LARGE_INTEGER
|
2005-10-19 17:03:38 +00:00
|
|
|
NTAPI
|
2004-05-31 19:33:59 +00:00
|
|
|
RtlLargeIntegerShiftLeft (
|
|
|
|
LARGE_INTEGER LargeInteger,
|
|
|
|
CCHAR ShiftCount
|
|
|
|
)
|
|
|
|
{
|
|
|
|
LARGE_INTEGER RC;
|
|
|
|
CCHAR Shift;
|
|
|
|
|
|
|
|
Shift = ShiftCount % 64;
|
|
|
|
RC.QuadPart = LargeInteger.QuadPart << Shift;
|
|
|
|
|
|
|
|
return RC;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* @implemented
|
|
|
|
*/
|
|
|
|
LARGE_INTEGER
|
2005-10-19 17:03:38 +00:00
|
|
|
NTAPI
|
2004-05-31 19:33:59 +00:00
|
|
|
RtlLargeIntegerShiftRight (
|
|
|
|
LARGE_INTEGER LargeInteger,
|
|
|
|
CCHAR ShiftCount
|
|
|
|
)
|
|
|
|
{
|
|
|
|
LARGE_INTEGER RC;
|
|
|
|
CCHAR Shift;
|
|
|
|
|
|
|
|
Shift = ShiftCount % 64;
|
|
|
|
RC.QuadPart = LargeInteger.QuadPart >> Shift;
|
|
|
|
|
|
|
|
return RC;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* @implemented
|
|
|
|
*/
|
|
|
|
LARGE_INTEGER
|
2005-10-19 17:03:38 +00:00
|
|
|
NTAPI
|
2004-05-31 19:33:59 +00:00
|
|
|
RtlLargeIntegerSubtract (
|
|
|
|
LARGE_INTEGER Minuend,
|
|
|
|
LARGE_INTEGER Subtrahend
|
|
|
|
)
|
|
|
|
{
|
|
|
|
LARGE_INTEGER RC;
|
|
|
|
|
|
|
|
RC.QuadPart = Minuend.QuadPart - Subtrahend.QuadPart;
|
|
|
|
|
|
|
|
return RC;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* EOF */
|