update for HEAD-2003091401
[reactos.git] / ntoskrnl / rtl / largeint.c
index de584b8..b62213b 100644 (file)
@@ -19,6 +19,9 @@
 
 /* FUNCTIONS *****************************************************************/
 
+/*
+ * @implemented
+ */
 LARGE_INTEGER
 STDCALL
 RtlConvertLongToLargeInteger (
@@ -32,6 +35,9 @@ RtlConvertLongToLargeInteger (
        return RC;
 }
 
+/*
+ * @implemented
+ */
 LARGE_INTEGER
 STDCALL
 RtlConvertUlongToLargeInteger (
@@ -45,6 +51,9 @@ RtlConvertUlongToLargeInteger (
        return RC;
 }
 
+/*
+ * @implemented
+ */
 LARGE_INTEGER
 STDCALL
 RtlEnlargedIntegerMultiply (
@@ -59,6 +68,9 @@ RtlEnlargedIntegerMultiply (
        return RC;
 }
 
+/*
+ * @implemented
+ */
 ULONG
 STDCALL
 RtlEnlargedUnsignedDivide (
@@ -73,6 +85,9 @@ RtlEnlargedUnsignedDivide (
        return (ULONG)(Dividend.QuadPart / Divisor);
 }
 
+/*
+ * @implemented
+ */
 LARGE_INTEGER
 STDCALL
 RtlEnlargedUnsignedMultiply (
@@ -87,6 +102,9 @@ RtlEnlargedUnsignedMultiply (
        return RC;
 }
 
+/*
+ * @implemented
+ */
 LARGE_INTEGER
 STDCALL
 RtlExtendedIntegerMultiply (
@@ -101,6 +119,9 @@ RtlExtendedIntegerMultiply (
        return RC;
 }
 
+/*
+ * @implemented
+ */
 LARGE_INTEGER
 STDCALL
 RtlExtendedLargeIntegerDivide (
@@ -119,18 +140,84 @@ RtlExtendedLargeIntegerDivide (
        return RC;
 }
 
-LARGE_INTEGER
-STDCALL
-RtlExtendedMagicDivide (LARGE_INTEGER  Dividend,
-                       LARGE_INTEGER   MagicDivisor,
-                       CCHAR           ShiftCount)
-{
-  LARGE_INTEGER Result;
 
-  Result.QuadPart = (Dividend.QuadPart * MagicDivisor.QuadPart) >> ShiftCount;
-  return(Result);
+/******************************************************************************
+ * RtlExtendedMagicDivide
+ *
+ * Allows replacing a division by a longlong constant with a multiplication by
+ * the inverse constant.
+ *
+ * RETURNS
+ *  (Dividend * MagicDivisor) >> (64 + ShiftCount)
+ *
+ * NOTES
+ *  If the divisor of a division is constant, the constants MagicDivisor and
+ *  shift must be chosen such that
+ *  MagicDivisor = 2^(64 + ShiftCount) / Divisor.
+ *
+ *  Then we have RtlExtendedMagicDivide(Dividend,MagicDivisor,ShiftCount) ==
+ *  Dividend * MagicDivisor / 2^(64 + ShiftCount) == Dividend / Divisor.
+ *
+ *  The Parameter MagicDivisor although defined as LONGLONG is used as
+ *  ULONGLONG.
+ */
+
+#define LOWER_32(A) ((A) & 0xffffffff)
+#define UPPER_32(A) ((A) >> 32)
+
+/*
+ * @implemented
+ */
+LARGE_INTEGER STDCALL
+RtlExtendedMagicDivide (LARGE_INTEGER Dividend,
+                       LARGE_INTEGER MagicDivisor,
+                       CCHAR ShiftCount)
+{
+  ULONGLONG dividend_high;
+  ULONGLONG dividend_low;
+  ULONGLONG inverse_divisor_high;
+  ULONGLONG inverse_divisor_low;
+  ULONGLONG ah_bl;
+  ULONGLONG al_bh;
+  LARGE_INTEGER result;
+  BOOLEAN positive;
+
+  if (Dividend.QuadPart < 0)
+    {
+      dividend_high = UPPER_32((ULONGLONG) -Dividend.QuadPart);
+      dividend_low =  LOWER_32((ULONGLONG) -Dividend.QuadPart);
+      positive = FALSE;
+    }
+  else
+    {
+      dividend_high = UPPER_32((ULONGLONG) Dividend.QuadPart);
+      dividend_low =  LOWER_32((ULONGLONG) Dividend.QuadPart);
+      positive = TRUE;
+    }
+  inverse_divisor_high = UPPER_32((ULONGLONG) MagicDivisor.QuadPart);
+  inverse_divisor_low =  LOWER_32((ULONGLONG) MagicDivisor.QuadPart);
+
+  ah_bl = dividend_high * inverse_divisor_low;
+  al_bh = dividend_low * inverse_divisor_high;
+
+  result.QuadPart =
+    (LONGLONG) ((dividend_high * inverse_divisor_high +
+                UPPER_32(ah_bl) +
+                UPPER_32(al_bh) +
+                UPPER_32(LOWER_32(ah_bl) + LOWER_32(al_bh) +
+                         UPPER_32(dividend_low * inverse_divisor_low))) >> ShiftCount);
+  if (!positive)
+    {
+      result.QuadPart = -result.QuadPart;
+    }
+
+  return result;
 }
 
+
+/*
+ * @implemented
+ */
 LARGE_INTEGER
 STDCALL
 RtlLargeIntegerAdd (
@@ -145,6 +232,9 @@ RtlLargeIntegerAdd (
        return RC;
 }
 
+/*
+ * @implemented
+ */
 LARGE_INTEGER
 STDCALL
 RtlLargeIntegerArithmeticShift (
@@ -171,6 +261,9 @@ RtlLargeIntegerArithmeticShift (
        return RC;
 }
 
+/*
+ * @implemented
+ */
 LARGE_INTEGER
 STDCALL
 RtlLargeIntegerDivide (
@@ -189,6 +282,9 @@ RtlLargeIntegerDivide (
        return RC;
 }
 
+/*
+ * @implemented
+ */
 LARGE_INTEGER
 STDCALL
 RtlLargeIntegerNegate (
@@ -202,6 +298,9 @@ RtlLargeIntegerNegate (
        return RC;
 }
 
+/*
+ * @implemented
+ */
 LARGE_INTEGER
 STDCALL
 RtlLargeIntegerShiftLeft (
@@ -218,6 +317,9 @@ RtlLargeIntegerShiftLeft (
        return RC;
 }
 
+/*
+ * @implemented
+ */
 LARGE_INTEGER
 STDCALL
 RtlLargeIntegerShiftRight (
@@ -234,6 +336,9 @@ RtlLargeIntegerShiftRight (
        return RC;
 }
 
+/*
+ * @implemented
+ */
 LARGE_INTEGER
 STDCALL
 RtlLargeIntegerSubtract (