Something went wrong. Try again.
Reactos
Something went wrong. Try again.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361/* * 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 RtlUshortByteSwapUSHORT FASTCALL RtlUshortByteSwap(USHORT Source);PVOID Dummy = RtlUshortByteSwap;#endif
/* * @implemented */LARGE_INTEGERNTAPIRtlConvertLongToLargeInteger ( LONG SignedInteger){ LARGE_INTEGER RC;
RC.QuadPart = SignedInteger;
return RC;}
/* * @implemented */LARGE_INTEGERNTAPIRtlConvertUlongToLargeInteger ( ULONG UnsignedInteger){ LARGE_INTEGER RC;
RC.QuadPart = UnsignedInteger;
return RC;}
/* * @implemented */LARGE_INTEGERNTAPIRtlEnlargedIntegerMultiply ( LONG Multiplicand, LONG Multiplier){ LARGE_INTEGER RC;
RC.QuadPart = (LONGLONG) Multiplicand * Multiplier;
return RC;}
/* * @implemented */ULONGNTAPIRtlEnlargedUnsignedDivide ( ULARGE_INTEGER Dividend, ULONG Divisor, PULONG Remainder){ if (Remainder) *Remainder = (ULONG)(Dividend.QuadPart % Divisor);
return (ULONG)(Dividend.QuadPart / Divisor);}
/* * @implemented */LARGE_INTEGERNTAPIRtlEnlargedUnsignedMultiply ( ULONG Multiplicand, ULONG Multiplier){ LARGE_INTEGER RC;
RC.QuadPart = (ULONGLONG) Multiplicand * Multiplier;
return RC;}
/* * @implemented */LARGE_INTEGERNTAPIRtlExtendedIntegerMultiply ( LARGE_INTEGER Multiplicand, LONG Multiplier){ LARGE_INTEGER RC;
RC.QuadPart = Multiplicand.QuadPart * Multiplier;
return RC;}
/* * @implemented */LARGE_INTEGERNTAPIRtlExtendedLargeIntegerDivide ( 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 NTAPIRtlExtendedMagicDivide (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_INTEGERNTAPIRtlLargeIntegerAdd ( LARGE_INTEGER Addend1, LARGE_INTEGER Addend2){ LARGE_INTEGER RC;
RC.QuadPart = Addend1.QuadPart + Addend2.QuadPart;
return RC;}
/* * @implemented */LARGE_INTEGERNTAPIRtlLargeIntegerArithmeticShift ( 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_INTEGERNTAPIRtlLargeIntegerDivide ( 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_INTEGERNTAPIRtlLargeIntegerNegate ( LARGE_INTEGER Subtrahend){ LARGE_INTEGER RC;
RC.QuadPart = - Subtrahend.QuadPart;
return RC;}
/* * @implemented */LARGE_INTEGERNTAPIRtlLargeIntegerShiftLeft ( LARGE_INTEGER LargeInteger, CCHAR ShiftCount){ LARGE_INTEGER RC; CCHAR Shift;
Shift = ShiftCount % 64; RC.QuadPart = LargeInteger.QuadPart << Shift;
return RC;}
/* * @implemented */LARGE_INTEGERNTAPIRtlLargeIntegerShiftRight ( LARGE_INTEGER LargeInteger, CCHAR ShiftCount){ LARGE_INTEGER RC; CCHAR Shift;
Shift = ShiftCount % 64; RC.QuadPart = LargeInteger.QuadPart >> Shift;
return RC;}
/* * @implemented */LARGE_INTEGERNTAPIRtlLargeIntegerSubtract ( LARGE_INTEGER Minuend, LARGE_INTEGER Subtrahend){ LARGE_INTEGER RC;
RC.QuadPart = Minuend.QuadPart - Subtrahend.QuadPart;
return RC;}
/* EOF */