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