/** * This code is available at * http://www.mindspring.com/~pfilandr/C/fs_math/ * and it is believed to be public domain. */ /* BEGIN fs_math.c */ #include "libs/fs_math.h" #include /* ** pi == (atan(1.0 / 3) + atan(1.0 / 2)) * 4 */ static double fs_pi(void); static long double fs_pil(void); double fs_sqrt(double x) { int n; double a, b; if (x > 0 && DBL_MAX >= x) { for (n = 0; x > 2; x /= 4) { ++n; } while (0.5 > x) { --n; x *= 4; } a = x; b = (1 + x) / 2; do { x = b; b = (a / x + x) / 2; } while (x > b); while (n > 0) { x *= 2; --n; } while (0 > n) { x /= 2; ++n; } } else { if (x != 0) { x = DBL_MAX; } } return x; } double fs_log(double x) { int n; double a, b, c, epsilon; static double A, B, C; static int initialized; if (x > 0 && DBL_MAX >= x) { if (!initialized) { initialized = 1; A = fs_sqrt(2); B = A / 2; C = fs_log(A); } for (n = 0; x > A; x /= 2) { ++n; } while (B > x) { --n; x *= 2; } a = (x - 1) / (x + 1); x = C * n + a; c = a * a; n = 1; epsilon = DBL_EPSILON * x; if (0 > a) { if (epsilon > 0) { epsilon = -epsilon; } do { n += 2; a *= c; b = a / n; x += b; } while (epsilon > b); } else { if (0 > epsilon) { epsilon = -epsilon; } do { n += 2; a *= c; b = a / n; x += b; } while (b > epsilon); } x *= 2; } else { x = -DBL_MAX; } return x; } double fs_log10(double x) { static double log_10; static int initialized; if (!initialized) { initialized = 1; log_10 = fs_log(10); } return x > 0 && DBL_MAX >= x ? fs_log(x) / log_10 : fs_log(x); } double fs_exp(double x) { unsigned n, square; double b, e; static double x_max, x_min, epsilon; static int initialized; if (!initialized) { initialized = 1; x_max = fs_log(DBL_MAX); x_min = fs_log(DBL_MIN); epsilon = DBL_EPSILON / 4; } if (x_max >= x && x >= x_min) { for (square = 0; x > 1; x /= 2) { ++square; } while (-1 > x) { ++square; x /= 2; } e = b = n = 1; do { b /= n++; b *= x; e += b; b /= n++; b *= x; e += b; } while (b > epsilon); while (square-- != 0) { e *= e; } } else { e = x > 0 ? DBL_MAX : 0; } return e; } double fs_modf(double value, double *iptr) { double a, b; const double c = value; if (0 > c) { value = -value; } if (DBL_MAX >= value) { for (*iptr = 0; value >= 1; value -= b) { a = value / 2; b = 1; while (a >= b) { b *= 2; } *iptr += b; } } else { *iptr = value; value = 0; } if (0 > c) { *iptr = -*iptr; value = -value; } return value; } double fs_fmod(double x, double y) { double a, b; const double c = x; if (0 > c) { x = -x; } if (0 > y) { y = -y; } if (y != 0 && DBL_MAX >= y && DBL_MAX >= x) { while (x >= y) { a = x / 2; b = y; while (a >= b) { b *= 2; } x -= b; } } else { x = 0; } return 0 > c ? -x : x; } double fs_pow(double x, double y) { double p = 0; if (0 > x && fs_fmod(y, 1) == 0) { if (fs_fmod(y, 2) == 0) { p = fs_exp(fs_log(-x) * y); } else { p = -fs_exp(fs_log(-x) * y); } } else { if (x != 0 || 0 >= y) { p = fs_exp(fs_log( x) * y); } } return p; } static double fs_pi(void) { unsigned n; double a, b, epsilon; static double p; static int initialized; if (!initialized) { initialized = 1; epsilon = DBL_EPSILON / 4; n = 1; a = 3; do { a /= 9; b = a / n; n += 2; a /= 9; b -= a / n; n += 2; p += b; } while (b > epsilon); epsilon = DBL_EPSILON / 2; n = 1; a = 2; do { a /= 4; b = a / n; n += 2; a /= 4; b -= a / n; n += 2; p += b; } while (b > epsilon); p *= 4; } return p; } double fs_cos(double x) { unsigned n; int negative, sine; double a, b, c; static double pi, two_pi, half_pi, third_pi, epsilon; static int initialized; if (0 > x) { x = -x; } if (DBL_MAX >= x) { if (!initialized) { initialized = 1; pi = fs_pi(); two_pi = 2 * pi; half_pi = pi / 2; third_pi = pi / 3; epsilon = DBL_EPSILON / 2; } if (x > two_pi) { x = fs_fmod(x, two_pi); } if (x > pi) { x = two_pi - x; } if (x > half_pi) { x = pi - x; negative = 1; } else { negative = 0; } if (x > third_pi) { x = half_pi - x; sine = 1; } else { sine = 0; } c = x * x; x = n = 0; a = 1; do { b = a; a *= c; a /= ++n; a /= ++n; b -= a; a *= c; a /= ++n; a /= ++n; x += b; } while (b > epsilon); if (sine) { x = fs_sqrt((1 - x) * (1 + x)); } if (negative) { x = -x; } } else { x = -DBL_MAX; } return x; } double fs_log2(double x) { static double log_2; static int initialized; if (!initialized) { initialized = 1; log_2 = fs_log(2); } return x > 0 && DBL_MAX >= x ? fs_log(x) / log_2 : fs_log(x); } double fs_exp2(double x) { static double log_2; static int initialized; if (!initialized) { initialized = 1; log_2 = fs_log(2); } return fs_exp(x * log_2); } long double fs_powl(long double x, long double y) { long double p; if (0 > x && fs_fmodl(y, 1) == 0) { if (fs_fmodl(y, 2) == 0) { p = fs_expl(fs_logl(-x) * y); } else { p = -fs_expl(fs_logl(-x) * y); } } else { if (x != 0 || 0 >= y) { p = fs_expl(fs_logl( x) * y); } else { p = 0; } } return p; } long double fs_sqrtl(long double x) { long int n; long double a, b; if (x > 0 && LDBL_MAX >= x) { for (n = 0; x > 2; x /= 4) { ++n; } while (0.5 > x) { --n; x *= 4; } a = x; b = (1 + x) / 2; do { x = b; b = (a / x + x) / 2; } while (x > b); while (n > 0) { x *= 2; --n; } while (0 > n) { x /= 2; ++n; } } else { if (x != 0) { x = LDBL_MAX; } } return x; } long double fs_logl(long double x) { long int n; long double a, b, c, epsilon; static long double A, B, C; static int initialized; if (x > 0 && LDBL_MAX >= x) { if (!initialized) { initialized = 1; B = 1.5; do { A = B; B = 1 / A + A / 2; } while (A > B); B /= 2; C = fs_logl(A); } for (n = 0; x > A; x /= 2) { ++n; } while (B > x) { --n; x *= 2; } a = (x - 1) / (x + 1); x = C * n + a; c = a * a; n = 1; epsilon = LDBL_EPSILON * x; if (0 > a) { if (epsilon > 0) { epsilon = -epsilon; } do { n += 2; a *= c; b = a / n; x += b; } while (epsilon > b); } else { if (0 > epsilon) { epsilon = -epsilon; } do { n += 2; a *= c; b = a / n; x += b; } while (b > epsilon); } x *= 2; } else { x = -LDBL_MAX; } return x; } long double fs_expl(long double x) { long unsigned n, square; long double b, e; static long double x_max, x_min, epsilon; static int initialized; if (!initialized) { initialized = 1; x_max = fs_logl(LDBL_MAX); x_min = fs_logl(LDBL_MIN); epsilon = LDBL_EPSILON / 4; } if (x_max >= x && x >= x_min) { for (square = 0; x > 1; x /= 2) { ++square; } while (-1 > x) { ++square; x /= 2; } e = b = n = 1; do { b /= n++; b *= x; e += b; b /= n++; b *= x; e += b; } while (b > epsilon); while (square-- != 0) { e *= e; } } else { e = x > 0 ? LDBL_MAX : 0; } return e; } static long double fs_pil(void) { long unsigned n; long double a, b, epsilon; static long double p; static int initialized; if (!initialized) { initialized = 1; epsilon = LDBL_EPSILON / 4; n = 1; a = 3; do { a /= 9; b = a / n; n += 2; a /= 9; b -= a / n; n += 2; p += b; } while (b > epsilon); epsilon = LDBL_EPSILON / 2; n = 1; a = 2; do { a /= 4; b = a / n; n += 2; a /= 4; b -= a / n; n += 2; p += b; } while (b > epsilon); p *= 4; } return p; } long double fs_cosl(long double x) { long unsigned n; int negative, sine; long double a, b, c; static long double pi, two_pi, half_pi, third_pi, epsilon; static int initialized; if (0 > x) { x = -x; } if (LDBL_MAX >= x) { if (!initialized) { initialized = 1; pi = fs_pil(); two_pi = 2 * pi; half_pi = pi / 2; third_pi = pi / 3; epsilon = LDBL_EPSILON / 2; } if (x > two_pi) { x = fs_fmodl(x, two_pi); } if (x > pi) { x = two_pi - x; } if (x > half_pi) { x = pi - x; negative = 1; } else { negative = 0; } if (x > third_pi) { x = half_pi - x; sine = 1; } else { sine = 0; } c = x * x; x = n = 0; a = 1; do { b = a; a *= c; a /= ++n; a /= ++n; b -= a; a *= c; a /= ++n; a /= ++n; x += b; } while (b > epsilon); if (sine) { x = fs_sqrtl((1 - x) * (1 + x)); } if (negative) { x = -x; } } else { x = -LDBL_MAX; } return x; } long double fs_fmodl(long double x, long double y) { long double a, b; const long double c = x; if (0 > c) { x = -x; } if (0 > y) { y = -y; } if (y != 0 && LDBL_MAX >= y && LDBL_MAX >= x) { while (x >= y) { a = x / 2; b = y; while (a >= b) { b *= 2; } x -= b; } } else { x = 0; } return 0 > c ? -x : x; } /* END fs_math.c */