char _lngamma( floatnum x, int digits) { floatstruct factor; int infinity; char result; if (float_cmp(x, &c1) == 0 || float_cmp(x, &c2) == 0) return _setzero(x); float_create(&factor); result = _lngamma_prim(x, &factor, &infinity, digits) && infinity == 0; if (result) { float_abs(&factor); _ln(&factor, digits + 1); result = float_sub(x, x, &factor, digits+1); } float_free(&factor); if (infinity != 0) return _seterror(x, ZeroDivide); if (!result) float_setnan(x); return result; }
/* evaluates tan x for |x| <= pi. A return value of 0 indicates that x = +/- pi/2 within small tolerances, so that tan x cannot be reliable computed */ char _tan( floatnum x, int digits) { signed char sgn; sgn = float_getsign(x); float_abs(x); if (float_cmp(x, &cPiDiv2) > 0) { float_sub(x, &cPi, x, digits+1); sgn = -sgn; } if (float_cmp(x, &cPiDiv4) <= 0) _tanltPiDiv4(x, digits); else { float_sub(x, &cPiDiv2, x, digits+1); if (float_iszero(x) || float_getexponent(x) < -digits) return 0; _tanltPiDiv4(x, digits); float_reciprocal(x, digits); } float_setsign(x, sgn); return 1; }
void _cos( floatnum x, int digits) { signed char sgn; float_abs(x); sgn = 1; if (float_cmp(x, &cPiDiv2) > 0) { sgn = -1; float_sub(x, &cPi, x, digits+1); } if (float_cmp(x, &cPiDiv4) <= 0) { if (2*float_getexponent(x)+2 < - digits) float_setzero(x); else _cosminus1ltPiDiv4(x, digits); float_add(x, x, &c1, digits); } else { float_sub(x, &cPiDiv2, x, digits+1); _sinltPiDiv4(x, digits); } float_setsign(x, sgn); }
char _gamma( floatnum x, int digits) { floatstruct tmp; int infinity; char result; if (float_cmp(&cMinus20, x) > 0) { float_create(&tmp); result = _lngamma_prim(x, &tmp, &infinity, digits) && infinity == 0 && _exp(x, digits) && float_div(x, x, &tmp, digits + 1); float_free(&tmp); if (infinity != 0) return _seterror(x, ZeroDivide); if (!result) float_setnan(x); return result; } return _gammagtminus20(x, digits); }
/** * Uses float_cmp to compare an array element-by-element using a specified tolerance. * Returns a number less than, equal to, or greater than zero. */ int float_cmp_array(float *a, float *b, float tol, size_t nelem) { for(size_t i = 0; i < nelem; i++) { int res = float_cmp(a[i], b[i], tol); if(res != 0) return res; } return 0; }
/* evaluates cos x - 1 for |x| <= pi. This function may underflow, which is indicated by the return value 0 */ char _cosminus1( floatnum x, int digits) { float_abs(x); if (float_cmp(x, &cPiDiv4) <= 0) return _cosminus1ltPiDiv4(x, digits); _cos(x, digits); float_sub(x, x, &c1, digits); return 1; }
int test_131() { size_t m = 1; size_t n = 3; size_t p = 1; float a[3] = {1, 2, 3}; float b[3] = {1, 2, 3}; float c[1]; matrix_multiply(a, b, c, m, n, p); ASSERT(!float_cmp(c[0], 14.0f, TOLERANCE)); return 1; }
static char _pochhammer_i( floatnum x, cfloatnum n, int digits) { /* do not use the expensive Gamma function when a few multiplications do the same */ /* pre: n is an integer */ int ni; signed char result; if (float_iszero(n)) return float_copy(x, &c1, EXACT); if (float_isinteger(x)) { result = -1; float_neg((floatnum)n); if (float_getsign(x) <= 0 && float_cmp(x, n) > 0) /* x and x+n have opposite signs, meaning 0 is among the factors */ result = _setzero(x); else if (float_getsign(x) > 0 && float_cmp(x, n) <= 0) /* x and x+n have opposite signs, meaning at one point you have to divide by 0 */ result = _seterror(x, ZeroDivide); float_neg((floatnum)n); if (result >= 0) return result; } if (float_getexponent(x) < EXPMAX/100) { ni = float_asinteger(n); if (ni != 0 && ni < 50 && ni > -50) return _pochhammer_si(x, ni, digits+2); } return _pochhammer_g(x, n, digits); }
char float_tanh( floatnum x, int digits) { signed char sgn; if (!chckmathparam(x, digits)) return 0; sgn = float_getsign(x); float_abs(x); if (float_cmp(x, &c1Div2) >= 0) _tanhgt0_5(x, digits); else _tanhlt0_5(x, digits); float_setsign(x, sgn); return 1; }
char float_artanhxplus1( floatnum x, int digits) { if (!chckmathparam(x, digits)) return 0; if (float_getsign(x) >= 0 || float_abscmp(x, &c2) >= 0) return _seterror(x, OutOfDomain); if (float_cmp(x, &c1Div2) < 0) { float_neg(x); _artanh1minusx(x, digits); } else { float_sub(x, &c1, x, digits+1); _artanh(x, digits); } return 1; }
char float_tanhminus1( floatnum x, int digits) { if (!chckmathparam(x, digits)) return 0; if (float_cmp(x, &c1Div2) >= 0) return _tanhminus1gt0(x, digits)? 1 : _seterror(x, Underflow); if (!float_iszero(x)) { if (float_abscmp(x, &c1Div2) <= 0) _tanhlt0_5(x, digits); else { float_setsign(x, 1); _tanhgt0_5(x, digits); float_setsign(x, -1); } } return float_sub(x, x, &c1, digits); }
/* evaluates arccos x for -1 <= x <= 1. The result is in the range 0 <= result <= pi. The relative error for a 100 digit result is < 5e-100 */ void _arccos( floatnum x, int digits) { signed char sgn; sgn = float_getsign(x); float_abs(x); if (float_cmp(x, &c1Div2) > 0) { float_sub(x, x, &c1, digits+1); _arccosxplus1lt0_5(x, digits); } else { _arcsinlt0_5(x, digits); float_sub(x, &cPiDiv2, x, digits+1); } if (sgn < 0) float_sub(x, &cPi, x, digits+1); }
void TemplateTable::double_cmp(int unordered_result) { transition(dtos, itos); float_cmp(false, unordered_result); }
void TemplateTable::float_cmp(int unordered_result) { transition(ftos, itos); float_cmp(true, unordered_result); }