2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS system libraries
4 * FILE: lib/rtl/largeint.c
5 * PURPOSE: Large integer operations
9 /* INCLUDES *****************************************************************/
16 /* FUNCTIONS *****************************************************************/
18 /* HACK: ld is too stupid to understand that we need the functions
19 when we export them, so we force it to be linked this way. */
21 #undef RtlUshortByteSwap
22 USHORT FASTCALL
RtlUshortByteSwap(USHORT Source
);
23 PVOID Dummy
= RtlUshortByteSwap
;
31 RtlConvertLongToLargeInteger (
37 RC
.QuadPart
= SignedInteger
;
47 RtlConvertUlongToLargeInteger (
53 RC
.QuadPart
= UnsignedInteger
;
63 RtlEnlargedIntegerMultiply (
70 RC
.QuadPart
= (LONGLONG
) Multiplicand
* Multiplier
;
80 RtlEnlargedUnsignedDivide (
81 ULARGE_INTEGER Dividend
,
87 *Remainder
= (ULONG
)(Dividend
.QuadPart
% Divisor
);
89 return (ULONG
)(Dividend
.QuadPart
/ Divisor
);
97 RtlEnlargedUnsignedMultiply (
104 RC
.QuadPart
= (ULONGLONG
) Multiplicand
* Multiplier
;
114 RtlExtendedIntegerMultiply (
115 LARGE_INTEGER Multiplicand
,
121 RC
.QuadPart
= Multiplicand
.QuadPart
* Multiplier
;
131 RtlExtendedLargeIntegerDivide (
132 LARGE_INTEGER Dividend
,
140 *Remainder
= (ULONG
)(Dividend
.QuadPart
% Divisor
);
142 RC
.QuadPart
= Dividend
.QuadPart
/ Divisor
;
148 /******************************************************************************
149 * RtlExtendedMagicDivide
151 * Allows replacing a division by a longlong constant with a multiplication by
152 * the inverse constant.
155 * (Dividend * MagicDivisor) >> (64 + ShiftCount)
158 * If the divisor of a division is constant, the constants MagicDivisor and
159 * shift must be chosen such that
160 * MagicDivisor = 2^(64 + ShiftCount) / Divisor.
162 * Then we have RtlExtendedMagicDivide(Dividend,MagicDivisor,ShiftCount) ==
163 * Dividend * MagicDivisor / 2^(64 + ShiftCount) == Dividend / Divisor.
165 * The Parameter MagicDivisor although defined as LONGLONG is used as
169 #define LOWER_32(A) ((A) & 0xffffffff)
170 #define UPPER_32(A) ((A) >> 32)
176 RtlExtendedMagicDivide (LARGE_INTEGER Dividend
,
177 LARGE_INTEGER MagicDivisor
,
180 ULONGLONG dividend_high
;
181 ULONGLONG dividend_low
;
182 ULONGLONG inverse_divisor_high
;
183 ULONGLONG inverse_divisor_low
;
186 LARGE_INTEGER result
;
189 if (Dividend
.QuadPart
< 0)
191 dividend_high
= UPPER_32((ULONGLONG
) -Dividend
.QuadPart
);
192 dividend_low
= LOWER_32((ULONGLONG
) -Dividend
.QuadPart
);
197 dividend_high
= UPPER_32((ULONGLONG
) Dividend
.QuadPart
);
198 dividend_low
= LOWER_32((ULONGLONG
) Dividend
.QuadPart
);
201 inverse_divisor_high
= UPPER_32((ULONGLONG
) MagicDivisor
.QuadPart
);
202 inverse_divisor_low
= LOWER_32((ULONGLONG
) MagicDivisor
.QuadPart
);
204 ah_bl
= dividend_high
* inverse_divisor_low
;
205 al_bh
= dividend_low
* inverse_divisor_high
;
208 (LONGLONG
) ((dividend_high
* inverse_divisor_high
+
211 UPPER_32(LOWER_32(ah_bl
) + LOWER_32(al_bh
) +
212 UPPER_32(dividend_low
* inverse_divisor_low
))) >> ShiftCount
);
215 result
.QuadPart
= -result
.QuadPart
;
228 LARGE_INTEGER Addend1
,
229 LARGE_INTEGER Addend2
234 RC
.QuadPart
= Addend1
.QuadPart
+ Addend2
.QuadPart
;
244 RtlLargeIntegerArithmeticShift (
245 LARGE_INTEGER LargeInteger
,
252 Shift
= ShiftCount
% 64;
256 RC
.QuadPart
= LargeInteger
.QuadPart
>> Shift
;
260 /* copy the sign bit */
261 RC
.u
.HighPart
= (LargeInteger
.u
.HighPart
& 0x80000000);
262 RC
.u
.LowPart
= LargeInteger
.u
.HighPart
>> Shift
;
273 RtlLargeIntegerDivide (
274 LARGE_INTEGER Dividend
,
275 LARGE_INTEGER Divisor
,
276 PLARGE_INTEGER Remainder
282 Remainder
->QuadPart
= Dividend
.QuadPart
% Divisor
.QuadPart
;
284 RC
.QuadPart
= Dividend
.QuadPart
/ Divisor
.QuadPart
;
294 RtlLargeIntegerNegate (
295 LARGE_INTEGER Subtrahend
300 RC
.QuadPart
= - Subtrahend
.QuadPart
;
310 RtlLargeIntegerShiftLeft (
311 LARGE_INTEGER LargeInteger
,
318 Shift
= ShiftCount
% 64;
319 RC
.QuadPart
= LargeInteger
.QuadPart
<< Shift
;
329 RtlLargeIntegerShiftRight (
330 LARGE_INTEGER LargeInteger
,
337 Shift
= ShiftCount
% 64;
338 RC
.QuadPart
= LargeInteger
.QuadPart
>> Shift
;
348 RtlLargeIntegerSubtract (
349 LARGE_INTEGER Minuend
,
350 LARGE_INTEGER Subtrahend
355 RC
.QuadPart
= Minuend
.QuadPart
- Subtrahend
.QuadPart
;