reactos/reactos/lib/rtl/largeint.c
Filip Navara d2bc064abf #include "rtl.h" -> #include <rtl.h>
svn path=/trunk/; revision=16732
2005-07-26 08:39:07 +00:00

356 lines
6.1 KiB
C

/* $Id$
*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel
* FILE: lib/rtl/largeint.c
* PURPOSE: Large integer operations
* UPDATE HISTORY:
* Created 22/05/98
* 08/30/98 RJJ Implemented several functions
*/
/* INCLUDES *****************************************************************/
#include <rtl.h>
#define NDEBUG
#include <debug.h>
/* FUNCTIONS *****************************************************************/
/*
* @implemented
*/
LARGE_INTEGER
STDCALL
RtlConvertLongToLargeInteger (
LONG SignedInteger
)
{
LARGE_INTEGER RC;
RC.QuadPart = SignedInteger;
return RC;
}
/*
* @implemented
*/
LARGE_INTEGER
STDCALL
RtlConvertUlongToLargeInteger (
ULONG UnsignedInteger
)
{
LARGE_INTEGER RC;
RC.QuadPart = UnsignedInteger;
return RC;
}
/*
* @implemented
*/
LARGE_INTEGER
STDCALL
RtlEnlargedIntegerMultiply (
LONG Multiplicand,
LONG Multiplier
)
{
LARGE_INTEGER RC;
RC.QuadPart = (LONGLONG) Multiplicand * Multiplier;
return RC;
}
/*
* @implemented
*/
ULONG
STDCALL
RtlEnlargedUnsignedDivide (
ULARGE_INTEGER Dividend,
ULONG Divisor,
PULONG Remainder
)
{
if (Remainder)
*Remainder = Dividend.QuadPart % Divisor;
return (ULONG)(Dividend.QuadPart / Divisor);
}
/*
* @implemented
*/
LARGE_INTEGER
STDCALL
RtlEnlargedUnsignedMultiply (
ULONG Multiplicand,
ULONG Multiplier
)
{
LARGE_INTEGER RC;
RC.QuadPart = (ULONGLONG) Multiplicand * Multiplier;
return RC;
}
/*
* @implemented
*/
LARGE_INTEGER
STDCALL
RtlExtendedIntegerMultiply (
LARGE_INTEGER Multiplicand,
LONG Multiplier
)
{
LARGE_INTEGER RC;
RC.QuadPart = Multiplicand.QuadPart * Multiplier;
return RC;
}
/*
* @implemented
*/
LARGE_INTEGER
STDCALL
RtlExtendedLargeIntegerDivide (
LARGE_INTEGER Dividend,
ULONG Divisor,
PULONG Remainder
)
{
LARGE_INTEGER RC;
if (Remainder)
*Remainder = 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 STDCALL
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
STDCALL
RtlLargeIntegerAdd (
LARGE_INTEGER Addend1,
LARGE_INTEGER Addend2
)
{
LARGE_INTEGER RC;
RC.QuadPart = Addend1.QuadPart + Addend2.QuadPart;
return RC;
}
/*
* @implemented
*/
LARGE_INTEGER
STDCALL
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
STDCALL
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
STDCALL
RtlLargeIntegerNegate (
LARGE_INTEGER Subtrahend
)
{
LARGE_INTEGER RC;
RC.QuadPart = - Subtrahend.QuadPart;
return RC;
}
/*
* @implemented
*/
LARGE_INTEGER
STDCALL
RtlLargeIntegerShiftLeft (
LARGE_INTEGER LargeInteger,
CCHAR ShiftCount
)
{
LARGE_INTEGER RC;
CCHAR Shift;
Shift = ShiftCount % 64;
RC.QuadPart = LargeInteger.QuadPart << Shift;
return RC;
}
/*
* @implemented
*/
LARGE_INTEGER
STDCALL
RtlLargeIntegerShiftRight (
LARGE_INTEGER LargeInteger,
CCHAR ShiftCount
)
{
LARGE_INTEGER RC;
CCHAR Shift;
Shift = ShiftCount % 64;
RC.QuadPart = LargeInteger.QuadPart >> Shift;
return RC;
}
/*
* @implemented
*/
LARGE_INTEGER
STDCALL
RtlLargeIntegerSubtract (
LARGE_INTEGER Minuend,
LARGE_INTEGER Subtrahend
)
{
LARGE_INTEGER RC;
RC.QuadPart = Minuend.QuadPart - Subtrahend.QuadPart;
return RC;
}
/* EOF */