HISTOGRAMS: Fix bin width problems on large numbers of bins
[pspp] / src / math / histogram.c
index ca2d9d7d20f1d93517bbaa71e2f36f7f9aa54791..afc40013e02865f46f82549599f4f9cb84812706 100644 (file)
@@ -140,29 +140,43 @@ adjust_bin_ranges (double bin_width, double min, double max, double *adj_min, do
   */
   if ( lower_limit % 2 == 0)
     {
-      if (upper_slack > lower_slack && upper_slack > half_bin_width)
+      /* If there is not enough slack at either end to perform a shift,
+         then we must extend the range so that there is.  We must extend
+         by two half bin widths in order to preserve the EVEN condition
+         established above.  Also, we extend on the end with the least
+         slack, in order to keep things as balanced as possible. */
+      if ( upper_slack > lower_slack && upper_slack <= half_bin_width)
         {
+          lower_limit -= 2;
+          lower_slack += 2 * half_bin_width;
+        }
+           
+      if (lower_slack > upper_slack && lower_slack < half_bin_width)
+        {
+          upper_limit += 2;
+          upper_slack += 2 * half_bin_width;
+        }
+
+      if (upper_slack > lower_slack)
+        {
+          assert (upper_slack > half_bin_width);
+
           /* Adjust the range to the left */
           lower_limit --;
           upper_limit --;
           upper_slack -= half_bin_width;
           lower_slack += half_bin_width;
         }
-      else if (lower_slack > upper_slack && lower_slack >= half_bin_width)
+      else
         {
+          assert (lower_slack >= half_bin_width);
+
           /* Adjust the range to the right */
           lower_limit ++;
           upper_limit ++;
           lower_slack -= half_bin_width;
           upper_slack += half_bin_width;
         }
-      else
-        {
-          /* In this case, we cannot adjust in either direction.
-             To get the most pleasing alignment, we would have to change
-             the bin width (which would have other visual disadvantages).
-          */
-        }
     }
 
   /* If there are any completely empty bins, then remove them,
@@ -208,12 +222,14 @@ histogram_create (double bin_width, double min, double max)
 
   assert (bin_width > 0);
 
+  bin_width = chart_rounded_tick (bin_width);
   bins = adjust_bin_ranges (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),
+      bin_width = chart_rounded_tick ((max - min) / (double) (MAX_BINS - 1));
+      bins = adjust_bin_ranges (bin_width,
                                 min, max, &adjusted_min, &adjusted_max);
     }