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