reactos/lib/rtl/largeint.c
Amine Khaldi 527f2f9057 [SHELL/EXPERIMENTS]
* Create a branch for some evul shell experiments.

svn path=/branches/shell-experiments/; revision=61927
2014-02-02 19:37:27 +00:00

359 lines
6.2 KiB
C

/* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS system libraries
* FILE: lib/rtl/largeint.c
* PURPOSE: Large integer operations
* PROGRAMMERS:
*/
/* INCLUDES *****************************************************************/
#include <rtl.h>
#define NDEBUG
#include <debug.h>
/* FUNCTIONS *****************************************************************/
/* 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__
#undef RtlUshortByteSwap
USHORT FASTCALL RtlUshortByteSwap(USHORT Source);
PVOID Dummy = RtlUshortByteSwap;
#endif
/*
* @implemented
*/
LARGE_INTEGER
NTAPI
RtlConvertLongToLargeInteger (
LONG SignedInteger
)
{
LARGE_INTEGER RC;
RC.QuadPart = SignedInteger;
return RC;
}
/*
* @implemented
*/
LARGE_INTEGER
NTAPI
RtlConvertUlongToLargeInteger (
ULONG UnsignedInteger
)
{
LARGE_INTEGER RC;
RC.QuadPart = UnsignedInteger;
return RC;
}
/*
* @implemented
*/
LARGE_INTEGER
NTAPI
RtlEnlargedIntegerMultiply (
LONG Multiplicand,
LONG Multiplier
)
{
LARGE_INTEGER RC;
RC.QuadPart = (LONGLONG) Multiplicand * Multiplier;
return RC;
}
/*
* @implemented
*/
ULONG
NTAPI
RtlEnlargedUnsignedDivide (
ULARGE_INTEGER Dividend,
ULONG Divisor,
PULONG Remainder
)
{
if (Remainder)
*Remainder = (ULONG)(Dividend.QuadPart % Divisor);
return (ULONG)(Dividend.QuadPart / Divisor);
}
/*
* @implemented
*/
LARGE_INTEGER
NTAPI
RtlEnlargedUnsignedMultiply (
ULONG Multiplicand,
ULONG Multiplier
)
{
LARGE_INTEGER RC;
RC.QuadPart = (ULONGLONG) Multiplicand * Multiplier;
return RC;
}
/*
* @implemented
*/
LARGE_INTEGER
NTAPI
RtlExtendedIntegerMultiply (
LARGE_INTEGER Multiplicand,
LONG Multiplier
)
{
LARGE_INTEGER RC;
RC.QuadPart = Multiplicand.QuadPart * Multiplier;
return RC;
}
/*
* @implemented
*/
LARGE_INTEGER
NTAPI
RtlExtendedLargeIntegerDivide (
LARGE_INTEGER Dividend,
ULONG Divisor,
PULONG Remainder
)
{
LARGE_INTEGER RC;
if (Remainder)
*Remainder = (ULONG)(Dividend.QuadPart % Divisor);
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
*/
LARGE_INTEGER NTAPI
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
NTAPI
RtlLargeIntegerAdd (
LARGE_INTEGER Addend1,
LARGE_INTEGER Addend2
)
{
LARGE_INTEGER RC;
RC.QuadPart = Addend1.QuadPart + Addend2.QuadPart;
return RC;
}
/*
* @implemented
*/
LARGE_INTEGER
NTAPI
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 */
RC.u.HighPart = (LargeInteger.u.HighPart & 0x80000000);
RC.u.LowPart = LargeInteger.u.HighPart >> Shift;
}
return RC;
}
/*
* @implemented
*/
LARGE_INTEGER
NTAPI
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
NTAPI
RtlLargeIntegerNegate (
LARGE_INTEGER Subtrahend
)
{
LARGE_INTEGER RC;
RC.QuadPart = - Subtrahend.QuadPart;
return RC;
}
/*
* @implemented
*/
LARGE_INTEGER
NTAPI
RtlLargeIntegerShiftLeft (
LARGE_INTEGER LargeInteger,
CCHAR ShiftCount
)
{
LARGE_INTEGER RC;
CCHAR Shift;
Shift = ShiftCount % 64;
RC.QuadPart = LargeInteger.QuadPart << Shift;
return RC;
}
/*
* @implemented
*/
LARGE_INTEGER
NTAPI
RtlLargeIntegerShiftRight (
LARGE_INTEGER LargeInteger,
CCHAR ShiftCount
)
{
LARGE_INTEGER RC;
CCHAR Shift;
Shift = ShiftCount % 64;
RC.QuadPart = LargeInteger.QuadPart >> Shift;
return RC;
}
/*
* @implemented
*/
LARGE_INTEGER
NTAPI
RtlLargeIntegerSubtract (
LARGE_INTEGER Minuend,
LARGE_INTEGER Subtrahend
)
{
LARGE_INTEGER RC;
RC.QuadPart = Minuend.QuadPart - Subtrahend.QuadPart;
return RC;
}
/* EOF */