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 *****************************************************************/
10 #define NO_RTL_INLINES
16 /* FUNCTIONS *****************************************************************/
23 RtlConvertLongToLargeInteger (
29 RC
.QuadPart
= SignedInteger
;
39 RtlConvertUlongToLargeInteger (
45 RC
.QuadPart
= UnsignedInteger
;
55 RtlEnlargedIntegerMultiply (
62 RC
.QuadPart
= (LONGLONG
) Multiplicand
* Multiplier
;
72 RtlEnlargedUnsignedDivide (
73 ULARGE_INTEGER Dividend
,
79 *Remainder
= Dividend
.QuadPart
% Divisor
;
81 return (ULONG
)(Dividend
.QuadPart
/ Divisor
);
89 RtlEnlargedUnsignedMultiply (
96 RC
.QuadPart
= (ULONGLONG
) Multiplicand
* Multiplier
;
106 RtlExtendedIntegerMultiply (
107 LARGE_INTEGER Multiplicand
,
113 RC
.QuadPart
= Multiplicand
.QuadPart
* Multiplier
;
123 RtlExtendedLargeIntegerDivide (
124 LARGE_INTEGER Dividend
,
132 *Remainder
= Dividend
.QuadPart
% Divisor
;
134 RC
.QuadPart
= Dividend
.QuadPart
/ Divisor
;
140 /******************************************************************************
141 * RtlExtendedMagicDivide
143 * Allows replacing a division by a longlong constant with a multiplication by
144 * the inverse constant.
147 * (Dividend * MagicDivisor) >> (64 + ShiftCount)
150 * If the divisor of a division is constant, the constants MagicDivisor and
151 * shift must be chosen such that
152 * MagicDivisor = 2^(64 + ShiftCount) / Divisor.
154 * Then we have RtlExtendedMagicDivide(Dividend,MagicDivisor,ShiftCount) ==
155 * Dividend * MagicDivisor / 2^(64 + ShiftCount) == Dividend / Divisor.
157 * The Parameter MagicDivisor although defined as LONGLONG is used as
161 #define LOWER_32(A) ((A) & 0xffffffff)
162 #define UPPER_32(A) ((A) >> 32)
168 RtlExtendedMagicDivide (LARGE_INTEGER Dividend
,
169 LARGE_INTEGER MagicDivisor
,
172 ULONGLONG dividend_high
;
173 ULONGLONG dividend_low
;
174 ULONGLONG inverse_divisor_high
;
175 ULONGLONG inverse_divisor_low
;
178 LARGE_INTEGER result
;
181 if (Dividend
.QuadPart
< 0)
183 dividend_high
= UPPER_32((ULONGLONG
) -Dividend
.QuadPart
);
184 dividend_low
= LOWER_32((ULONGLONG
) -Dividend
.QuadPart
);
189 dividend_high
= UPPER_32((ULONGLONG
) Dividend
.QuadPart
);
190 dividend_low
= LOWER_32((ULONGLONG
) Dividend
.QuadPart
);
193 inverse_divisor_high
= UPPER_32((ULONGLONG
) MagicDivisor
.QuadPart
);
194 inverse_divisor_low
= LOWER_32((ULONGLONG
) MagicDivisor
.QuadPart
);
196 ah_bl
= dividend_high
* inverse_divisor_low
;
197 al_bh
= dividend_low
* inverse_divisor_high
;
200 (LONGLONG
) ((dividend_high
* inverse_divisor_high
+
203 UPPER_32(LOWER_32(ah_bl
) + LOWER_32(al_bh
) +
204 UPPER_32(dividend_low
* inverse_divisor_low
))) >> ShiftCount
);
207 result
.QuadPart
= -result
.QuadPart
;
220 LARGE_INTEGER Addend1
,
221 LARGE_INTEGER Addend2
226 RC
.QuadPart
= Addend1
.QuadPart
+ Addend2
.QuadPart
;
236 RtlLargeIntegerArithmeticShift (
237 LARGE_INTEGER LargeInteger
,
244 Shift
= ShiftCount
% 64;
248 RC
.QuadPart
= LargeInteger
.QuadPart
>> Shift
;
252 /* copy the sign bit */
253 RC
.u
.HighPart
= (LargeInteger
.u
.HighPart
& 0x80000000);
254 RC
.u
.LowPart
= LargeInteger
.u
.HighPart
>> Shift
;
265 RtlLargeIntegerDivide (
266 LARGE_INTEGER Dividend
,
267 LARGE_INTEGER Divisor
,
268 PLARGE_INTEGER Remainder
274 Remainder
->QuadPart
= Dividend
.QuadPart
% Divisor
.QuadPart
;
276 RC
.QuadPart
= Dividend
.QuadPart
/ Divisor
.QuadPart
;
286 RtlLargeIntegerNegate (
287 LARGE_INTEGER Subtrahend
292 RC
.QuadPart
= - Subtrahend
.QuadPart
;
302 RtlLargeIntegerShiftLeft (
303 LARGE_INTEGER LargeInteger
,
310 Shift
= ShiftCount
% 64;
311 RC
.QuadPart
= LargeInteger
.QuadPart
<< Shift
;
321 RtlLargeIntegerShiftRight (
322 LARGE_INTEGER LargeInteger
,
329 Shift
= ShiftCount
% 64;
330 RC
.QuadPart
= LargeInteger
.QuadPart
>> Shift
;
340 RtlLargeIntegerSubtract (
341 LARGE_INTEGER Minuend
,
342 LARGE_INTEGER Subtrahend
347 RC
.QuadPart
= Minuend
.QuadPart
- Subtrahend
.QuadPart
;