xref: /reactos/sdk/lib/rtl/largeint.c (revision 845faec4)
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
22 USHORT FASTCALL RtlUshortByteSwap(USHORT Source);
23 PVOID Dummy = RtlUshortByteSwap;
24 #endif
25 
26 /*
27  * @implemented
28  */
29 LARGE_INTEGER
30 NTAPI
31 RtlConvertLongToLargeInteger (
32    LONG SignedInteger
33 )
34 {
35    LARGE_INTEGER RC;
36 
37    RC.QuadPart = SignedInteger;
38 
39    return RC;
40 }
41 
42 /*
43  * @implemented
44  */
45 LARGE_INTEGER
46 NTAPI
47 RtlConvertUlongToLargeInteger (
48    ULONG UnsignedInteger
49 )
50 {
51    LARGE_INTEGER RC;
52 
53    RC.QuadPart = UnsignedInteger;
54 
55    return RC;
56 }
57 
58 /*
59  * @implemented
60  */
61 LARGE_INTEGER
62 NTAPI
63 RtlEnlargedIntegerMultiply (
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  */
78 ULONG
79 NTAPI
80 RtlEnlargedUnsignedDivide (
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  */
95 LARGE_INTEGER
96 NTAPI
97 RtlEnlargedUnsignedMultiply (
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  */
112 LARGE_INTEGER
113 NTAPI
114 RtlExtendedIntegerMultiply (
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  */
129 LARGE_INTEGER
130 NTAPI
131 RtlExtendedLargeIntegerDivide (
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  */
175 LARGE_INTEGER NTAPI
176 RtlExtendedMagicDivide (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  */
225 LARGE_INTEGER
226 NTAPI
227 RtlLargeIntegerAdd (
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  */
242 LARGE_INTEGER
243 NTAPI
244 RtlLargeIntegerArithmeticShift (
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  */
271 LARGE_INTEGER
272 NTAPI
273 RtlLargeIntegerDivide (
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  */
292 LARGE_INTEGER
293 NTAPI
294 RtlLargeIntegerNegate (
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  */
308 LARGE_INTEGER
309 NTAPI
310 RtlLargeIntegerShiftLeft (
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  */
327 LARGE_INTEGER
328 NTAPI
329 RtlLargeIntegerShiftRight (
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  */
346 LARGE_INTEGER
347 NTAPI
348 RtlLargeIntegerSubtract (
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 */
361