X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=src%2Fmath%2Fhistogram.c;h=3c324eff2485d583c3cff0c72e49c137c98aecca;hb=3380cd42c3831b98b71709a0c1fcb175e3e4a5d9;hp=7fc2d08e3de341a49455e0395d7283e204384f79;hpb=cdae9856ee4695fef212a4dcf24d81dff484c7d4;p=pspp diff --git a/src/math/histogram.c b/src/math/histogram.c index 7fc2d08e3d..3c324eff24 100644 --- a/src/math/histogram.c +++ b/src/math/histogram.c @@ -17,10 +17,12 @@ #include #include "math/histogram.h" +#include "math/decimal.h" #include #include +#include "data/settings.h" #include "libpspp/message.h" #include "libpspp/assertion.h" #include "libpspp/cast.h" @@ -84,6 +86,10 @@ double get_slack (double limit, double half_bin_width, int *n_half_bins) ADJ_MIN and ADJ_MAX are locations of the adjusted values of MIN and MAX (the range will always be equal or slightly larger). Returns the number of bins. + + The "testing_assert" expressions in this function should be algebraically correct. + However, due to floating point rounding they could fail, especially when small numbers + are involved. In normal use, therefore, testing_assert does nothing. */ static int adjust_bin_ranges (double bin_width, double min, double max, double *adj_min, double *adj_max) @@ -97,7 +103,7 @@ adjust_bin_ranges (double bin_width, double min, double max, double *adj_min, do double lower_slack = get_slack (min, half_bin_width, &lower_limit); double upper_slack = -get_slack (max, half_bin_width, &upper_limit); - assert (max > min); + testing_assert (max > min); /* If min is negative, then lower_slack may be less than zero. In this case, the lower bound must be extended in the negative direction @@ -108,7 +114,7 @@ adjust_bin_ranges (double bin_width, double min, double max, double *adj_min, do lower_limit--; lower_slack += half_bin_width; } - assert (lower_limit * half_bin_width <= min); + testing_assert (lower_limit * half_bin_width <= min); /* However, the upper bound must be extended regardless, because histogram bins span the range [lower, upper). In other words, the upper bound must be @@ -116,7 +122,7 @@ adjust_bin_ranges (double bin_width, double min, double max, double *adj_min, do */ upper_limit++;; upper_slack += half_bin_width; - assert (upper_limit * half_bin_width > max); + testing_assert (upper_limit * half_bin_width > max); /* The range must be an EVEN number of half bin_widths */ if ( (upper_limit - lower_limit) % 2) @@ -159,7 +165,7 @@ adjust_bin_ranges (double bin_width, double min, double max, double *adj_min, do if (upper_slack > lower_slack) { - assert (upper_slack > half_bin_width); + testing_assert (upper_slack > half_bin_width); /* Adjust the range to the left */ lower_limit --; @@ -169,7 +175,7 @@ adjust_bin_ranges (double bin_width, double min, double max, double *adj_min, do } else { - assert (lower_slack >= half_bin_width); + testing_assert (lower_slack >= half_bin_width); /* Adjust the range to the right */ lower_limit ++; @@ -197,8 +203,8 @@ adjust_bin_ranges (double bin_width, double min, double max, double *adj_min, do *adj_min = lower_limit * half_bin_width; *adj_max = upper_limit * half_bin_width; - assert (*adj_max > max); - assert (*adj_min <= min); + testing_assert (*adj_max > max); + testing_assert (*adj_min <= min); return (upper_limit - lower_limit) / 2.0; } @@ -206,8 +212,9 @@ adjust_bin_ranges (double bin_width, double min, double max, double *adj_min, do struct histogram * -histogram_create (double bin_width, double min, double max) +histogram_create (double bin_width_in, double min, double max) { + struct decimal bin_width; const int MAX_BINS = 25; struct histogram *h; struct statistic *stat; @@ -220,14 +227,17 @@ histogram_create (double bin_width, double min, double max) return NULL; } - assert (bin_width > 0); + assert (bin_width_in > 0); - bins = adjust_bin_ranges (bin_width, min, max, &adjusted_min, &adjusted_max); + chart_rounded_tick (bin_width_in, &bin_width); + bins = adjust_bin_ranges (decimal_to_double (&bin_width), + min, max, &adjusted_min, &adjusted_max); /* Force the number of bins to lie in a sensible range. */ if (bins > MAX_BINS) { - bins = adjust_bin_ranges ((max - min) / (double) (MAX_BINS - 1), + chart_rounded_tick ((max - min) / (double) (MAX_BINS - 1), &bin_width); + bins = adjust_bin_ranges (decimal_to_double (&bin_width), min, max, &adjusted_min, &adjusted_max); }