Reactos
1/*
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
6 * PROGRAMMERS:
7 */
8
9/* INCLUDES *****************************************************************/
10
11#include <rtl.h>
12
13#define NDEBUG
14#include <debug.h>
15
16/* FUNCTIONS *****************************************************************/
17
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. */
20#ifdef __GNUC__
21#undef RtlUshortByteSwap
22USHORT FASTCALL RtlUshortByteSwap(USHORT Source);
23PVOID Dummy = RtlUshortByteSwap;
24#endif
25
26/*
27 * @implemented
28 */
29LARGE_INTEGER
30NTAPI
31RtlConvertLongToLargeInteger (
32 LONG SignedInteger
33)
34{
35 LARGE_INTEGER RC;
36
37 RC.QuadPart = SignedInteger;
38
39 return RC;
40}
41
42/*
43 * @implemented
44 */
45LARGE_INTEGER
46NTAPI
47RtlConvertUlongToLargeInteger (
48 ULONG UnsignedInteger
49)
50{
51 LARGE_INTEGER RC;
52
53 RC.QuadPart = UnsignedInteger;
54
55 return RC;
56}
57
58/*
59 * @implemented
60 */
61LARGE_INTEGER
62NTAPI
63RtlEnlargedIntegerMultiply (
64 LONG Multiplicand,
65 LONG Multiplier
66)
67{
68 LARGE_INTEGER RC;
69
70 RC.QuadPart = (LONGLONG) Multiplicand * Multiplier;
71
72 return RC;
73}
74
75/*
76 * @implemented
77 */
78ULONG
79NTAPI
80RtlEnlargedUnsignedDivide (
81 ULARGE_INTEGER Dividend,
82 ULONG Divisor,
83 PULONG Remainder
84)
85{
86 if (Remainder)
87 *Remainder = (ULONG)(Dividend.QuadPart % Divisor);
88
89 return (ULONG)(Dividend.QuadPart / Divisor);
90}
91
92/*
93 * @implemented
94 */
95LARGE_INTEGER
96NTAPI
97RtlEnlargedUnsignedMultiply (
98 ULONG Multiplicand,
99 ULONG Multiplier
100)
101{
102 LARGE_INTEGER RC;
103
104 RC.QuadPart = (ULONGLONG) Multiplicand * Multiplier;
105
106 return RC;
107}
108
109/*
110 * @implemented
111 */
112LARGE_INTEGER
113NTAPI
114RtlExtendedIntegerMultiply (
115 LARGE_INTEGER Multiplicand,
116 LONG Multiplier
117)
118{
119 LARGE_INTEGER RC;
120
121 RC.QuadPart = Multiplicand.QuadPart * Multiplier;
122
123 return RC;
124}
125
126/*
127 * @implemented
128 */
129LARGE_INTEGER
130NTAPI
131RtlExtendedLargeIntegerDivide (
132 LARGE_INTEGER Dividend,
133 ULONG Divisor,
134 PULONG Remainder
135)
136{
137 LARGE_INTEGER RC;
138
139 if (Remainder)
140 *Remainder = (ULONG)(Dividend.QuadPart % Divisor);
141
142 RC.QuadPart = Dividend.QuadPart / Divisor;
143
144 return RC;
145}
146
147
148/******************************************************************************
149 * RtlExtendedMagicDivide
150 *
151 * Allows replacing a division by a longlong constant with a multiplication by
152 * the inverse constant.
153 *
154 * RETURNS
155 * (Dividend * MagicDivisor) >> (64 + ShiftCount)
156 *
157 * NOTES
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.
161 *
162 * Then we have RtlExtendedMagicDivide(Dividend,MagicDivisor,ShiftCount) ==
163 * Dividend * MagicDivisor / 2^(64 + ShiftCount) == Dividend / Divisor.
164 *
165 * The Parameter MagicDivisor although defined as LONGLONG is used as
166 * ULONGLONG.
167 */
168
169#define LOWER_32(A) ((A) & 0xffffffff)
170#define UPPER_32(A) ((A) >> 32)
171
172/*
173 * @implemented
174 */
175LARGE_INTEGER NTAPI
176RtlExtendedMagicDivide (LARGE_INTEGER Dividend,
177 LARGE_INTEGER MagicDivisor,
178 CCHAR ShiftCount)
179{
180 ULONGLONG dividend_high;
181 ULONGLONG dividend_low;
182 ULONGLONG inverse_divisor_high;
183 ULONGLONG inverse_divisor_low;
184 ULONGLONG ah_bl;
185 ULONGLONG al_bh;
186 LARGE_INTEGER result;
187 BOOLEAN positive;
188
189 if (Dividend.QuadPart < 0)
190 {
191 dividend_high = UPPER_32((ULONGLONG) -Dividend.QuadPart);
192 dividend_low = LOWER_32((ULONGLONG) -Dividend.QuadPart);
193 positive = FALSE;
194 }
195 else
196 {
197 dividend_high = UPPER_32((ULONGLONG) Dividend.QuadPart);
198 dividend_low = LOWER_32((ULONGLONG) Dividend.QuadPart);
199 positive = TRUE;
200 }
201 inverse_divisor_high = UPPER_32((ULONGLONG) MagicDivisor.QuadPart);
202 inverse_divisor_low = LOWER_32((ULONGLONG) MagicDivisor.QuadPart);
203
204 ah_bl = dividend_high * inverse_divisor_low;
205 al_bh = dividend_low * inverse_divisor_high;
206
207 result.QuadPart =
208 (LONGLONG) ((dividend_high * inverse_divisor_high +
209 UPPER_32(ah_bl) +
210 UPPER_32(al_bh) +
211 UPPER_32(LOWER_32(ah_bl) + LOWER_32(al_bh) +
212 UPPER_32(dividend_low * inverse_divisor_low))) >> ShiftCount);
213 if (!positive)
214 {
215 result.QuadPart = -result.QuadPart;
216 }
217
218 return result;
219}
220
221
222/*
223 * @implemented
224 */
225LARGE_INTEGER
226NTAPI
227RtlLargeIntegerAdd (
228 LARGE_INTEGER Addend1,
229 LARGE_INTEGER Addend2
230)
231{
232 LARGE_INTEGER RC;
233
234 RC.QuadPart = Addend1.QuadPart + Addend2.QuadPart;
235
236 return RC;
237}
238
239/*
240 * @implemented
241 */
242LARGE_INTEGER
243NTAPI
244RtlLargeIntegerArithmeticShift (
245 LARGE_INTEGER LargeInteger,
246 CCHAR ShiftCount
247)
248{
249 LARGE_INTEGER RC;
250 CHAR Shift;
251
252 Shift = ShiftCount % 64;
253
254 if (Shift < 32)
255 {
256 RC.QuadPart = LargeInteger.QuadPart >> Shift;
257 }
258 else
259 {
260 /* copy the sign bit */
261 RC.u.HighPart = (LargeInteger.u.HighPart & 0x80000000);
262 RC.u.LowPart = LargeInteger.u.HighPart >> Shift;
263 }
264
265 return RC;
266}
267
268/*
269 * @implemented
270 */
271LARGE_INTEGER
272NTAPI
273RtlLargeIntegerDivide (
274 LARGE_INTEGER Dividend,
275 LARGE_INTEGER Divisor,
276 PLARGE_INTEGER Remainder
277)
278{
279 LARGE_INTEGER RC;
280
281 if (Remainder)
282 Remainder->QuadPart = Dividend.QuadPart % Divisor.QuadPart;
283
284 RC.QuadPart = Dividend.QuadPart / Divisor.QuadPart;
285
286 return RC;
287}
288
289/*
290 * @implemented
291 */
292LARGE_INTEGER
293NTAPI
294RtlLargeIntegerNegate (
295 LARGE_INTEGER Subtrahend
296)
297{
298 LARGE_INTEGER RC;
299
300 RC.QuadPart = - Subtrahend.QuadPart;
301
302 return RC;
303}
304
305/*
306 * @implemented
307 */
308LARGE_INTEGER
309NTAPI
310RtlLargeIntegerShiftLeft (
311 LARGE_INTEGER LargeInteger,
312 CCHAR ShiftCount
313)
314{
315 LARGE_INTEGER RC;
316 CCHAR Shift;
317
318 Shift = ShiftCount % 64;
319 RC.QuadPart = LargeInteger.QuadPart << Shift;
320
321 return RC;
322}
323
324/*
325 * @implemented
326 */
327LARGE_INTEGER
328NTAPI
329RtlLargeIntegerShiftRight (
330 LARGE_INTEGER LargeInteger,
331 CCHAR ShiftCount
332)
333{
334 LARGE_INTEGER RC;
335 CCHAR Shift;
336
337 Shift = ShiftCount % 64;
338 RC.QuadPart = LargeInteger.QuadPart >> Shift;
339
340 return RC;
341}
342
343/*
344 * @implemented
345 */
346LARGE_INTEGER
347NTAPI
348RtlLargeIntegerSubtract (
349 LARGE_INTEGER Minuend,
350 LARGE_INTEGER Subtrahend
351)
352{
353 LARGE_INTEGER RC;
354
355 RC.QuadPart = Minuend.QuadPart - Subtrahend.QuadPart;
356
357 return RC;
358}
359
360/* EOF */