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