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