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