// SPDX-License-Identifier: GPL-2.0 /*---------------------------------------------------------------------------+ | poly_sin.c | | | | Computation of an approximation of the sin function and the cosine | | function by a polynomial. | | | | Copyright (C) 1992,1993,1994,1997,1999 | | W. Metzenthen, 22 Parker St, Ormond, Vic 3163, Australia | | E-mail billm@melbpc.org.au | | | | |
+---------------------------------------------------------------------------*/
/* Split into two ranges, for arguments below and above 1.0 */ /* The boundary between upper and lower is approx 0.88309101259 */ if ((exponent < -1)
|| ((exponent == -1) && (st0_ptr->sigh <= 0xe21240aa))) { /* The argument is <= 0.88309101259 */
setexponentpos(&result, exponent(st0_ptr) + echange);
} else { /* The argument is > 0.88309101259 */ /* We use sin(st(0)) = cos(pi/2-st(0)) */
fixed_arg = significand(st0_ptr);
if (exponent == 0) { /* The argument is >= 1.0 */
/* Put the binary point at the left. */
fixed_arg <<= 1;
} /* pi/2 in hex is: 1.921fb54442d18469 898CC51701B839A2 52049C1 */
fixed_arg = 0x921fb54442d18469LL - fixed_arg; /* There is a special case which arises due to rounding, to fix here. */ if (fixed_arg == 0xffffffffffffffffLL)
fixed_arg = 0;
accumulator.lsw |= 1; /* A zero accumulator here would cause problems */
negate_Xsig(&accumulator);
/* The basic computation is complete. Now fix the answer to compensate for the error due to the approximation used for pi/2
*/
/* This has an exponent of -65 */
fix_up = 0x898cc517; /* The fix-up needs to be improved for larger args */ if (argSqrd.msw & 0xffc00000) { /* Get about 32 bit precision in these: */
fix_up -= mul_32_32(0x898cc517, argSqrd.msw) / 6;
}
fix_up = mul_32_32(fix_up, LL_MSW(fixed_arg));
adj = accumulator.lsw; /* temp save */
accumulator.lsw -= fix_up; if (accumulator.lsw > adj)
XSIG_LL(accumulator)--;
/* It doesn't matter if accumulator is all zero here, the
following code will work ok */
negate_Xsig(&accumulator);
if (accumulator.lsw & 0x80000000)
XSIG_LL(accumulator)++; if (accumulator.msw == 0) { /* The result is 1.0 */
FPU_copy_to_reg0(&CONST_1, TAG_Valid); return;
} else {
significand(&result) = XSIG_LL(accumulator);
/* will be a valid positive nr with expon = -1 */
setexponentpos(&result, -1);
}
} else {
fixed_arg = significand(st0_ptr);
if (exponent == 0) { /* The argument is >= 1.0 */
/* Put the binary point at the left. */
fixed_arg <<= 1;
} /* pi/2 in hex is: 1.921fb54442d18469 898CC51701B839A2 52049C1 */
fixed_arg = 0x921fb54442d18469LL - fixed_arg; /* There is a special case which arises due to rounding, to fix here. */ if (fixed_arg == 0xffffffffffffffffLL)
fixed_arg = 0;
exponent = -1;
exp2 = -1;
/* A shift is needed here only for a narrow range of arguments,
i.e. for fixed_arg approx 2^-32, but we pick up more... */ if (!(LL_MSW(fixed_arg) & 0xffff0000)) {
fixed_arg <<= 16;
exponent -= 16;
exp2 -= 16;
}
/* The basic computation is complete. Now fix the answer to compensate for the error due to the approximation used for pi/2
*/
/* This has an exponent of -65 */
XSIG_LL(fix_up) = 0x898cc51701b839a2ll;
fix_up.lsw = 0;
/* The fix-up needs to be improved for larger args */ if (argSqrd.msw & 0xffc00000) { /* Get about 32 bit precision in these: */
fix_up.msw -= mul_32_32(0x898cc517, argSqrd.msw) / 2;
fix_up.msw += mul_32_32(0x898cc517, argTo4.msw) / 24;
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.