1 /* COPYRIGHT: See COPYING in the top level directory
2 * PROJECT: ReactOS system libraries
3 * FILE: lib/rtl/largeint.c
4 * PURPOSE: Large integer operations
8 /* INCLUDES *****************************************************************/
15 /* FUNCTIONS *****************************************************************/
22 RtlConvertLongToLargeInteger (
28 RC
.QuadPart
= SignedInteger
;
38 RtlConvertUlongToLargeInteger (
44 RC
.QuadPart
= UnsignedInteger
;
54 RtlEnlargedIntegerMultiply (
61 RC
.QuadPart
= (LONGLONG
) Multiplicand
* Multiplier
;
71 RtlEnlargedUnsignedDivide (
72 ULARGE_INTEGER Dividend
,
78 *Remainder
= (ULONG
)(Dividend
.QuadPart
% Divisor
);
80 return (ULONG
)(Dividend
.QuadPart
/ Divisor
);
88 RtlEnlargedUnsignedMultiply (
95 RC
.QuadPart
= (ULONGLONG
) Multiplicand
* Multiplier
;
105 RtlExtendedIntegerMultiply (
106 LARGE_INTEGER Multiplicand
,
112 RC
.QuadPart
= Multiplicand
.QuadPart
* Multiplier
;
122 RtlExtendedLargeIntegerDivide (
123 LARGE_INTEGER Dividend
,
131 *Remainder
= (ULONG
)(Dividend
.QuadPart
% Divisor
);
133 RC
.QuadPart
= Dividend
.QuadPart
/ Divisor
;
139 /******************************************************************************
140 * RtlExtendedMagicDivide
142 * Allows replacing a division by a longlong constant with a multiplication by
143 * the inverse constant.
146 * (Dividend * MagicDivisor) >> (64 + ShiftCount)
149 * If the divisor of a division is constant, the constants MagicDivisor and
150 * shift must be chosen such that
151 * MagicDivisor = 2^(64 + ShiftCount) / Divisor.
153 * Then we have RtlExtendedMagicDivide(Dividend,MagicDivisor,ShiftCount) ==
154 * Dividend * MagicDivisor / 2^(64 + ShiftCount) == Dividend / Divisor.
156 * The Parameter MagicDivisor although defined as LONGLONG is used as
160 #define LOWER_32(A) ((A) & 0xffffffff)
161 #define UPPER_32(A) ((A) >> 32)
167 RtlExtendedMagicDivide (LARGE_INTEGER Dividend
,
168 LARGE_INTEGER MagicDivisor
,
171 ULONGLONG dividend_high
;
172 ULONGLONG dividend_low
;
173 ULONGLONG inverse_divisor_high
;
174 ULONGLONG inverse_divisor_low
;
177 LARGE_INTEGER result
;
180 if (Dividend
.QuadPart
< 0)
182 dividend_high
= UPPER_32((ULONGLONG
) -Dividend
.QuadPart
);
183 dividend_low
= LOWER_32((ULONGLONG
) -Dividend
.QuadPart
);
188 dividend_high
= UPPER_32((ULONGLONG
) Dividend
.QuadPart
);
189 dividend_low
= LOWER_32((ULONGLONG
) Dividend
.QuadPart
);
192 inverse_divisor_high
= UPPER_32((ULONGLONG
) MagicDivisor
.QuadPart
);
193 inverse_divisor_low
= LOWER_32((ULONGLONG
) MagicDivisor
.QuadPart
);
195 ah_bl
= dividend_high
* inverse_divisor_low
;
196 al_bh
= dividend_low
* inverse_divisor_high
;
199 (LONGLONG
) ((dividend_high
* inverse_divisor_high
+
202 UPPER_32(LOWER_32(ah_bl
) + LOWER_32(al_bh
) +
203 UPPER_32(dividend_low
* inverse_divisor_low
))) >> ShiftCount
);
206 result
.QuadPart
= -result
.QuadPart
;
219 LARGE_INTEGER Addend1
,
220 LARGE_INTEGER Addend2
225 RC
.QuadPart
= Addend1
.QuadPart
+ Addend2
.QuadPart
;
235 RtlLargeIntegerArithmeticShift (
236 LARGE_INTEGER LargeInteger
,
243 Shift
= ShiftCount
% 64;
247 RC
.QuadPart
= LargeInteger
.QuadPart
>> Shift
;
251 /* copy the sign bit */
252 RC
.u
.HighPart
= (LargeInteger
.u
.HighPart
& 0x80000000);
253 RC
.u
.LowPart
= LargeInteger
.u
.HighPart
>> Shift
;
264 RtlLargeIntegerDivide (
265 LARGE_INTEGER Dividend
,
266 LARGE_INTEGER Divisor
,
267 PLARGE_INTEGER Remainder
273 Remainder
->QuadPart
= Dividend
.QuadPart
% Divisor
.QuadPart
;
275 RC
.QuadPart
= Dividend
.QuadPart
/ Divisor
.QuadPart
;
285 RtlLargeIntegerNegate (
286 LARGE_INTEGER Subtrahend
291 RC
.QuadPart
= - Subtrahend
.QuadPart
;
301 RtlLargeIntegerShiftLeft (
302 LARGE_INTEGER LargeInteger
,
309 Shift
= ShiftCount
% 64;
310 RC
.QuadPart
= LargeInteger
.QuadPart
<< Shift
;
320 RtlLargeIntegerShiftRight (
321 LARGE_INTEGER LargeInteger
,
328 Shift
= ShiftCount
% 64;
329 RC
.QuadPart
= LargeInteger
.QuadPart
>> Shift
;
339 RtlLargeIntegerSubtract (
340 LARGE_INTEGER Minuend
,
341 LARGE_INTEGER Subtrahend
346 RC
.QuadPart
= Minuend
.QuadPart
- Subtrahend
.QuadPart
;