3 * COPYRIGHT: See COPYING in the top level directory
4 * PROJECT: ReactOS kernel
5 * FILE: kernel/rtl/largeint.c
6 * PURPOSE: Large integer operations
9 * 08/30/98 RJJ Implemented several functions
12 /* INCLUDES *****************************************************************/
14 #include <ddk/ntddk.h>
17 #include <internal/debug.h>
20 /* FUNCTIONS *****************************************************************/
27 RtlConvertLongToLargeInteger (
33 RC.QuadPart = SignedInteger;
43 RtlConvertUlongToLargeInteger (
49 RC.QuadPart = UnsignedInteger;
59 RtlEnlargedIntegerMultiply (
66 RC.QuadPart = (LONGLONG) Multiplicand * Multiplier;
76 RtlEnlargedUnsignedDivide (
77 ULARGE_INTEGER Dividend,
83 *Remainder = Dividend.QuadPart % Divisor;
85 return (ULONG)(Dividend.QuadPart / Divisor);
93 RtlEnlargedUnsignedMultiply (
100 RC.QuadPart = (ULONGLONG) Multiplicand * Multiplier;
110 RtlExtendedIntegerMultiply (
111 LARGE_INTEGER Multiplicand,
117 RC.QuadPart = Multiplicand.QuadPart * Multiplier;
127 RtlExtendedLargeIntegerDivide (
128 LARGE_INTEGER Dividend,
136 *Remainder = Dividend.QuadPart % Divisor;
138 RC.QuadPart = Dividend.QuadPart / Divisor;
144 /******************************************************************************
145 * RtlExtendedMagicDivide
147 * Allows replacing a division by a longlong constant with a multiplication by
148 * the inverse constant.
151 * (Dividend * MagicDivisor) >> (64 + ShiftCount)
154 * If the divisor of a division is constant, the constants MagicDivisor and
155 * shift must be chosen such that
156 * MagicDivisor = 2^(64 + ShiftCount) / Divisor.
158 * Then we have RtlExtendedMagicDivide(Dividend,MagicDivisor,ShiftCount) ==
159 * Dividend * MagicDivisor / 2^(64 + ShiftCount) == Dividend / Divisor.
161 * The Parameter MagicDivisor although defined as LONGLONG is used as
165 #define LOWER_32(A) ((A) & 0xffffffff)
166 #define UPPER_32(A) ((A) >> 32)
171 LARGE_INTEGER STDCALL
172 RtlExtendedMagicDivide (LARGE_INTEGER Dividend,
173 LARGE_INTEGER MagicDivisor,
176 ULONGLONG dividend_high;
177 ULONGLONG dividend_low;
178 ULONGLONG inverse_divisor_high;
179 ULONGLONG inverse_divisor_low;
182 LARGE_INTEGER result;
185 if (Dividend.QuadPart < 0)
187 dividend_high = UPPER_32((ULONGLONG) -Dividend.QuadPart);
188 dividend_low = LOWER_32((ULONGLONG) -Dividend.QuadPart);
193 dividend_high = UPPER_32((ULONGLONG) Dividend.QuadPart);
194 dividend_low = LOWER_32((ULONGLONG) Dividend.QuadPart);
197 inverse_divisor_high = UPPER_32((ULONGLONG) MagicDivisor.QuadPart);
198 inverse_divisor_low = LOWER_32((ULONGLONG) MagicDivisor.QuadPart);
200 ah_bl = dividend_high * inverse_divisor_low;
201 al_bh = dividend_low * inverse_divisor_high;
204 (LONGLONG) ((dividend_high * inverse_divisor_high +
207 UPPER_32(LOWER_32(ah_bl) + LOWER_32(al_bh) +
208 UPPER_32(dividend_low * inverse_divisor_low))) >> ShiftCount);
211 result.QuadPart = -result.QuadPart;
224 LARGE_INTEGER Addend1,
225 LARGE_INTEGER Addend2
230 RC.QuadPart = Addend1.QuadPart + Addend2.QuadPart;
240 RtlLargeIntegerArithmeticShift (
241 LARGE_INTEGER LargeInteger,
248 Shift = ShiftCount % 64;
252 RC.QuadPart = LargeInteger.QuadPart >> Shift;
256 /* copy the sign bit */
257 RC.u.HighPart |= (LargeInteger.u.HighPart & 0x80000000);
258 RC.u.LowPart = LargeInteger.u.HighPart >> Shift;
269 RtlLargeIntegerDivide (
270 LARGE_INTEGER Dividend,
271 LARGE_INTEGER Divisor,
272 PLARGE_INTEGER Remainder
278 Remainder->QuadPart = Dividend.QuadPart % Divisor.QuadPart;
280 RC.QuadPart = Dividend.QuadPart / Divisor.QuadPart;
290 RtlLargeIntegerNegate (
291 LARGE_INTEGER Subtrahend
296 RC.QuadPart = - Subtrahend.QuadPart;
306 RtlLargeIntegerShiftLeft (
307 LARGE_INTEGER LargeInteger,
314 Shift = ShiftCount % 64;
315 RC.QuadPart = LargeInteger.QuadPart << Shift;
325 RtlLargeIntegerShiftRight (
326 LARGE_INTEGER LargeInteger,
333 Shift = ShiftCount % 64;
334 RC.QuadPart = LargeInteger.QuadPart >> ShiftCount;
344 RtlLargeIntegerSubtract (
345 LARGE_INTEGER Minuend,
346 LARGE_INTEGER Subtrahend
351 RC.QuadPart = Minuend.QuadPart - Subtrahend.QuadPart;