#include "nr.h" #include #include void get_eps(float *eps) { *eps = 1.0f; while ((1.0f + *eps / 2.0f) > 1.0f) { *eps /= 2.0f; } } void get_eps_double(double *eps) { *eps = 1.0; while ((1.0 + *eps / 2.0) > 1.0) { *eps /= 2.0; } } #define CONV(i) ((double) (i)) void machar_double(int *ibeta, int *it, int *irnd, int *ngrd, int *machep, int *negep, int *iexp, int *minexp, int *maxexp, double *eps, double *epsneg, double *xmin, double *xmax) { int i, itemp, iz, j, k, mx, nxres; double a, b, beta, betah, betain, one, t, temp, temp1, tempa, two, y, z, zero; one = CONV(1); two = one + one; zero = one - one; a = one; do { a += a; temp = a + one; temp1 = temp - a; } while (temp1 - one == zero); b = one; do { b += b; temp = a + b; itemp = (int) (temp - a); } while (itemp == 0); *ibeta = itemp; beta = CONV(*ibeta); *it = 0; b = one; do { ++(*it); b *= beta; temp = b + one; temp1 = temp - b; } while (temp1 - one == zero); *irnd = 0; betah = beta / two; temp = a + betah; if (temp - a != zero) *irnd = 1; tempa = a + beta; temp = tempa + betah; if (*irnd == 0 && temp - tempa != zero) *irnd = 2; *negep = (*it) + 3; betain = one / beta; a = one; for (i = 1; i <= (*negep); i++) a *= betain; b = a; for (;;) { temp = one - a; if (temp - one != zero) break; a *= beta; --(*negep); } *negep = -(*negep); *epsneg = a; *machep = -(*it) - 3; a = b; for (;;) { temp = one + a; if (temp - one != zero) break; a *= beta; ++(*machep); } *eps = a; *ngrd = 0; temp = one + (*eps); if (*irnd == 0 && temp * one - one != zero) *ngrd = 1; i = 0; k = 1; z = betain; t = one + (*eps); nxres = 0; for (;;) { y = z; z = y * y; a = z * one; temp = z * t; if (a + a == zero || fabs(z) >= y) break; temp1 = temp * betain; if (temp1 * beta == z) break; ++i; k += k; } if (*ibeta != 10) { *iexp = i + 1; mx = k + k; } else { *iexp = 2; iz = (*ibeta); while (k >= iz) { iz *= *ibeta; ++(*iexp); } mx = iz + iz - 1; } for (;;) { *xmin = y; y *= betain; a = y * one; temp = y * t; if (a + a != zero && fabs(y) < *xmin) { ++k; temp1 = temp * betain; if (temp1 * beta == y && temp != y) { nxres = 3; *xmin = y; break; } } else break; } *minexp = -k; if (mx <= k + k - 3 && *ibeta != 10) { mx += mx; ++(*iexp); } *maxexp = mx + (*minexp); *irnd += nxres; if (*irnd >= 2) *maxexp -= 2; i = (*maxexp) + (*minexp); if (*ibeta == 2 && !i) --(*maxexp); if (i > 20) --(*maxexp); if (a != y) *maxexp -= 2; *xmax = one - (*epsneg); if ((*xmax) * one != *xmax) *xmax = one - beta * (*epsneg); *xmax /= (*xmin * beta * beta * beta); i = (*maxexp) + (*minexp) + 3; for (j = 1; j <= i; j++) { if (*ibeta == 2) *xmax += *xmax; else *xmax *= beta; } } #undef CONV int main() { int ibeta, it, irnd, ngrd, machep, negep, iexp, minexp, maxexp; float eps, epsneg, xmin, xmax; machar(&ibeta, &it, &irnd, &ngrd, &machep, &negep, &iexp, &minexp, &maxexp, &eps, &epsneg, &xmin, &xmax); printf("Machine Accuracy for float (machar): \t\t%0.20f\n", eps); get_eps(&eps); printf("Machine Accuracy for float (get_eps): \t\t%0.20f\n", eps); double eps_double, epsneg_double, xmin_double, xmax_double; machar_double(&ibeta, &it, &irnd, &ngrd, &machep, &negep, &iexp, &minexp, &maxexp, &eps_double, &epsneg_double, &xmin_double, &xmax_double); printf("Machine Accuracy for double (machar_double): \t%0.20f\n", eps_double); get_eps_double(&eps_double); printf("Machine Accuracy for double (get_eps_double): \t%0.20f\n", eps_double); return 0; }