double log(double x) { int exp; static const double coeff[] = { 0.0000000000, /* a0 */ 0.9999964239, /* a1 */ -0.4998741238, /* a2 */ 0.3317990258, /* a3 */ -0.2407338084, /* a4 */ 0.1676540711, /* a5 */ -0.0953293897, /* a6 */ 0.0360884937, /* a7 */ -0.0064535442, /* a8 */ }; /* zero or -ve arguments are not defined */ if(x < 0.0) { errno = EDOM; return 0.0; } if(x == 0.0) { errno = ERANGE; return 0.0; } x = frexp(x, &exp) * 2.0 - 1.0; exp--; x = eval_poly(x, coeff, sizeof coeff/sizeof coeff[0] - 1); return x + 0.69314718055995 * exp; }
/*------------------------------------------------------------------*/ int32 fplog_eval_poly(int64 a, uint32 b, mpz_t scratch, mpz_poly_t *f, double log_base, uint32 *bits) { /* Compute f(a,b) and take its logarithm in the current base of sieve logarithms, rounding down */ eval_poly(scratch, a, b, f); *bits = mpz_sizeinbase(scratch, 2); return (uint32)((*bits) * M_LN2 / log_base); }
double get_log_base(mpz_poly_t *poly, int64 a0, int64 a1, uint32 b) { /* Decide on a base for the logs of one polynomial. The rational poly is assumed linear, its maximum value occurs at one of the endpoints of the sieve interval Rigorously finding the extreme values of the algebraic poly would require finding the minima and maxima, and comparing the polynomial values there to the values at a0 and a1. However, experiments show that for small b the values at the endpoints are much larger than those at the extreme values, and for large b the values are close but the extreme values tend to be outside the sieve interval. Hence we cheat and just do the same as with the rational poly */ double t; mpz_t tmp1, tmp2; mpz_init(tmp1); mpz_init(tmp2); eval_poly(tmp1, a0, b, poly); eval_poly(tmp2, a1, b, poly); if (mpz_cmp(tmp2, tmp1) > 0) t = mpz_sizeinbase(tmp1, 2); else t = mpz_sizeinbase(tmp2, 2); /* the base to use is a number x such that log_x (2^t) = LOG_TARGET. After much re- arranging, x amounts to: */ mpz_clear(tmp1); mpz_clear(tmp2); return pow(2.0, t / LOG_TARGET); }
int main() { int degree; printf("Enter the degree of the polynomial: "); scanf("%d", °ree); printf("Enter each coefficient: "); double coeff[degree]; get_poly(coeff[degree], degree); double x; printf("Enter the value for x: "); scanf("%lf", &x); eval_poly(coeff[degree], degree, x); system("pause"); return 0; }
double exp(double x) { int exp; char sign; const static double coeff[] = { 1.0000000000e+00, 6.9314718056e-01, 2.4022650695e-01, 5.5504108945e-02, 9.6181261779e-03, 1.3333710529e-03, 1.5399104432e-04, 1.5327675257e-05, 1.2485143336e-06, 1.3908092221e-07, }; if(x == 0.0) return 1.0; #if sizeof(double)<=4 if (x > EXP_MAX) { //too big? errno = ERANGE; return DBL_MAX; } if (x < EXP_MIN) { //too small? errno = ERANGE; return 0.0; } #endif sign = x < 0.0; if(sign) x = -x; x *= 1.4426950409; /* convert to log2 */ exp = (int)floor(x); x -= (double)exp; x = ldexp(eval_poly(x, coeff, sizeof coeff/sizeof coeff[0] - 1), exp); if(sign) { if (x == DBL_MAX) return 0.0; return 1.0/x; } return x; }
static double bessel(double x) { // Modified Bessel function of the first kind of order zero // minimax rational approximations on intervals, see // Blair and Edwards, Chalk River Report AECL-4928, 1974 static const double p1[] = { -2.2335582639474375249e+15, -5.5050369673018427753e+14, -3.2940087627407749166e+13, -8.4925101247114157499e+11, -1.1912746104985237192e+10, -1.0313066708737980747e+08, -5.9545626019847898221e+05, -2.4125195876041896775e+03, -7.0935347449210549190e+00, -1.5453977791786851041e-02, -2.5172644670688975051e-05, -3.0517226450451067446e-08, -2.6843448573468483278e-11, -1.5982226675653184646e-14, -5.2487866627945699800e-18, }; static const double q1[] = { -2.2335582639474375245e+15, 7.8858692566751002988e+12, -1.2207067397808979846e+10, 1.0377081058062166144e+07, -4.8527560179962773045e+03, 1.0, }; static const double p2[] = { -2.2210262233306573296e-04, 1.3067392038106924055e-02, -4.4700805721174453923e-01, 5.5674518371240761397e+00, -2.3517945679239481621e+01, 3.1611322818701131207e+01, -9.6090021968656180000e+00, }; static const double q2[] = { -5.5194330231005480228e-04, 3.2547697594819615062e-02, -1.1151759188741312645e+00, 1.3982595353892851542e+01, -6.0228002066743340583e+01, 8.5539563258012929600e+01, -3.1446690275135491500e+01, 1.0, }; double y, r, factor; if (x == 0) return 1.0; x = fabs(x); if (x <= 15) { y = x * x; return eval_poly(p1, FF_ARRAY_ELEMS(p1), y) / eval_poly(q1, FF_ARRAY_ELEMS(q1), y); } else { y = 1 / x - 1.0 / 15; r = eval_poly(p2, FF_ARRAY_ELEMS(p2), y) / eval_poly(q2, FF_ARRAY_ELEMS(q2), y); factor = exp(x) / sqrt(x); return factor * r; } }