1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66
|
/*
* precision.c
*
* This file contains the functions
*
* int decimal_places_of_accuracy(double x, double y);
* int complex_decimal_places_of_accuracy(Complex x, Complex y);
*
* which are used within the kernel to determine how many decimal
* places of accuracy the doubles (resp. Complexes) x and y have in common.
* Typically x and y will be two estimates of the same computed quantity
* (e.g. the volume of a manifold as computed at the last and the
* next-to-the-last iterations of Newton's method in
* hyperbolic_structures.c), and decimal_places_of_accuracy()
* will be used to tell the user interface how many decimal places
* should be printed. We compute the number of decimal places of
* accuracy instead of the number of significant figures, because
* this is what printf() requires in its formatting string.
*/
#include "kernel.h"
int decimal_places_of_accuracy(
double x,
double y)
{
int digits;
if (x == y)
{
if (x == 0.0)
digits = DBL_DIG;
else
digits = DBL_DIG - (int) ceil(log10(fabs(x)));
}
else
digits = - (int) ceil(log10(fabs(x - y)));
/*
* Typically the difference between the computed values
* of a quantity at the penultimate and ultimate iterations
* of Newton's method is a little less than the true error.
* So we fudge a bit.
*/
digits -= 4;
if (digits < 0)
digits = 0;
return digits;
}
int complex_decimal_places_of_accuracy(
Complex x,
Complex y)
{
int real_precision,
imag_precision;
real_precision = decimal_places_of_accuracy(x.real, y.real);
imag_precision = decimal_places_of_accuracy(x.imag, y.imag);
return MIN(real_precision, imag_precision);
}
|