1 /* $Id: largeint.c,v 1.15 2003/07/11 01:23:15 royce Exp $
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
;