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