Author: aandrejevic Date: Sat May 23 02:50:11 2015 New Revision: 67855
URL: http://svn.reactos.org/svn/reactos?rev=67855&view=rev Log: [FAST486] Use a better algorithm for the base 2 logarithm. Put the shared code for FPREM and FPREM1 in an inline function used by both.
Modified: trunk/reactos/lib/fast486/fpu.c
Modified: trunk/reactos/lib/fast486/fpu.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/lib/fast486/fpu.c?rev=67855... ============================================================================== --- trunk/reactos/lib/fast486/fpu.c [iso-8859-1] (original) +++ trunk/reactos/lib/fast486/fpu.c [iso-8859-1] Sat May 23 02:50:11 2015 @@ -52,6 +52,9 @@
/* ln(2) */ static const FAST486_FPU_DATA_REG FpuLnTwo = {0xB17217F7D1CF79ABULL, FPU_REAL10_BIAS - 1, FALSE}; + +/* 2.00 */ +static const FAST486_FPU_DATA_REG FpuTwo = {0x8000000000000000ULL, FPU_REAL10_BIAS + 1, FALSE};
static const FAST486_FPU_DATA_REG FpuInverseNumber[INVERSE_NUMBERS_COUNT] = { @@ -1105,11 +1108,6 @@ *Result = TempResult; }
-/* - * Calculates using the identities: - * log2(x) = ln(x) / ln(2) - * ln(x)= sum { -1^(n+1) * x^n / n!, n >= 1 } - */ static inline BOOLEAN FASTCALL Fast486FpuCalculateLogBase2(PFAST486_STATE State, PFAST486_FPU_DATA_REG Operand, @@ -1117,7 +1115,6 @@ { INT i; FAST486_FPU_DATA_REG Value = *Operand; - FAST486_FPU_DATA_REG SeriesElement; FAST486_FPU_DATA_REG TempResult; FAST486_FPU_DATA_REG TempValue; LONGLONG UnbiasedExp = (LONGLONG)Operand->Exponent - FPU_REAL10_BIAS; @@ -1163,40 +1160,31 @@ Value.Mantissa <<= Bits; }
- /* Subtract one from the value */ - if (!Fast486FpuSubtract(State, &Value, &FpuOne, &Value)) return FALSE; - - /* Calculate the natural logarithm */ - SeriesElement = TempResult = Value; - - for (i = 2; i < INVERSE_NUMBERS_COUNT / 2; i++) - { - if (!Fast486FpuMultiply(State, &SeriesElement, &Value, &SeriesElement)) - { - /* An exception occurred */ - return FALSE; - } - - /* Toggle the sign of the series element */ - SeriesElement.Sign = !SeriesElement.Sign; - - /* Divide it by the counter */ - if (!Fast486FpuMultiply(State, &SeriesElement, &FpuInverseNumber[i - 1], &TempValue)) - { - /* An exception occurred */ - return FALSE; - } - - /* And add it to the result */ - if (!Fast486FpuAdd(State, &TempResult, &TempValue, &TempResult)) - { - /* An exception occurred */ - return FALSE; - } - } - - /* Now convert the natural logarithm into a base 2 logarithm */ - if (!Fast486FpuDivide(State, &TempResult, &FpuLnTwo, &TempResult)) return FALSE; + TempResult.Sign = FALSE; + TempResult.Exponent = FPU_REAL10_BIAS - 1; + TempResult.Mantissa = 0ULL; + + for (i = 63; i >= 0; i--) + { + /* Square the value */ + if (!Fast486FpuMultiply(State, &Value, &Value, &Value)) return FALSE; + + /* Subtract two from it */ + if (!Fast486FpuSubtract(State, &Value, &FpuTwo, &TempValue)) return FALSE; + + /* Is the result positive? */ + if (!TempValue.Sign) + { + /* Yes, set the appropriate bit in the mantissa */ + TempResult.Mantissa |= 1ULL << i; + + /* Halve the value */ + if (!Fast486FpuMultiply(State, &Value, &FpuInverseNumber[1], &Value)) return FALSE; + } + } + + /* Normalize the result */ + if (!Fast486FpuNormalize(State, &TempResult)) return FALSE;
/* * Add the exponent to the result @@ -1207,6 +1195,35 @@
*Result = TempResult; return TRUE; +} + +static inline BOOLEAN FASTCALL +Fast486FpuRemainder(PFAST486_STATE State, + PCFAST486_FPU_DATA_REG FirstOperand, + PCFAST486_FPU_DATA_REG SecondOperand, + BOOLEAN RoundToNearest, + PFAST486_FPU_DATA_REG Result) +{ + BOOLEAN Success = FALSE; + INT OldRoundingMode = State->FpuControl.Rc; + LONGLONG Integer; + FAST486_FPU_DATA_REG Temp; + + if (!Fast486FpuDivide(State, FirstOperand, SecondOperand, &Temp)) return FALSE; + + State->FpuControl.Rc = RoundToNearest ? FPU_ROUND_NEAREST : FPU_ROUND_TRUNCATE; + + if (!Fast486FpuToInteger(State, &Temp, &Integer)) goto Cleanup; + Fast486FpuFromInteger(State, Integer, &Temp); + + if (!Fast486FpuMultiply(State, &Temp, SecondOperand, &Temp)) goto Cleanup; + if (!Fast486FpuSubtract(State, FirstOperand, &Temp, Result)) goto Cleanup; + + Success = TRUE; + +Cleanup: + State->FpuControl.Rc = OldRoundingMode; + return Success; }
/* @@ -2008,10 +2025,6 @@ /* FPREM1 */ case 0x35: { - FAST486_FPU_DATA_REG Temp; - LONGLONG Integer; - INT OldRoundingMode = State->FpuControl.Rc; - if (FPU_GET_TAG(0) == FPU_TAG_EMPTY || FPU_GET_TAG(1) == FPU_TAG_EMPTY) { State->FpuStatus.Ie = TRUE; @@ -2020,34 +2033,9 @@ break; }
- /* Divide ST0 by ST1 */ - if (!Fast486FpuDivide(State, &FPU_ST(0), &FPU_ST(1), &Temp)) break; - - /* Round the result to the nearest integer */ - if (FPU_ST(0).Exponent < FPU_REAL10_BIAS + 63) - { - State->FpuControl.Rc = FPU_ROUND_NEAREST; - - if (Fast486FpuToInteger(State, &Temp, &Integer)) - { - Fast486FpuFromInteger(State, Integer, &Temp); - State->FpuControl.Rc = OldRoundingMode; - } - else - { - /* Restore the rounding mode and exit */ - State->FpuControl.Rc = OldRoundingMode; - break; - } - } - - /* Multiply the result by ST1 */ - if (!Fast486FpuMultiply(State, &Temp, &FPU_ST(1), &Temp)) break; - - /* Subtract the result from ST0 */ - if (!Fast486FpuSubtract(State, &FPU_ST(0), &Temp, &FPU_ST(0))) break; - + Fast486FpuRemainder(State, &FPU_ST(0), &FPU_ST(1), TRUE, &FPU_ST(0)); FPU_UPDATE_TAG(0); + break; }
@@ -2068,10 +2056,6 @@ /* FPREM */ case 0x38: { - FAST486_FPU_DATA_REG Temp; - LONGLONG Integer; - INT OldRoundingMode = State->FpuControl.Rc; - if (FPU_GET_TAG(0) == FPU_TAG_EMPTY || FPU_GET_TAG(1) == FPU_TAG_EMPTY) { State->FpuStatus.Ie = TRUE; @@ -2080,34 +2064,9 @@ break; }
- /* Divide ST0 by ST1 */ - if (!Fast486FpuDivide(State, &FPU_ST(0), &FPU_ST(1), &Temp)) break; - - /* Round the result to an integer, towards zero */ - if (FPU_ST(0).Exponent < FPU_REAL10_BIAS + 63) - { - State->FpuControl.Rc = FPU_ROUND_TRUNCATE; - - if (Fast486FpuToInteger(State, &Temp, &Integer)) - { - Fast486FpuFromInteger(State, Integer, &Temp); - State->FpuControl.Rc = OldRoundingMode; - } - else - { - /* Restore the rounding mode and exit */ - State->FpuControl.Rc = OldRoundingMode; - break; - } - } - - /* Multiply the result by ST1 */ - if (!Fast486FpuMultiply(State, &Temp, &FPU_ST(1), &Temp)) break; - - /* Subtract the result from ST0 */ - if (!Fast486FpuSubtract(State, &FPU_ST(0), &Temp, &FPU_ST(0))) break; - + Fast486FpuRemainder(State, &FPU_ST(0), &FPU_ST(1), FALSE, &FPU_ST(0)); FPU_UPDATE_TAG(0); + break; }