END_TEST START_TEST(test_negate_negative) { struct fp_number fp = fp_strtofp("-14.5", NULL, 9, 25); struct fp_number nfp = fp_negate(fp); ck_assert_int_eq(nfp.integer.value, 14); ck_assert_int_eq(fp.fraction.value, nfp.fraction.value); ck_assert_str_eq(fp_fptostr(nfp, NULL), "14.5"); }
double sinh(double x) { int sign; ip_number ix,r; ix=_d2e(x); if (fp_uncommon(ix)) goto dom_error; sign=fp_sign(ix); fp_abs(ix); if (fp_grpow(ix,0)) { /* _sinh_lnv is REQUIRED to read in as a number with the lower part of */ /* its floating point representation zero. */ ip_number w,z,z2; w=_esub(ix,&sinh_lnv); z=_exp(w); if (fp_error(z)) goto range_error; if (!fp_grpow(z,32)) { ip_number t; z2=z; t=_erdv(z,&sinh_vm2); fp_negate(t); z=_eadd(t,&z2); } z2=z; r=_eadd(_emul(z,&sinh_v2m1),&z2); fp_abs(r); r.word.hi|=sign; } else if (!fp_grpow(ix,-32)) return x; else { ip_number g,t,ix2; ix2=ix; g=_esquare(ix); /* Use a (minimax) rational approximation. See Cody & Waite. */ t=__fp_poly1(g,4,sinhp_poly); r=_erdv(__fp_poly0(g,3,sinhq_poly),&t); ix2.word.hi|=sign; /* put sign back */ r=__fp_spike(r,&ix2); /* r=r*ix+ix */ } if (fp_error(r)) goto range_error; return _e2d(r); dom_error: return __fp_edom(sign_bit, TRUE); range_error: return __fp_erange(ix.word.hi, TRUE); }
double tanh(double x) { /* The first two exits avoid premature overflow as well as needless use */ /* of the exp() function. */ int sign; dp_number fx; fx.d=x; sign=fp_sign(fx); fp_abs(fx); if (fx.d<=27.0) { ip_number ix=_d2e(fx.d); if (fp_uncommon(ix)) goto uncommon; if (_egr(ix,&log3_by_2)) { ix=_emul(ix,&two); ix=_exp(ix); if (fp_error(ix)) goto error; ix=_erdv(_eadd(ix,&one),&two); fp_negate(ix); ix=_eadd(ix,&one); } else { if (fp_grpow(ix,-32)) { ip_number g,t,r1,r2,ix2; ix2=ix; g=_esquare(ix2); r1=__fp_poly1(g,3,tanhp_poly); r2=__fp_poly0(g,3,tanhq_poly); t=_erdv(r2,&r1); ix=__fp_spike(t,&ix2); /* ix=g*ix+ix */ } } ix.word.hi|=sign; if (fp_error(ix)) goto error; return _e2d(ix); } else { dp_number result; result.word.hi=0x3ff00000 | sign; result.word.lo=0; return result.d; } error: return __fp_erange(sign, TRUE); uncommon: return __fp_edom(0, TRUE); }
double _asnacs(double x,int acs_flag) { ip_number ix,g,r,t1; int sign,flags; ix=_d2e(x); if (!fp_uncommon(ix)) { sign=fp_sign(ix); fp_abs(ix); if (fp_geqpow(ix,-1)) { /* ix>=0.5 */ /* Filter out domain errors and 1.0 */ if (fp_geqpow(ix,0)) goto dom_error; /* ix<1.0 */ /* ix is in the range [0.5,1.0] (acos(1.0) already catered for) */ flags=acs_flag ? sign ? 0xe : 0x0 : sign ? 0xd : 0xc; /* Do the range reduction g := (1-Y)/2; Y := 2*SQT(g) as done by the FPE. */ g=ix; fp_negate(g); g=_eadd(g,&one); g.word.hi--; /* /2 - we can use exp arithmetic because */ ix=_esqrt(g); ix.word.hi++; /* *2 - we know ix is in the range [0.5,1.0] */ } else { flags=acs_flag ? sign ? 0x4 : 0xc : sign ? 0x1 : 0x0; if (!fp_geqpow(ix,-32)) goto very_small; g=_esquare(ix); } t1=__fp_poly0(g,5,asnacsq_poly); r=_ediv(__fp_poly1(g,5,asnacsp_poly),&t1); ix=__fp_spike(r,&ix); /* ix=r*ix+ix */ very_small: ix.word.hi^=(flags & 0x8) << 28; /* negate if bit 3 of flags is set */ if (flags & 0x4) { /* If bit 2 is set... */ /* ...add a constant */ ip_number constant=pi_by_2; if (flags & 0x2) constant.word.hi++; /* Turn into pi if bit 1 set */ ix=_eadd(constant,&ix); } ix.word.hi^=flags<<31; /* Negate final answer if bit 0 set */ return _e2d(ix); dom_error: /* Either a domain error or an argument of 1.0 */ if (fp_eqpow(ix,0)) { dp_number res; /* This is an exact result of -pi/2, 0, pi/2 or pi depending... */ res.d=_pi_2; if (acs_flag) { if (sign) res.word.hi+=1<<DExp_pos; /* change pi/2 to pi */ else res.d=0.0; } else { res.word.hi|=sign; } return res.d; } /* Fall through to EDOM code */ } /* asin/acos(Inf/QNaN/SNaN) => DOMAIN ERROR */ return __fp_edom(sign_bit, TRUE); }