Author: aandrejevic Date: Mon May 25 03:23:40 2015 New Revision: 67894
URL: http://svn.reactos.org/svn/reactos?rev=67894&view=rev Log: [FAST486] Fix the implementation of FSIN and FCOS: First of all, 4 steps for a Maclaurin series is not enough. Second, the angle should be normalized to the [-pi/2, pi/2] range.
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=67894... ============================================================================== --- trunk/reactos/lib/fast486/fpu.c [iso-8859-1] (original) +++ trunk/reactos/lib/fast486/fpu.c [iso-8859-1] Mon May 25 03:23:40 2015 @@ -55,6 +55,9 @@
/* 2.00 */ static const FAST486_FPU_DATA_REG FpuTwo = {0x8000000000000000ULL, FPU_REAL10_BIAS + 1, FALSE}; + +/* Pi / 2 */ +static const FAST486_FPU_DATA_REG FpuHalfPi = {0xC90FDAA22168C235ULL, FPU_REAL10_BIAS, FALSE};
static const FAST486_FPU_DATA_REG FpuInverseNumber[INVERSE_NUMBERS_COUNT] = { @@ -110,6 +113,114 @@ {0xA3D70A3D70A3D70AULL, FPU_REAL10_BIAS - 6, FALSE}, /* 1 / 50 */ };
+static const FAST486_FPU_DATA_REG FpuInverseNumberSine[INVERSE_NUMBERS_COUNT] = +{ + {0xAAAAAAAAAAAAAAAAULL, FPU_REAL10_BIAS - 3, FALSE}, /* 1 / 6 */ + {0xCCCCCCCCCCCCCCCCULL, FPU_REAL10_BIAS - 5, FALSE}, /* 1 / 20 */ + {0xC30C30C30C30C30CULL, FPU_REAL10_BIAS - 6, FALSE}, /* 1 / 42 */ + {0xE38E38E38E38E38EULL, FPU_REAL10_BIAS - 7, FALSE}, /* 1 / 72 */ + {0x94F2094F2094F209ULL, FPU_REAL10_BIAS - 7, FALSE}, /* 1 / 110 */ + {0xD20D20D20D20D20DULL, FPU_REAL10_BIAS - 8, FALSE}, /* 1 / 156 */ + {0x9C09C09C09C09C09ULL, FPU_REAL10_BIAS - 8, FALSE}, /* 1 / 210 */ + {0xF0F0F0F0F0F0F0F0ULL, FPU_REAL10_BIAS - 9, FALSE}, /* 1 / 272 */ + {0xBFA02FE80BFA02FEULL, FPU_REAL10_BIAS - 9, FALSE}, /* 1 / 342 */ + {0x9C09C09C09C09C09ULL, FPU_REAL10_BIAS - 9, FALSE}, /* 1 / 420 */ + {0x81848DA8FAF0D277ULL, FPU_REAL10_BIAS - 9, FALSE}, /* 1 / 506 */ + {0xDA740DA740DA740DULL, FPU_REAL10_BIAS - 10, FALSE}, /* 1 / 600 */ + {0xBAB656100BAB6561ULL, FPU_REAL10_BIAS - 10, FALSE}, /* 1 / 702 */ + {0xA16B312EA8FC377CULL, FPU_REAL10_BIAS - 10, FALSE}, /* 1 / 812 */ + {0x8CF008CF008CF008ULL, FPU_REAL10_BIAS - 10, FALSE}, /* 1 / 930 */ + {0xF83E0F83E0F83E0FULL, FPU_REAL10_BIAS - 11, FALSE}, /* 1 / 1056 */ + {0xDC4A00DC4A00DC4AULL, FPU_REAL10_BIAS - 11, FALSE}, /* 1 / 1190 */ + {0xC4CE07B00C4CE07BULL, FPU_REAL10_BIAS - 11, FALSE}, /* 1 / 1332 */ + {0xB0E2A2600B0E2A26ULL, FPU_REAL10_BIAS - 11, FALSE}, /* 1 / 1482 */ + {0x9FD809FD809FD809ULL, FPU_REAL10_BIAS - 11, FALSE}, /* 1 / 1640 */ + {0x9126D6E4802449B5ULL, FPU_REAL10_BIAS - 11, FALSE}, /* 1 / 1806 */ + {0x84655D9BAB2F1008ULL, FPU_REAL10_BIAS - 11, FALSE}, /* 1 / 1980 */ + {0xF2805AF0221A0CC9ULL, FPU_REAL10_BIAS - 12, FALSE}, /* 1 / 2162 */ + {0xDEE95C4CA037BA57ULL, FPU_REAL10_BIAS - 12, FALSE}, /* 1 / 2352 */ + {0xCD9A673400CD9A67ULL, FPU_REAL10_BIAS - 12, FALSE}, /* 1 / 2550 */ + {0xBE3C310B84A4F832ULL, FPU_REAL10_BIAS - 12, FALSE}, /* 1 / 2756 */ + {0xB087277A39941560ULL, FPU_REAL10_BIAS - 12, FALSE}, /* 1 / 2970 */ + {0xA44029100A440291ULL, FPU_REAL10_BIAS - 12, FALSE}, /* 1 / 3192 */ + {0x9936034AA9121AA1ULL, FPU_REAL10_BIAS - 12, FALSE}, /* 1 / 3422 */ + {0x8F3F82A86DACA008ULL, FPU_REAL10_BIAS - 12, FALSE}, /* 1 / 3660 */ + {0x8639F00218E7C008ULL, FPU_REAL10_BIAS - 12, FALSE}, /* 1 / 3906 */ + {0xFC0FC0FC0FC0FC0FULL, FPU_REAL10_BIAS - 13, FALSE}, /* 1 / 4160 */ + {0xED208916CF412FD1ULL, FPU_REAL10_BIAS - 13, FALSE}, /* 1 / 4422 */ + {0xDF7B4EC93886702DULL, FPU_REAL10_BIAS - 13, FALSE}, /* 1 / 4692 */ + {0xD2FB287C7224E167ULL, FPU_REAL10_BIAS - 13, FALSE}, /* 1 / 4970 */ + {0xC78031E00C78031EULL, FPU_REAL10_BIAS - 13, FALSE}, /* 1 / 5256 */ + {0xBCEEBFB33F021F2EULL, FPU_REAL10_BIAS - 13, FALSE}, /* 1 / 5550 */ + {0xB32EB86E96D5D441ULL, FPU_REAL10_BIAS - 13, FALSE}, /* 1 / 5852 */ + {0xAA2B0A62E08248F3ULL, FPU_REAL10_BIAS - 13, FALSE}, /* 1 / 6162 */ + {0xA1D139855F7268EDULL, FPU_REAL10_BIAS - 13, FALSE}, /* 1 / 6480 */ + {0x9A1100604AA03C2EULL, FPU_REAL10_BIAS - 13, FALSE}, /* 1 / 6806 */ + {0x92DC0092DC0092DCULL, FPU_REAL10_BIAS - 13, FALSE}, /* 1 / 7140 */ + {0x8C258008C258008CULL, FPU_REAL10_BIAS - 13, FALSE}, /* 1 / 7482 */ + {0x85E230A32BAB46DDULL, FPU_REAL10_BIAS - 13, FALSE}, /* 1 / 7832 */ + {0x8008008008008008ULL, FPU_REAL10_BIAS - 13, FALSE}, /* 1 / 8190 */ + {0xF51BE2CC2D7AAC94ULL, FPU_REAL10_BIAS - 14, FALSE}, /* 1 / 8556 */ + {0xEAD7EC46DDA80C62ULL, FPU_REAL10_BIAS - 14, FALSE}, /* 1 / 8930 */ + {0xE135A9C97500E135ULL, FPU_REAL10_BIAS - 14, FALSE}, /* 1 / 9312 */ + {0xD8281B71177BDB7BULL, FPU_REAL10_BIAS - 14, FALSE}, /* 1 / 9702 */ + {0xCFA3892CE9FFCC17ULL, FPU_REAL10_BIAS - 14, FALSE}, /* 1 / 10100 */ +}; + +static const FAST486_FPU_DATA_REG FpuInverseNumberCosine[INVERSE_NUMBERS_COUNT] = +{ + {0x8000000000000000ULL, FPU_REAL10_BIAS - 1, FALSE}, /* 1 / 2 */ + {0xAAAAAAAAAAAAAAAAULL, FPU_REAL10_BIAS - 4, FALSE}, /* 1 / 12 */ + {0x8888888888888888ULL, FPU_REAL10_BIAS - 5, FALSE}, /* 1 / 30 */ + {0x9249249249249249ULL, FPU_REAL10_BIAS - 6, FALSE}, /* 1 / 56 */ + {0xB60B60B60B60B60BULL, FPU_REAL10_BIAS - 7, FALSE}, /* 1 / 90 */ + {0xF83E0F83E0F83E0FULL, FPU_REAL10_BIAS - 8, FALSE}, /* 1 / 132 */ + {0xB40B40B40B40B40BULL, FPU_REAL10_BIAS - 8, FALSE}, /* 1 / 182 */ + {0x8888888888888888ULL, FPU_REAL10_BIAS - 8, FALSE}, /* 1 / 240 */ + {0xD62B80D62B80D62BULL, FPU_REAL10_BIAS - 9, FALSE}, /* 1 / 306 */ + {0xAC7691840AC76918ULL, FPU_REAL10_BIAS - 9, FALSE}, /* 1 / 380 */ + {0x8DDA520237694808ULL, FPU_REAL10_BIAS - 9, FALSE}, /* 1 / 462 */ + {0xED7303B5CC0ED730ULL, FPU_REAL10_BIAS - 10, FALSE}, /* 1 / 552 */ + {0xC9A633FCD967300CULL, FPU_REAL10_BIAS - 10, FALSE}, /* 1 / 650 */ + {0xAD602B580AD602B5ULL, FPU_REAL10_BIAS - 10, FALSE}, /* 1 / 756 */ + {0x96A850096A850096ULL, FPU_REAL10_BIAS - 10, FALSE}, /* 1 / 870 */ + {0x8421084210842108ULL, FPU_REAL10_BIAS - 10, FALSE}, /* 1 / 992 */ + {0xE9A3D25E00E9A3D2ULL, FPU_REAL10_BIAS - 11, FALSE}, /* 1 / 1122 */ + {0xD00D00D00D00D00DULL, FPU_REAL10_BIAS - 11, FALSE}, /* 1 / 1260 */ + {0xBA7258200BA72582ULL, FPU_REAL10_BIAS - 11, FALSE}, /* 1 / 1406 */ + {0xA80A80A80A80A80AULL, FPU_REAL10_BIAS - 11, FALSE}, /* 1 / 1560 */ + {0x983B773A92E16009ULL, FPU_REAL10_BIAS - 11, FALSE}, /* 1 / 1722 */ + {0x8A8DCD1FEEAE465CULL, FPU_REAL10_BIAS - 11, FALSE}, /* 1 / 1892 */ + {0xFD477B6C956529CDULL, FPU_REAL10_BIAS - 12, FALSE}, /* 1 / 2070 */ + {0xE865AC7B7603A196ULL, FPU_REAL10_BIAS - 12, FALSE}, /* 1 / 2256 */ + {0xD5FEBF01E17D2DC4ULL, FPU_REAL10_BIAS - 12, FALSE}, /* 1 / 2450 */ + {0xC5B200C5B200C5B2ULL, FPU_REAL10_BIAS - 12, FALSE}, /* 1 / 2652 */ + {0xB7307B1492B1D28FULL, FPU_REAL10_BIAS - 12, FALSE}, /* 1 / 2862 */ + {0xAA392F35DC17F00AULL, FPU_REAL10_BIAS - 12, FALSE}, /* 1 / 3080 */ + {0x9E96394D47B46C68ULL, FPU_REAL10_BIAS - 12, FALSE}, /* 1 / 3306 */ + {0x941A9CC82BF7E68BULL, FPU_REAL10_BIAS - 12, FALSE}, /* 1 / 3540 */ + {0x8AA08EF5936D4008ULL, FPU_REAL10_BIAS - 12, FALSE}, /* 1 / 3782 */ + {0x8208208208208208ULL, FPU_REAL10_BIAS - 12, FALSE}, /* 1 / 4032 */ + {0xF46C5E0BB22F800FULL, FPU_REAL10_BIAS - 13, FALSE}, /* 1 / 4290 */ + {0xE6271BA5329217D3ULL, FPU_REAL10_BIAS - 13, FALSE}, /* 1 / 4556 */ + {0xD918B2EF5B7B4866ULL, FPU_REAL10_BIAS - 13, FALSE}, /* 1 / 4830 */ + {0xCD1ED923A7DCBEB2ULL, FPU_REAL10_BIAS - 13, FALSE}, /* 1 / 5112 */ + {0xC21BDD800C21BDD8ULL, FPU_REAL10_BIAS - 13, FALSE}, /* 1 / 5402 */ + {0xB7F5F08CD84C2BD5ULL, FPU_REAL10_BIAS - 13, FALSE}, /* 1 / 5700 */ + {0xAE968C517F46800AULL, FPU_REAL10_BIAS - 13, FALSE}, /* 1 / 6006 */ + {0xA5E9F6ED347F0721ULL, FPU_REAL10_BIAS - 13, FALSE}, /* 1 / 6320 */ + {0x9DDEDA75A1CD4726ULL, FPU_REAL10_BIAS - 13, FALSE}, /* 1 / 6642 */ + {0x9665EE14DB2283E4ULL, FPU_REAL10_BIAS - 13, FALSE}, /* 1 / 6972 */ + {0x8F71AD362448008FULL, FPU_REAL10_BIAS - 13, FALSE}, /* 1 / 7310 */ + {0x88F61A371B048C2BULL, FPU_REAL10_BIAS - 13, FALSE}, /* 1 / 7656 */ + {0x82E88A942AB2D933ULL, FPU_REAL10_BIAS - 13, FALSE}, /* 1 / 8010 */ + {0xFA7EF5D91AC9538AULL, FPU_REAL10_BIAS - 14, FALSE}, /* 1 / 8372 */ + {0xEFE4D31416B96CFEULL, FPU_REAL10_BIAS - 14, FALSE}, /* 1 / 8742 */ + {0xE5F36CB00E5F36CBULL, FPU_REAL10_BIAS - 14, FALSE}, /* 1 / 9120 */ + {0xDC9D0ECFCB6E9378ULL, FPU_REAL10_BIAS - 14, FALSE}, /* 1 / 9506 */ + {0xD3D56292AB7E800DULL, FPU_REAL10_BIAS - 14, FALSE}, /* 1 / 9900 */ +}; + /* PRIVATE FUNCTIONS **********************************************************/
#ifndef FAST486_NO_FPU @@ -1202,7 +1313,8 @@ PCFAST486_FPU_DATA_REG FirstOperand, PCFAST486_FPU_DATA_REG SecondOperand, BOOLEAN RoundToNearest, - PFAST486_FPU_DATA_REG Result) + PFAST486_FPU_DATA_REG Result, + PLONGLONG Quotient OPTIONAL) { BOOLEAN Success = FALSE; INT OldRoundingMode = State->FpuControl.Rc; @@ -1219,6 +1331,7 @@ if (!Fast486FpuMultiply(State, &Temp, SecondOperand, &Temp)) goto Cleanup; if (!Fast486FpuSubtract(State, FirstOperand, &Temp, Result)) goto Cleanup;
+ if (Quotient) *Quotient = Integer; Success = TRUE;
Cleanup: @@ -1236,14 +1349,43 @@ PFAST486_FPU_DATA_REG Result) { INT i; - FAST486_FPU_DATA_REG TempResult = *Operand; - FAST486_FPU_DATA_REG OperandSquared = *Operand; - FAST486_FPU_DATA_REG SeriesElement = *Operand; + ULONGLONG Quadrant; + FAST486_FPU_DATA_REG Normalized = *Operand; + FAST486_FPU_DATA_REG TempResult; + FAST486_FPU_DATA_REG OperandSquared; + FAST486_FPU_DATA_REG SeriesElement; + PCFAST486_FPU_DATA_REG Inverse; + + if (!Fast486FpuRemainder(State, + Operand, + &FpuHalfPi, + FALSE, + &Normalized, + (PLONGLONG)&Quadrant)) + { + return FALSE; + } + + /* Normalize the quadrant number */ + Quadrant &= 3; + + if (!(Quadrant & 1)) + { + /* This is a sine */ + Inverse = FpuInverseNumberSine; + TempResult = SeriesElement = Normalized; + } + else + { + /* This is a cosine */ + Inverse = FpuInverseNumberCosine; + TempResult = SeriesElement = FpuOne; + }
/* Calculate the square of the operand */ - if (!Fast486FpuMultiply(State, Operand, Operand, &OperandSquared)) return FALSE; - - for (i = 2; (i * (i + 1)) <= INVERSE_NUMBERS_COUNT; i += 2) + if (!Fast486FpuMultiply(State, &Normalized, &Normalized, &OperandSquared)) return FALSE; + + for (i = 0; i < INVERSE_NUMBERS_COUNT; i++) { if (!Fast486FpuMultiply(State, &SeriesElement, &OperandSquared, &SeriesElement)) { @@ -1253,7 +1395,7 @@
if (!Fast486FpuMultiply(State, &SeriesElement, - &FpuInverseNumber[i * (i + 1) - 1], + &Inverse[i], &SeriesElement)) { /* An exception occurred */ @@ -1269,6 +1411,9 @@ return FALSE; } } + + /* Flip the sign for the third and fourth quadrant */ + if (Quadrant >= 2) TempResult.Sign = !TempResult.Sign;
*Result = TempResult; return TRUE; @@ -1283,43 +1428,13 @@ PFAST486_FPU_DATA_REG Operand, PFAST486_FPU_DATA_REG Result) { - INT i; - FAST486_FPU_DATA_REG TempResult = FpuOne; - FAST486_FPU_DATA_REG OperandSquared = *Operand; - FAST486_FPU_DATA_REG SeriesElement = FpuOne; - - /* Calculate the square of the operand */ - if (!Fast486FpuMultiply(State, Operand, Operand, &OperandSquared)) return FALSE; - - for (i = 1; (i * (i + 1)) <= INVERSE_NUMBERS_COUNT; i += 2) - { - if (!Fast486FpuMultiply(State, &SeriesElement, &OperandSquared, &SeriesElement)) - { - /* An exception occurred */ - return FALSE; - } - - if (!Fast486FpuMultiply(State, - &SeriesElement, - &FpuInverseNumber[i * (i + 1) - 1], - &SeriesElement)) - { - /* An exception occurred */ - return FALSE; - } - - /* Toggle the sign of the series element */ - SeriesElement.Sign = !SeriesElement.Sign; - - if (!Fast486FpuAdd(State, &TempResult, &SeriesElement, &TempResult)) - { - /* An exception occurred */ - return FALSE; - } - } - - *Result = TempResult; - return TRUE; + FAST486_FPU_DATA_REG Value = *Operand; + + /* Add pi / 2 */ + if (!Fast486FpuAdd(State, &Value, &FpuHalfPi, &Value)) return FALSE; + + /* Calculate the sine */ + return Fast486FpuCalculateSine(State, &Value, Result); }
static inline VOID FASTCALL @@ -2090,7 +2205,7 @@ break; }
- Fast486FpuRemainder(State, &FPU_ST(0), &FPU_ST(1), TRUE, &FPU_ST(0)); + Fast486FpuRemainder(State, &FPU_ST(0), &FPU_ST(1), TRUE, &FPU_ST(0), NULL); FPU_UPDATE_TAG(0);
break; @@ -2121,7 +2236,7 @@ break; }
- Fast486FpuRemainder(State, &FPU_ST(0), &FPU_ST(1), FALSE, &FPU_ST(0)); + Fast486FpuRemainder(State, &FPU_ST(0), &FPU_ST(1), FALSE, &FPU_ST(0), NULL); FPU_UPDATE_TAG(0);
break;