replaced decimal module, xrchart_scale with autoformat, histogram x-axis ticks changed.
authorFriedrich Beckmann <friedrich.beckmann@gmx.de>
Sun, 7 Jun 2015 21:10:07 +0000 (23:10 +0200)
committerFriedrich Beckmann <friedrich.beckmann@gmx.de>
Thu, 11 Jun 2015 12:24:19 +0000 (14:24 +0200)
During gtk3 osx debugging the decimal unit crashed. I replaced the decimal computations
with traditional tick interval computation plus a printf format string generation which is
adapted to the chosen tick style.

The xrchart scales writing are adapted to use this mechanism. If the tick text is too long
to fit in the interval, then the tick label uses the existing rotation by 45 degrees. I added
some space below the x-axis to make the tick labels visible. Maybe the tick label placement
could also be done in two rows for the even and odd ticks.

The histogram x-axis tick generation is changed from a tick per bin to the usual
normal x-axis tick generation. This allows easier visual bin border identification.
The bin width is adapted to the chosen x-axis tick scale. Any number of bins can now
be visualized. This is according to the spss examples I found for the histograms.

Conflicts:
src/output/cairo-chart.c

16 files changed:
src/math/automake.mk
src/math/chart-geometry.c
src/math/chart-geometry.h
src/math/decimal.c [deleted file]
src/math/decimal.h [deleted file]
src/math/histogram.c
src/output/cairo-chart.c
src/output/cairo-chart.h
src/output/charts/plot-hist-cairo.c
tests/automake.mk
tests/math/chart-geometry-test.c [deleted file]
tests/math/chart-geometry.at
tests/math/chart-get-scale-test.c
tests/math/chart-get-ticks-format-test.c
tests/math/decimal-test.c [deleted file]
tests/math/decimal.at [deleted file]

index f40aac57e1222cf807d1c3e7ada2403d63c842e5..cdcc2c8cb79355d6434a32a6019f21aa6edc3851 100644 (file)
@@ -17,7 +17,6 @@ src_math_libpspp_math_la_SOURCES = \
        src/math/covariance.h \
        src/math/correlation.c \
        src/math/correlation.h \
-       src/math/decimal.c src/math/decimal.h \
        src/math/extrema.c src/math/extrema.h \
        src/math/histogram.c src/math/histogram.h \
        src/math/interaction.c src/math/interaction.h \
index 49b1ed6a8d243341d768e9d9b0695f4a2804de8f..1265a61eb872a1713813d406ba80096251acb916 100644 (file)
@@ -20,7 +20,6 @@
 #include <assert.h>
 
 #include "chart-geometry.h"
-#include "decimal.h"
 #include <stdlib.h>
 
 #include "gl/xalloc.h"
 
 static const double standard_tick[] = {1, 2, 5, 10};
 
-/* Adjust tick to be a sensible value
-   ie:  ... 0.1,0.2,0.5,   1,2,5,  10,20,50 ... */
-void
-chart_rounded_tick (double tick, struct decimal *result)
-{
-  int i;
-
-  struct decimal ddif = {1, 1000};
-
-  /* Avoid arithmetic problems with very small values */
-  if (fabs (tick) < DBL_EPSILON)
-    {
-      result->ordinate = 0;
-      result->mantissa = 0;
-      return;
-    }
-
-  struct decimal dt;
-  decimal_from_double (&dt, tick);
-  
-  double expd = dec_log10 (&dt) - 1;
-
-  for (i = 0  ; i < 4 ; ++i)
-    {
-      struct decimal candidate;
-      struct decimal delta;
-
-      decimal_init (&candidate, standard_tick[i], expd);
-      
-      delta = dt;
-      decimal_subtract (&delta, &candidate);
-      delta.ordinate = llabs (delta.ordinate);
-
-      if (decimal_cmp (&delta, &ddif) < 0)
-       {
-         ddif = delta;
-         *result = candidate;
-       }
-    }
-}
-
 /* 
    Find a set {LOWER, INTERVAL, N_TICKS} such that:
 
@@ -92,73 +50,48 @@ chart_rounded_tick (double tick, struct decimal *result)
         ^LOWDBL                 ^HIGHDBL
 */
 void
-chart_get_scale (double highdbl, double lowdbl,
-                struct decimal *lower, 
-                struct decimal *interval,
+chart_get_scale (double high, double low,
+                double *lower, double *interval,
                 int *n_ticks)
 {
   int i;
   double fitness = DBL_MAX;
+  double logrange;
   *n_ticks = 0;
-  struct decimal high;
-  struct decimal low;
 
-  assert (highdbl >= lowdbl);
+  assert (high >= low);
 
-  decimal_from_double (&high, highdbl);
-  decimal_from_double (&low, lowdbl);
-  
-  struct decimal diff = high;
-  decimal_subtract (&diff, &low);
+  if ((high - low) < 10 * DBL_MIN) {
+    *n_ticks = 0;
+    *lower = low;
+    *interval = 0.0;
+    return;
+  }
 
-  double expd = dec_log10 (&diff) - 2;
+  logrange = floor(log10(high-low));
 
   /* Find the most pleasing interval */
   for (i = 1; i < 4; ++i)
     {
-      struct decimal clbound = low;
-      struct decimal cubound = high;
-      struct decimal candidate;
-      decimal_init (&candidate, standard_tick[i], expd);
-
-      decimal_divide (&clbound, &candidate);
-      int fl = decimal_floor (&clbound);
-      decimal_int_multiply (&candidate, fl);
-      clbound = candidate;
-
-
-      decimal_init (&candidate, standard_tick[i], expd);
-      decimal_divide (&cubound, &candidate);
-      int fu = decimal_ceil (&cubound);
-      decimal_int_multiply (&candidate, fu);
-
-      cubound = candidate;
-
-      decimal_init (&candidate, standard_tick[i], expd);
-      decimal_subtract (&cubound, &clbound);
-      decimal_divide (&cubound, &candidate);
-
-
-      ord_t n_int = decimal_floor (&cubound);
-
-      /* We prefer to have between 5 and 10 tick marks on a scale */
-      double f = 1 - exp (-0.2 *  fabs (n_int - 7.5) / 7.5);
-
-      if (f < fitness)
-       {
-         fitness = f;
-         *lower = clbound;
-         *interval = candidate;
-         *n_ticks = n_int;
-       }
+      double cinterval = standard_tick[i] * pow(10.0,logrange-1);
+      double clower = floor(low/cinterval) * cinterval;
+      int cnticks = ceil((high - clower) / cinterval)-1;
+      double cfitness = fabs(7.5 - cnticks);
+
+      if (cfitness < fitness) {
+       fitness = cfitness;
+       *lower = clower;
+       *interval = cinterval;
+       *n_ticks = cnticks;
+      }
     }
 }
 
 /*
  * Compute the optimum format string and the scaling
  * for the tick drawing on a chart axis
- * Input:  max:     the maximum value of the range
- *         min:     the minimum value of the range
+ * Input:  lower:   the lowest tick
+ *         interval:the interval between the ticks
  *         nticks:  the number of tick intervals (bins) on the axis
  * Return: fs:      format string for printf to print the tick value
  *         scale:   scaling factor for the tick value
@@ -167,17 +100,15 @@ chart_get_scale (double highdbl, double lowdbl,
  * Non Scientific: "%.3lf", scale=1.00
  * Scientific:     "%.2lfe3", scale = 0.001
  * Usage example:
- *   fs = chart_get_ticks_format(95359943.3,34434.9,8,&scale);
+ *   fs = chart_get_ticks_format(-0.7,0.1,8,&scale);
  *   printf(fs,value*scale);
  *   free(fs);
  */
 char *
-chart_get_ticks_format (const double max, const double min,
+chart_get_ticks_format (const double lower, const double interval,
                        const unsigned int nticks, double *scale)
 {
-  assert(max > min);
-  double interval = (max - min)/nticks;
-  double logmax = log10(fmax(fabs(max),fabs(min)));
+  double logmax = log10(fmax(fabs(lower + (nticks+1)*interval),fabs(lower)));
   double logintv = log10(interval);
   int logshift = 0;
   char *format_string = NULL;
@@ -185,13 +116,16 @@ chart_get_ticks_format (const double max, const double min,
 
   if (logmax > 0.0 && logintv < 0.0)
     {
-      nrdecs = MIN(6,(int)(fabs(logintv))+1);
+      nrdecs = MIN(6,(int)(ceil(fabs(logintv))));
       logshift = 0;
-      format_string = xasprintf("%%.%dlf",nrdecs);
+      if (logmax < 12.0)
+       format_string = xasprintf("%%.%dlf",nrdecs);
+      else
+       format_string = xasprintf("%%lg");
     }
   else if (logmax > 0.0) /*logintv is > 0*/
     {
-      if (logintv < 5.0)
+      if (logintv < 5.0 && logmax < 10.0)
        {
          logshift = 0; /* No scientific format */
          nrdecs = 0;
@@ -200,23 +134,26 @@ chart_get_ticks_format (const double max, const double min,
       else
        {
          logshift = (int)logmax;
-         nrdecs = MIN(6,(int)(logmax-logintv)+1);
-         format_string = xasprintf("%%.%dlf&#8729;10<sup>%d</sup>",nrdecs,logshift);
+         /* Possible intervals are 0.2Ex, 0.5Ex, 1.0Ex                    */
+         /* log10(0.2E9) = 8.30, log10(0.5E9) = 8.69, log10(1.0E9) = 9    */
+         /* 0.2 and 0.5 need one decimal more. For stability subtract 0.1 */
+         nrdecs = MIN(8,(int)(ceil(logshift-logintv-0.1)));
+         format_string = xasprintf("%%.%dlf&#8901;10<sup>%d</sup>",nrdecs,logshift);
        }
     }
   else /* logmax and logintv are < 0 */
     {
-      if (logmax > -4.0)
+      if (logmax > -3.0)
        {
          logshift = 0; /* No scientific format */
-         nrdecs = (int)(-logintv) + 1;
+         nrdecs = MIN(8,(int)(ceil(-logintv)));
          format_string = xasprintf("%%.%dlf",nrdecs);
        }
       else
        {
          logshift = (int)logmax-1;
-         nrdecs = MIN(6,(int)(logmax-logintv)+1);
-         format_string = xasprintf("%%.%dlf&#8729;10<sup>%d</sup>",nrdecs,logshift);
+         nrdecs = MIN(8,(int)(ceil(logshift-logintv-0.1)));
+         format_string = xasprintf("%%.%dlf&#8901;10<sup>%d</sup>",nrdecs,logshift);
        }
     }
   *scale = pow(10.0,-(double)logshift);
index 67d35bb62fe423afcd248859c1db5e119c00ff39..3d3955e75eadbe51ca692a4e5bffe5950b95c95e 100644 (file)
 #ifndef CHART_GEOMETRY_H
 #define CHART_GEOMETRY_H
 
-struct decimal;
-void chart_rounded_tick (double tick, struct decimal *);
-
 void chart_get_scale (double high, double low,
-                     struct decimal *lower, struct decimal *interval, int *n_ticks);
+                     double *lower, double *interval, int *n_ticks);
 
 char *
-chart_get_ticks_format (const double max, const double min, const unsigned int nticks,
+chart_get_ticks_format (const double lower, const double interval, const unsigned int nticks,
                        double *scale);
 
 #endif
diff --git a/src/math/decimal.c b/src/math/decimal.c
deleted file mode 100644 (file)
index 0655834..0000000
+++ /dev/null
@@ -1,572 +0,0 @@
-/* PSPP - a program for statistical analysis.
-   Copyright (C) 2015 Free Software Foundation, Inc.
-
-   This program is free software: you can redistribute it and/or modify
-   it under the terms of the GNU General Public License as published by
-   the Free Software Foundation, either version 3 of the License, or
-   (at your option) any later version.
-
-   This program is distributed in the hope that it will be useful,
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-   GNU General Public License for more details.
-
-   You should have received a copy of the GNU General Public License
-   along with this program.  If not, see <http://www.gnu.org/licenses/>. */
-
-
-#include <config.h>
-#include <stdio.h>
-#include <stdint.h>
-#include <string.h>
-#include <limits.h>
-#include <assert.h>
-#include <stdlib.h>
-#include <stdbool.h>
-#include <math.h>
-#include "libpspp/i18n.h"
-
-#include "decimal.h"
-
-int dec_warning;
-
-static bool
-down (struct decimal *dec)
-{
-  if (dec->ordinate % 10 == 0 &&  dec->mantissa < MANT_MAX - 1)
-    {
-      dec->ordinate /= 10;
-      dec->mantissa++;
-      return true;
-    }
-  
-  return false;
-}
-
-static bool
-up (struct decimal *dec)
-{
-  if (llabs (dec->ordinate) < ORD_MAX / 10   &&   dec->mantissa > MANT_MIN)
-    {
-      dec->ordinate *= 10;
-      dec->mantissa--;
-      return true;
-    }
-  return false;
-}
-
-
-/* Reduce the absolute value of the ordinate to the smallest possible,
-   without loosing precision */
-static void 
-reduce (struct decimal *dec)
-{
-  if (dec->ordinate == 0)
-    {
-      dec->mantissa = 0;
-      return;
-    }
-    
-  while (dec->ordinate % 10 == 0)
-    {
-      if (! down (dec))
-       break;
-    }
-}
-
-/* Attempt to make the mantissas of BM and SM equal.
-   Prerequisite: the mantissa SM must be no greater than that of BM.
- */
-static void 
-normalisebs (struct decimal *sm, struct decimal *bm)
-{
-  while (sm->mantissa < bm->mantissa)
-    {
-      if (down (sm))
-       ;
-      else if (up (bm))
-       ;
-      else
-       {
-         dec_warning = DEC_PREC;
-         break;
-       }
-    }
-
-  while (sm->mantissa < bm->mantissa)
-    {
-      sm->ordinate /= 10;
-      sm->mantissa++;
-    }
-}
-
-
-/* arrange d1 and d2 such that thier mantissas are equal */
-void 
-normalise (struct decimal *d1, struct decimal *d2)
-{
-  normalisebs (d1, d2);
-  normalisebs (d2, d1);
-}
-
-
-
-/* Return log base 10 of D */
-mant_t 
-dec_log10 (const struct decimal *d_)
-{
-  struct decimal d = *d_;
-
-  while (llabs (d.ordinate) > 0)
-    {
-      d.ordinate /= 10;
-      d.mantissa++;
-    }
-
-  return d.mantissa;
-}
-
-
-
-/* Return the smallest integer >= d */
-static ord_t
-decimal_ceil_pos (const struct decimal *d)
-{
-  mant_t m = d->mantissa;
-  ord_t o = d->ordinate;
-
-  assert (d->ordinate >= 0);
-  
-  while (m > 0)
-    {
-      o *= 10;
-      m--;
-    }
-
-  while (m < 0)
-    {
-      bool flag = o % 10;
-      o /= 10;
-      if (flag)
-       o++;
-      m++;
-    }
-
-  return o;
-}
-
-/* Return the largest integer <= d */
-static ord_t
-decimal_floor_pos (const struct decimal *d)
-{
-  mant_t m = d->mantissa;
-  ord_t o = d->ordinate;
-
-  assert (d->ordinate >= 0);
-
-  while (m > 0)
-    {
-      m--;
-      o *= 10;
-    }
-
-  while (m < 0)
-    {
-      m++;
-      o /= 10;
-    }
-  
-
-  return o;
-}
-
-/* Return the smallest integer which is no less than D.
-   (round towards minus infinity) */
-ord_t
-decimal_floor (const struct decimal *d)
-{
-  if (d->ordinate >= 0)
-    return decimal_floor_pos (d);
-  else
-    {
-      struct decimal dd = *d;
-      dd.ordinate = llabs (dd.ordinate);
-      return -decimal_ceil_pos (&dd);
-    }
-}
-
-/* Return the largest integer which is no greater than D.
-   (round towards plus infinity) */
-ord_t
-decimal_ceil (const struct decimal *d)
-{
-  if (d->ordinate >= 0)
-    return decimal_ceil_pos (d);
-  else
-    {
-      struct decimal dd = *d;
-      dd.ordinate = llabs (dd.ordinate);
-      return -decimal_floor_pos (&dd);
-    }
-}
-
-/* Add SRC onto DEST */
-void
-decimal_add (struct decimal *dest, const struct decimal *src_)
-{
-  struct decimal src = *src_;
-
-  src.ordinate = -src.ordinate;
-
-  decimal_subtract (dest, &src);
-}
-
-/* Subtract SRC from DEST */
-void
-decimal_subtract (struct decimal *dest, const struct decimal *src_)
-{
-  struct decimal src = *src_;
-
-  normalise (dest, &src);
-
-  bool dest_neg = dest->ordinate < 0;
-  bool src_neg = src.ordinate < 0;
-
-  bool expected_neg = dest_neg * src_neg;
-  
-  if (dest->ordinate == src.ordinate)
-    {
-      expected_neg = 0;
-    }
-  else if (llabs (src.ordinate) > llabs (dest->ordinate))
-    {
-      if (dest_neg == src_neg)
-       expected_neg = !expected_neg;
-    }
-
-  dest->ordinate -= src.ordinate;
-
-  bool result_neg = dest->ordinate < 0;
-
-  if (expected_neg != result_neg)
-    {
-      /* The operation has resulted in an overflow.
-        To resolve this, undo the operation, 
-        reduce the precision and try again */
-
-      dest->ordinate += src.ordinate;
-
-      dest->ordinate /= 10;
-      src.ordinate /= 10;
-
-      dest->mantissa ++;
-      src.mantissa ++;
-
-      dest->ordinate -= src.ordinate;
-    }
-
-  reduce (dest);
-
-}
-
-/* Initialise DEC with ordinate ORD and mantissa MANT */
-void
-decimal_init (struct decimal *dec, ord_t ord, mant_t mant)
-{
-  dec->ordinate = ord;
-  dec->mantissa = mant;
-  reduce (dec);
-}
-
-
-/*
-  Compare D1 and D2.
-
-  Returns zero if equal, +1 if D1 > D2 and -1 if D1 < D2
-*/
-int
-decimal_cmp (const struct decimal *d1, const struct decimal *d2)
-{
-  struct decimal td1 = *d1;
-  struct decimal td2 = *d2;
-  
-  normalise (&td1, &td2);
-
-  if (td1.ordinate < td2.ordinate)
-    return -1;
-
-  return (td1.ordinate > td2.ordinate);
-}
-
-
-/* Multiply DEST by M */
-void
-decimal_int_multiply (struct decimal *dest, ord_t m)
-{
-  if (m != 0)
-    while (llabs (dest->ordinate) > llabs (ORD_MAX / m))
-      {
-        dest->ordinate /= 10;
-        dest->mantissa++;
-      }
-
-  dest->ordinate *= m;
-
-  reduce (dest);
-}
-
-
-/* Divide DEST by M */
-void
-decimal_int_divide (struct decimal *dest, ord_t m)
-{
-  while (dest->ordinate % m)
-    {
-      if (labs (dest->ordinate) > ORD_MAX / 10)
-       {
-         dec_warning = DEC_PREC;
-         break;
-       }
-      up (dest);
-    }
-  dest->ordinate /= m;
-}
-
-/* Divide DEST by SRC */
-void
-decimal_divide (struct decimal *dest, const struct decimal *src)
-{
-  while (dest->ordinate % src->ordinate)
-    {
-      if (labs (dest->ordinate) > ORD_MAX / 10)
-       {
-         dec_warning = DEC_PREC;
-         break;
-       }
-      up (dest);
-    }
-
-  dest->ordinate /= src->ordinate;
-  dest->mantissa -= src->mantissa;
-}
-
-/* Print the value of DEC to F.  Probably useful only for debugging */
-void
-decimal_show (const struct decimal *dec, FILE *f)
-{
-  fprintf (f, PR_ORD " x 10^" PR_MANT "\n", dec->ordinate, dec->mantissa);
-}
-
-
-/* Reverse the characters in string S which has length LEN */
-static void 
-reverse (char *s, int len)
-{
-  int i;
-  for (i = 0; i < len / 2; ++i)
-    {
-      char temp = s[len - i - 1];
-      s[len - i - 1] = s[i];
-      s[i] = temp;
-    }
-}
-
-/* Return a string representation of DEC on the heap.
-   The caller is responsible for freeing the string */
-char *
-decimal_to_string (const struct decimal *dec)
-{
-  int cap = 16;
-  int len = 0;
-  char *s = calloc (cap, 1);
-  ord_t ordinate = dec->ordinate;
-
-  while (len < dec->mantissa)
-    {
-      s[len++] = '0';
-      if (len >= cap) s = realloc (s, cap <<= 1);
-    }
-
-  while (ordinate)
-    {
-      s[len++] = labs (ordinate % 10) + '0';
-      if (len >= cap) s = realloc (s, cap <<= 1);
-      ordinate /= 10;
-    }
-
-  if (ordinate < 0)
-      ordinate = -ordinate;
-
-  while (len < -dec->mantissa)
-    {
-      s[len++] = '0';
-      if (len >= cap) s = realloc (s, cap <<= 1);
-    }
-
-  if (dec->mantissa < 0 )
-    {
-      if (len <= -dec->mantissa)
-       {
-         s[len++] = get_system_decimal ();
-         if (len >= cap) s = realloc (s, cap <<= 1);
-         s[len++] = '0';
-         if (len >= cap) s = realloc (s, cap <<= 1);
-       }
-      else
-       {
-         int i;
-         if (len >= cap) s = realloc (s, cap <<= 1);
-         for (i = len - 1 ; i >= -dec->mantissa ; --i)
-           s[i + 1] = s[i];
-         s[i + 1] = get_system_decimal ();
-         len++;
-       }
-    }
-
-  if (dec->ordinate < 0)
-    {
-      s[len++] = '-';
-      if (len >= cap) s = realloc (s, cap <<= 1);
-    }
-
-
-  reverse (s, len);
-
-  {
-    int abs_len = len;
-    if (dec->ordinate < 0)
-      abs_len--;
-
-    while (abs_len++ <= dec->mantissa)
-      {
-       s[len++] = '0';
-       if (len >= cap) s = realloc (s, cap <<= 1);
-      }
-  }
-  
-  return s;
-}
-
-
-/* Initialise DECIMAL from INPUT.
-   INPUT should be a convential decimal representation.
- */
-void
-decimal_init_from_string (struct decimal *decimal, const char *input)
-{
-  ord_t ordinate = 0;
-
-  int point = -1;
-  int lsd = -1;
-  int fsd = -1;
-  int i = 0;
-  int len = 0;
-  int sign = 1;
-
-  const char *p;
-
-  for (p = input; *p ; p++)
-    {
-      if (*p == '-')
-       {
-         sign = -1;
-       }
-      else if (*p == get_system_decimal ())
-       {
-         assert (point == -1);
-         point = i;
-       }
-      else if (*p > '0' && *p <= '9')
-       {
-         lsd = i;
-         if (fsd == -1)
-           fsd = i;
-       }
-      else if (*p == '0')
-       /* ignore */
-       ;
-      else 
-       {
-         fprintf (stderr, "Error: invalid character %c\n", *p);
-         return;
-       }
-
-      i++;
-    }
-  len = i;
-
-  if (point == -1)
-    point = len;
-
-  mant_t mantissa = 0;
-  if (fsd >= 0)
-    {
-      mant_t m = 1;
-      for (i = lsd ; i >= fsd ; --i)
-       {
-         if (input[i] != get_system_decimal ())
-           {
-             if (ordinate > ORD_MAX - m * (input[i] - '0'))
-               {
-                 fprintf (stderr, "Overflow reading value %s\n", input);
-                 break;
-               }
-             ordinate += m * (input[i] - '0');
-             m *= 10;
-           }
-       }
-
-      if (lsd > point)
-       mantissa = point - lsd;
-      else
-       mantissa = point - lsd - 1;
-    }
-
-  decimal->ordinate = ordinate * sign;
-  decimal->mantissa = mantissa;
-}
-
-
-
-/* Initialise DEC from the binary fp value X */
-void 
-decimal_from_double (struct decimal *dec, double x)
-{
-  dec->mantissa = 0;
-
-  while (trunc (x) != x)
-    {
-      if (fabs (x) > ORD_MAX / 10.0)
-       {
-         dec_warning = DEC_PREC;
-         break;
-       }
-      x *= 10.0;
-      dec->mantissa--;
-    }
-
-  dec->ordinate = x;
-}
-
-/* Return a binary floating point value 
-   approximating DEC */
-double
-decimal_to_double (const struct decimal *dec)
-{
-  double x = dec->ordinate;
-  int mult = dec->mantissa;
-
-  while (mult < 0)
-    {
-      x /= 10.0;
-      mult++;
-    }
-
-  while (mult > 0)
-    {
-      x *= 10.0;
-      mult--;
-    }
-
-  return x;
-}
diff --git a/src/math/decimal.h b/src/math/decimal.h
deleted file mode 100644 (file)
index b5740f6..0000000
+++ /dev/null
@@ -1,114 +0,0 @@
-/* PSPP - a program for statistical analysis.
-   Copyright (C) 2015 Free Software Foundation, Inc.
-
-   This program is free software: you can redistribute it and/or modify
-   it under the terms of the GNU General Public License as published by
-   the Free Software Foundation, either version 3 of the License, or
-   (at your option) any later version.
-
-   This program is distributed in the hope that it will be useful,
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-   GNU General Public License for more details.
-
-   You should have received a copy of the GNU General Public License
-   along with this program.  If not, see <http://www.gnu.org/licenses/>. */
-
-
-#ifndef DECIMAL_H
-#define DECIMAL_H
-
-/* This module provides a rudimentary floating point implementation using a decimal
-   base.   It can be used for floating point calculations where it is desirable that
-   the result is representable in decimal base.
-
-   Any of the functions may set the static variable dec_warning to non-zero if a
-   loss of precision or other issue occurs.
-
-   This does not purport to be efficient, either in time or space.
- */
-
-#include <stdio.h>
-#include <stdbool.h>
-
-#include <limits.h>
-
-#define DEC_PREC 1 /* operation resulted in a loss of precision */
-extern int dec_warning;
-
-
-#define ORDINATE_LONG
-#define MANTISSA_LONG
-
-#ifdef ORDINATE_SHORT
-typedef short ord_t;
-static const short ORD_MAX = SHRT_MAX;
-#define PR_ORD "%d"
-#endif
-
-#ifdef ORDINATE_INT
-typedef int ord_t;
-static const int ORD_MAX = INT_MAX;
-#define PR_ORD "%d"
-#endif
-
-#ifdef ORDINATE_LONG
-typedef long ord_t;
-static const long ORD_MAX = LONG_MAX;
-#define PR_ORD "%ld"
-#endif
-
-
-
-#ifdef MANTISSA_SHORT
-typedef short mant_t;
-static const short MANT_MAX = SHRT_MAX;
-#define PR_MANT "%d"
-#endif
-
-#ifdef MANTISSA_INT
-typedef int mant_t;
-static const int MANT_MAX = INT_MAX;
-#define PR_MANT "%d"
-#endif
-
-#ifdef MANTISSA_LONG
-typedef long mant_t;
-static const long MANT_MAX = LONG_MAX;
-#define PR_MANT "%ld"
-#endif
-
-
-
-#define MANT_MIN       (-MANT_MAX - 1)
-#define ORD_MIN                (-ORD_MAX - 1)
-
-struct decimal 
-{
-  ord_t ordinate;
-  mant_t mantissa;
-};
-
-void normalise (struct decimal *d1, struct decimal *d2);
-void decimal_init (struct decimal *dec, ord_t ord, mant_t mant);
-void decimal_init_from_string (struct decimal *dec, const char *s);
-int decimal_cmp (const struct decimal *d1, const struct decimal *d2);
-void decimal_int_multiply (struct decimal *dest, ord_t m);
-void decimal_int_divide (struct decimal *dest, ord_t m);
-void decimal_divide (struct decimal *dest, const struct decimal *src);
-void decimal_show (const struct decimal *dec, FILE *f);
-char *decimal_to_string (const struct decimal *dec);
-
-void decimal_add (struct decimal *dest, const struct decimal *);
-void decimal_subtract (struct decimal *dest, const struct decimal *);
-ord_t decimal_ceil (const struct decimal *d);
-ord_t decimal_floor (const struct decimal *d);
-mant_t dec_log10 (const struct decimal *d);
-
-
-void decimal_from_double (struct decimal *dec, double x);
-double decimal_to_double (const struct decimal *dec);
-
-
-
-#endif
index 3c324eff2485d583c3cff0c72e49c137c98aecca..9158590dd75c3a140244292004087a773eddec3c 100644 (file)
@@ -17,7 +17,6 @@
 #include <config.h>
 
 #include "math/histogram.h"
-#include "math/decimal.h"
 
 #include <gsl/gsl_histogram.h>
 #include <math.h>
@@ -59,163 +58,74 @@ destroy (struct statistic *s)
 }
 
 
-static
-double get_slack (double limit, double half_bin_width, int *n_half_bins)
-{
-  double ipart, remainder;
-
-  assert (half_bin_width > 0);
-
-  remainder =  modf (limit / half_bin_width, &ipart);
+/* Find a bin width which is adapted to the scaling of the x axis
+In the example here, the binwidth is half of the tick interval.
 
-  /* In C modf and % behave in an unexpected (to me at any rate) manner
-     when presented with a negative value
+        binwidth
+         >   <
+     |....+....+....+.      .+....|
+   LOWER  1    2    3     N_TICKS
+        ^LOWDBL                 ^HIGHDBL
 
-     For example, modf (-7.0 / 3.0) returns -2.0 R -0.3333
-  */
-
-  
-  *n_half_bins = ipart;
-
-  return remainder * half_bin_width;
-}
-
-
-/* This functions adjusts the upper and lower range of the histogram to make them fit BIN_WIDTH
-   MIN and MAX are the lowest and highest data to be plotted in the histogram.
-   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.
- */
+This only works, when the min and max value for the histogram are adapted
+such that (max-min) is a multiple of the binwidth. Then the location of the
+first bin has to be aligned to the ticks.
+*/
 static int
-adjust_bin_ranges (double bin_width, double min, double max, double *adj_min, double *adj_max)
+hist_find_pretty_no_of_bins(double bin_width_in, double min, double max,
+                           double *adjusted_min, double *adjusted_max)
 {
-  const double half_bin_width = bin_width / 2.0;
-
-  /* The lower and upper limits of the histogram, in units of half
-     bin widths */
-  int lower_limit, upper_limit;
-
-  double lower_slack =  get_slack (min, half_bin_width, &lower_limit);
-  double upper_slack = -get_slack (max, half_bin_width, &upper_limit);
+  double lower, interval;
+  int n_ticks;
+  double binwidth;
+  int nbins;
 
-  testing_assert (max > min);
+  chart_get_scale (max, min, &lower, &interval, &n_ticks);
 
-  /* 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
-     so that it is less than OR EQUAL to min.
-   */
-  if (lower_slack < 0)
+  if (bin_width_in >= 2 * interval)
     {
-      lower_limit--;
-      lower_slack += half_bin_width;
+      binwidth = floor(bin_width_in/interval) * interval;
+      *adjusted_min = lower;
     }
-  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
-     greater than max.
-  */
-  upper_limit++;;
-  upper_slack += half_bin_width;
-  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)
+  else if (bin_width_in >= 1.5 * interval)
     {
-      /* Extend the range at the end which gives the least unused space */
-      if (upper_slack > lower_slack)
-        {
-          lower_limit--;
-          lower_slack += half_bin_width;
-        }
+      binwidth = 1.5 * interval;
+      if (min < (lower + 0.5 * interval))
+       *adjusted_min = lower;
       else
-        {
-          upper_limit++;
-          upper_slack += half_bin_width;
-        }
+       *adjusted_min = lower + 0.5 * interval;
     }
-
-  /* But the range should be aligned to an ODD number of
-     half bin widths, so that the labels are aesthetically pleasing ones.
-     Otherwise we are likely to get labels such as -3 -1 1 3 instead of -2 0 2 4
-  */
-  if ( lower_limit % 2 == 0)
+  else if (bin_width_in >= interval)
     {
-      /* 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)
-        {
-          testing_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
-        {
-          testing_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;
-        }
+      binwidth = interval;
+      *adjusted_min = lower;
     }
-
-  /* If there are any completely empty bins, then remove them,
-     since empty bins don't really add much information to the histogram.
-   */
-  if (upper_slack > 2 * half_bin_width)
+  else if (bin_width_in >= (2.0/3.0 * interval))
     {
-      upper_slack -= 2 * half_bin_width;
-      upper_limit -=2;
+      binwidth = (2.0/3.0 * interval);
+      if (min >= lower + binwidth)
+       *adjusted_min = lower + binwidth;
+      else
+       *adjusted_min = lower;
     }
-
-  if (lower_slack >= 2 * half_bin_width)
+  else
     {
-      lower_slack -= 2 * half_bin_width;
-      lower_limit +=2;
+      int i;
+      for(i = 2; bin_width_in < interval/i; i++);
+      binwidth = interval/i;
+      *adjusted_min = floor((min - lower)/binwidth)*binwidth + lower;
     }
 
-  *adj_min = lower_limit * half_bin_width;
-  *adj_max = upper_limit * half_bin_width;
-
-  testing_assert (*adj_max > max);
-  testing_assert (*adj_min <= min);
+  nbins = ceil((max-*adjusted_min)/binwidth);
+  *adjusted_max = nbins*binwidth + *adjusted_min;
 
-  return (upper_limit - lower_limit) / 2.0;
+  return nbins;
 }
 
 
-
 struct histogram *
 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;
   int bins;
@@ -229,21 +139,7 @@ histogram_create (double bin_width_in, double min, double max)
 
   assert (bin_width_in > 0);
 
-  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) 
-    {
-      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);
-    }
-
-  /* Can this ever happen? */
-  if (bins < 1)
-    bins = 1;
+  bins = hist_find_pretty_no_of_bins(bin_width_in, min, max, &adjusted_min, &adjusted_max);
 
   h = xmalloc (sizeof *h);
 
index e0591723b7df0663dbb670b0b4dfd93795311fc8..f3accda3fb504745e4ed083ef8f21a2222b8003a 100644 (file)
@@ -17,7 +17,6 @@
 #include <config.h>
 
 #include "output/cairo-chart.h"
-#include "math/decimal.h"
 #include "math/chart-geometry.h"
 
 #include <assert.h>
@@ -48,7 +47,7 @@ xrchart_geometry_init (cairo_t *cr, struct xrchart_geometry *geom,
 {
   /* Set default chart geometry. */
   geom->axis[SCALE_ORDINATE].data_max = 0.900 * length;
-  geom->axis[SCALE_ORDINATE].data_min = 0.120 * length;
+  geom->axis[SCALE_ORDINATE].data_min = 0.200 * length;
 
   geom->axis[SCALE_ABSCISSA].data_min = 0.150 * width;
   geom->axis[SCALE_ABSCISSA].data_max = 0.800 * width;
@@ -317,8 +316,6 @@ draw_tick_internal (cairo_t *cr, const struct xrchart_geometry *geom,
        }
       else if (orientation == SCALE_ORDINATE)
         {
-          if (fabs (position) < DBL_EPSILON)
-           cairo_rel_move_to (cr, 0, 10);
           xrchart_label (cr, 'r', 'c', geom->font_size, s);
         }
     }
@@ -345,7 +342,29 @@ xrchart_write_title (cairo_t *cr, const struct xrchart_geometry *geom,
   cairo_restore (cr);
 }
 
+static void
+xrchart_text_extents (cairo_t *cr, const struct xrchart_geometry *geom,
+                     const char *utf8,
+                     double *width, double *height)
+{
+  PangoFontDescription *desc;
+  PangoLayout *layout;
+  int width_pango;
+  int height_pango;
 
+  desc = pango_font_description_from_string ("Sans");
+  if (desc == NULL)
+      return;
+  pango_font_description_set_absolute_size (desc, geom->font_size * PANGO_SCALE);
+  layout = pango_cairo_create_layout (cr);
+  pango_layout_set_font_description (layout, desc);
+  pango_layout_set_markup (layout, utf8, -1);
+  pango_layout_get_size (layout, &width_pango, &height_pango);
+  *width = (double) width_pango / PANGO_SCALE;
+  *height = (double) height_pango / PANGO_SCALE;
+  g_object_unref (layout);
+  pango_font_description_free (desc);
+}
 
 static void
 xrchart_write_scale (cairo_t *cr, struct xrchart_geometry *geom,
@@ -354,36 +373,50 @@ xrchart_write_scale (cairo_t *cr, struct xrchart_geometry *geom,
   int s;
   int ticks;
 
-  struct decimal dinterval;
-  struct decimal dlower;
-  struct decimal dupper;
+  double interval;
+  double lower;
+  double upper;
+  double tickscale;
+  char *tick_format_string;
+  bool tickoversize = false;
 
-  chart_get_scale (smax, smin, &dlower, &dinterval, &ticks);
+  chart_get_scale (smax, smin, &lower, &interval, &ticks);
 
-  dupper = dinterval;
-  decimal_int_multiply (&dupper, ticks);
-  decimal_add (&dupper, &dlower);
+  tick_format_string = chart_get_ticks_format (lower, interval, ticks, &tickscale);
 
-  double tick_interval = decimal_to_double (&dinterval);
+  upper = lower + interval * (ticks+1);
    
-  geom->axis[orient].max = decimal_to_double (&dupper);
-  geom->axis[orient].min = decimal_to_double (&dlower);
+  geom->axis[orient].max = upper;
+  geom->axis[orient].min = lower;
   
   geom->axis[orient].scale = (fabs (geom->axis[orient].data_max - geom->axis[orient].data_min)
                              / fabs (geom->axis[orient].max - geom->axis[orient].min));
+
+  if (orient == SCALE_ABSCISSA)
+    {
+      char *test_text;
+      double lower_txt_width, upper_txt_width, unused, width;
+      test_text = xasprintf(tick_format_string, upper*tickscale);
+      xrchart_text_extents (cr, geom, test_text, &upper_txt_width, &unused);
+      free(test_text);
+      test_text = xasprintf(tick_format_string, lower*tickscale);
+      xrchart_text_extents (cr, geom, test_text, &lower_txt_width, &unused);
+      free(test_text);
+      width = MAX(lower_txt_width, upper_txt_width);
+      tickoversize = width > 0.9 *
+       ((double)(geom->axis[SCALE_ABSCISSA].data_max - geom->axis[SCALE_ABSCISSA].data_min))/(ticks+1);
+    }
   
-  struct decimal pos = dlower;
+  double pos = lower;
 
-  for (s = 0 ; s < ticks; ++s)
+  for (s = 0 ; s <= ticks; ++s)
     {
-      char *str = decimal_to_string (&pos);
-      draw_tick (cr, geom, orient, false,
-                s * tick_interval * geom->axis[orient].scale,
-                "%s", str);
-      free (str);
-      
-      decimal_add (&pos, &dinterval);
+      draw_tick (cr, geom, orient, tickoversize,
+                s * interval * geom->axis[orient].scale,
+                tick_format_string, pos*tickscale);
+      pos += interval;
     }
+  free(tick_format_string);
 }
 
 /* Set the scale for the ordinate */
@@ -570,26 +603,3 @@ xrchart_line(cairo_t *cr, const struct xrchart_geometry *geom,
   cairo_stroke (cr);
 }
 
-void
-xrchart_text_extents (cairo_t *cr, const struct xrchart_geometry *geom,
-                     const char *utf8,
-                     double *width, double *height)
-{
-  PangoFontDescription *desc;
-  PangoLayout *layout;
-  int width_pango;
-  int height_pango;
-
-  desc = pango_font_description_from_string ("Sans");
-  if (desc == NULL)
-      return;
-  pango_font_description_set_absolute_size (desc, geom->font_size * PANGO_SCALE);
-  layout = pango_cairo_create_layout (cr);
-  pango_layout_set_font_description (layout, desc);
-  pango_layout_set_markup (layout, utf8, -1);
-  pango_layout_get_size (layout, &width_pango, &height_pango);
-  *width = (double) width_pango / PANGO_SCALE;
-  *height = (double) height_pango / PANGO_SCALE;
-  g_object_unref (layout);
-  pango_font_description_free (desc);
-}
index 116a8c990110be01d1e21a900874e18823a703c9..60ef282928b913e768ca25c693793abdfe9ef9bd 100644 (file)
@@ -178,9 +178,4 @@ void xrchart_draw_spreadlevel (const struct chart_item *, cairo_t *,
 void xrchart_draw_scatterplot (const struct chart_item *, cairo_t *,
                          struct xrchart_geometry *);
 
-/* Get the width and height of rendered label text */
-void xrchart_text_extents (cairo_t *cr, const struct xrchart_geometry *geom,
-                          const char *utf8,
-                          double *width, double *height);
-
 #endif /* output/cairo-chart.h */
index 7e2afee9b022cc621578623c889a474ad7b033dc..a85471962fcbebf52ff445190766d049781244f4 100644 (file)
@@ -69,30 +69,24 @@ histogram_write_legend (cairo_t *cr, const struct xrchart_geometry *geom,
 
 static void
 hist_draw_bar (cairo_t *cr, const struct xrchart_geometry *geom,
-               const gsl_histogram *h, int bar, const char *tick_format_string,
-              const double tickscale, const bool tickoversize)
+               const gsl_histogram *h, int bar)
 {
   double upper;
   double lower;
   double height;
 
-  const size_t bins = gsl_histogram_bins (h);
-
-  const double x_pos =
-    (geom->axis[SCALE_ABSCISSA].data_max - geom->axis[SCALE_ABSCISSA].data_min) *
-    bar / (double) bins ;
-
-  const double width =
-    (geom->axis[SCALE_ABSCISSA].data_max - geom->axis[SCALE_ABSCISSA].data_min) / (double) bins ;
-
   assert ( 0 == gsl_histogram_get_range (h, bar, &lower, &upper));
-
   assert ( upper >= lower);
 
+  const double x_pos =
+    (lower - geom->axis[SCALE_ABSCISSA].min) * geom->axis[SCALE_ABSCISSA].scale
+    +  geom->axis[SCALE_ABSCISSA].data_min;
+  const double width = (upper - lower) * geom->axis[SCALE_ABSCISSA].scale;
+
   height = geom->axis[SCALE_ORDINATE].scale * gsl_histogram_get (h, bar);
 
   cairo_rectangle (cr,
-                  geom->axis[SCALE_ABSCISSA].data_min + x_pos,
+                  x_pos,
                   geom->axis[SCALE_ORDINATE].data_min,
                    width, height);
   cairo_save (cr);
@@ -103,10 +97,6 @@ hist_draw_bar (cairo_t *cr, const struct xrchart_geometry *geom,
   cairo_fill_preserve (cr);
   cairo_restore (cr);
   cairo_stroke (cr);
-
-  draw_tick (cr, geom, SCALE_ABSCISSA, tickoversize,
-            x_pos + width / 2.0, tick_format_string, (upper+lower)/2.0*tickscale);
-
 }
 
 void
@@ -116,11 +106,6 @@ xrchart_draw_histogram (const struct chart_item *chart_item, cairo_t *cr,
   struct histogram_chart *h = to_histogram_chart (chart_item);
   int i;
   int bins;
-  char *tick_format_string;
-  char *test_text;
-  double width, left_width, right_width, unused;
-  double tickscale;
-  bool tickoversize;
 
   xrchart_write_title (cr, geom, _("HISTOGRAM"));
 
@@ -134,27 +119,17 @@ xrchart_draw_histogram (const struct chart_item *chart_item, cairo_t *cr,
     }
 
   xrchart_write_yscale (cr, geom, 0, gsl_histogram_max_val (h->gsl_hist));
+  xrchart_write_xscale (cr, geom, gsl_histogram_min (h->gsl_hist),
+                       gsl_histogram_max (h->gsl_hist));
+
 
   /* Draw the ticks and compute if the rendered tick text is wider than the bin */
   bins = gsl_histogram_bins (h->gsl_hist);
-  tick_format_string = chart_get_ticks_format (gsl_histogram_max (h->gsl_hist),
-                                              gsl_histogram_min (h->gsl_hist),
-                                              bins,
-                                              &tickscale);
-  test_text = xasprintf(tick_format_string, gsl_histogram_max (h->gsl_hist)*tickscale);
-  xrchart_text_extents (cr, geom, test_text, &right_width, &unused);
-  free(test_text);
-  test_text = xasprintf(tick_format_string, gsl_histogram_min (h->gsl_hist)*tickscale);
-  xrchart_text_extents (cr, geom, test_text, &left_width, &unused);
-  free(test_text);
-  width = MAX(left_width, right_width);
-  tickoversize = width > 0.9 *
-    ((double)(geom->axis[SCALE_ABSCISSA].data_max - geom->axis[SCALE_ABSCISSA].data_min))/bins;
+
   for (i = 0; i < bins; i++)
     {
-      hist_draw_bar (cr, geom, h->gsl_hist, i, tick_format_string, tickscale, tickoversize);
+      hist_draw_bar (cr, geom, h->gsl_hist, i);
     }
-  free(tick_format_string);
 
   histogram_write_legend (cr, geom, h->n, h->mean, h->stddev);
 
@@ -162,31 +137,28 @@ xrchart_draw_histogram (const struct chart_item *chart_item, cairo_t *cr,
       && h->n != SYSMIS && h->mean != SYSMIS && h->stddev != SYSMIS)
     {
       /* Draw the normal curve */
-      double d;
-      double x_min, x_max, not_used;
-      double abscissa_scale;
+      double x_min, x_max;
       double ordinate_scale;
-      double range;
+      double binwidth;
+      double x;
 
-      gsl_histogram_get_range (h->gsl_hist, 0, &x_min, &not_used);
-      range = not_used - x_min;
-      gsl_histogram_get_range (h->gsl_hist, bins - 1, &not_used, &x_max);
+      gsl_histogram_get_range (h->gsl_hist, 0, &x_min, &x_max);
+      binwidth = x_max - x_min;
 
-      abscissa_scale = (geom->axis[SCALE_ABSCISSA].data_max - geom->axis[SCALE_ABSCISSA].data_min) / (x_max - x_min);
-      ordinate_scale = (geom->axis[SCALE_ORDINATE].data_max - geom->axis[SCALE_ORDINATE].data_min) /
-       gsl_histogram_max_val (h->gsl_hist);
+      /* The integral over the histogram is binwidth * sum(bin_i), while the integral over the pdf is 1 */
+      /* Therefore the pdf has to be scaled accordingly such that the integrals are equal               */
+      ordinate_scale = binwidth * gsl_histogram_sum(h->gsl_hist);
 
       cairo_move_to (cr, geom->axis[SCALE_ABSCISSA].data_min, geom->axis[SCALE_ORDINATE].data_min);
-      for (d = geom->axis[SCALE_ABSCISSA].data_min;
-          d <= geom->axis[SCALE_ABSCISSA].data_max;
-          d += (geom->axis[SCALE_ABSCISSA].data_max - geom->axis[SCALE_ABSCISSA].data_min) / 100.0)
+      for (x = geom->axis[SCALE_ABSCISSA].min;
+          x <= geom->axis[SCALE_ABSCISSA].max;
+          x += (geom->axis[SCALE_ABSCISSA].max - geom->axis[SCALE_ABSCISSA].min) / 100.0)
        {
-         const double x = (d - geom->axis[SCALE_ABSCISSA].data_min) / abscissa_scale + x_min;
-         const double y = h->n * range *
-           gsl_ran_gaussian_pdf (x - h->mean, h->stddev);
-
-          cairo_line_to (cr, d, geom->axis[SCALE_ORDINATE].data_min  + y * ordinate_scale);
-
+         const double y = gsl_ran_gaussian_pdf (x - h->mean, h->stddev) * ordinate_scale;
+         /* Transform to drawing coordinates */
+         const double x_pos = (x - geom->axis[SCALE_ABSCISSA].min) * geom->axis[SCALE_ABSCISSA].scale + geom->axis[SCALE_ABSCISSA].data_min;
+         const double y_pos = (y - geom->axis[SCALE_ORDINATE].min) * geom->axis[SCALE_ORDINATE].scale + geom->axis[SCALE_ORDINATE].data_min;
+          cairo_line_to (cr, x_pos, y_pos);
        }
       cairo_stroke (cr);
     }
index be44b342e9267ccc2f491457f960b308f1383a4d..3b9a5535037f4e1d379e20ac4b0d3284531a2b99 100644 (file)
@@ -31,9 +31,8 @@ check_PROGRAMS += \
        tests/libpspp/tower-test \
        tests/libpspp/u8-istream-test \
        tests/libpspp/zip-test \
-       tests/math/chart-geometry-test \
+       tests/math/chart-get-ticks-format-test \
        tests/math/chart-get-scale-test \
-       tests/math/decimal-test \
        tests/output/render-test \
        tests/ui/syntax-gen-test
 
@@ -212,14 +211,6 @@ tests_libpspp_zip_test_LDADD = \
        src/libpspp-core.la \
        gl/libgl.la 
 
-check_PROGRAMS += tests/math/chart-geometry-test
-tests_math_chart_geometry_test_SOURCES = tests/math/chart-geometry-test.c
-tests_math_chart_geometry_test_LDADD = \
-       src/math/libpspp-math.la \
-       src/libpspp/liblibpspp.la \
-       src/libpspp-core.la \
-       gl/libgl.la 
-
 check_PROGRAMS += tests/math/chart-get-scale-test
 tests_math_chart_get_scale_test_SOURCES = tests/math/chart-get-scale-test.c
 tests_math_chart_get_scale_test_LDADD = \
@@ -236,15 +227,6 @@ tests_math_chart_get_ticks_format_test_LDADD = \
        src/libpspp-core.la \
        gl/libgl.la
 
-check_PROGRAMS += tests/math/decimal-test
-tests_math_decimal_test_SOURCES = tests/math/decimal-test.c
-tests_math_decimal_test_LDADD = \
-       src/math/libpspp-math.la \
-       src/libpspp/liblibpspp.la \
-       src/libpspp-core.la \
-       gl/libgl.la 
-
-
 check_PROGRAMS += tests/output/render-test
 tests_output_render_test_SOURCES = tests/output/render-test.c
 tests_output_render_test_LDADD = \
@@ -404,7 +386,6 @@ TESTSUITE_AT = \
        tests/libpspp/u8-istream.at \
        tests/libpspp/zip.at \
        tests/math/chart-geometry.at \
-       tests/math/decimal.at \
        tests/math/moments.at \
        tests/math/randist.at \
        tests/output/ascii.at \
diff --git a/tests/math/chart-geometry-test.c b/tests/math/chart-geometry-test.c
deleted file mode 100644 (file)
index 1cf67c3..0000000
+++ /dev/null
@@ -1,61 +0,0 @@
-/* PSPP - a program for statistical analysis.
-   Copyright (C) 2015 Free Software Foundation, Inc.
-
-   This program is free software: you can redistribute it and/or modify
-   it under the terms of the GNU General Public License as published by
-   the Free Software Foundation, either version 3 of the License, or
-   (at your option) any later version.
-
-   This program is distributed in the hope that it will be useful,
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-   GNU General Public License for more details.
-
-   You should have received a copy of the GNU General Public License
-   along with this program.  If not, see <http://www.gnu.org/licenses/>. */
-
-#include <config.h>
-#include <stdlib.h>
-#include "math/chart-geometry.h"
-#include "math/decimal.h"
-#include "libpspp/compiler.h"
-
-const double in[20] =
-  {
-    0.00648687,
-    728815,
-    8.14431e-07,
-    77611.4,
-    3.33497,
-    180.426,
-    0.676168,
-    2.00744e+08,
-    14099.3,
-    19.5186,
-    1.17473e-07,
-    166337,
-    0.00163644,
-    1.94724e-09,
-    2.31564e-06,
-    3.10674e+06,
-    5.10314e-05,
-    1.95101,
-    1.40884e+09,
-    78217.6
-  };
-
-int 
-main (int argc UNUSED, char **argv UNUSED)
-{
-  int i;
-  for (i = 0; i < 20; ++i)
-    {
-      struct decimal dout;
-      chart_rounded_tick (in[i], &dout);
-      
-      printf ("%g %s\n", in[i], decimal_to_string (&dout));
-    }
-
-  return 0;
-}
-
index 96bf02db736952bac2b61c7f717121e65120cc88..9bbd0cf070cc08fe7adc03063bed01c48fc11dd6 100644 (file)
@@ -1,66 +1,37 @@
 AT_BANNER([Chart Geometry])
 
-AT_SETUP([Chart Rounding])
-
-AT_CHECK([../../math/chart-geometry-test], [0], [dnl
-0.00648687 0.005
-728815 500000
-8.14431e-07 0.000001
-77611.4 100000
-3.33497 2
-180.426 200
-0.676168 0.5
-2.00744e+08 200000000
-14099.3 10000
-19.5186 20
-1.17473e-07 0.0000001
-166337 200000
-0.00163644 0.002
-1.94724e-09 0.000000002
-2.31564e-06 0.000002
-3.10674e+06 2000000
-5.10314e-05 0.00005
-1.95101 2
-1.40884e+09 1000000000
-78217.6 100000
-])
-
-AT_CLEANUP
-
-
 AT_SETUP([Chart Scale])
-
 AT_CHECK([../../math/chart-get-scale-test], [0], [ignore])
-
 AT_CLEANUP
 
-
 AT_SETUP([Chart Ticks Format])
-
 AT_CHECK([../../math/chart-get-ticks-format-test], [0], [dnl
-max: 1000, min: 10, nticks: 10, fs: %.0lf, scale: 1, example: 505
-max: 10000, min: 10, nticks: 10, fs: %.0lf, scale: 1, example: 5005
-max: 100000, min: 10, nticks: 10, fs: %.0lf, scale: 1, example: 50005
-max: 1e+06, min: 10, nticks: 10, fs: %.0lf, scale: 1, example: 500005
-max: 1e+07, min: 10, nticks: 10, fs: %.2lf&#8729;10<sup>7</sup>, scale: 1e-07, example: 0.50&#8729;10<sup>7</sup>
-max: 1e+08, min: 10, nticks: 10, fs: %.2lf&#8729;10<sup>8</sup>, scale: 1e-08, example: 0.50&#8729;10<sup>8</sup>
-max: 0.1, min: 0.01, nticks: 10, fs: %.3lf, scale: 1, example: 0.055
-max: 0.01, min: 0.001, nticks: 10, fs: %.4lf, scale: 1, example: 0.0055
-max: 0.001, min: 0.0001, nticks: 10, fs: %.5lf, scale: 1, example: 0.00055
-max: 0.0001, min: 1e-05, nticks: 10, fs: %.2lf&#8729;10<sup>-5</sup>, scale: 100000, example: 5.50&#8729;10<sup>-5</sup>
-max: 1e-05, min: 1e-07, nticks: 10, fs: %.2lf&#8729;10<sup>-6</sup>, scale: 1e+06, example: 5.05&#8729;10<sup>-6</sup>
-max: 1e-07, min: 1e-08, nticks: 10, fs: %.2lf&#8729;10<sup>-8</sup>, scale: 1e+08, example: 5.50&#8729;10<sup>-8</sup>
-max: 1.00001e-05, min: 1e-05, nticks: 10, fs: %.6lf&#8729;10<sup>-5</sup>, scale: 100000, example: 1.000005&#8729;10<sup>-5</sup>
-max: 1e+08, min: 1e+08, nticks: 10, fs: %.0lf, scale: 1, example: 100000005
-max: 100000, min: -500000, nticks: 10, fs: %.0lf, scale: 1, example: -200000
-max: 5, min: -5, nticks: 10, fs: %.0lf, scale: 1, example: 0
-max: 5, min: -4.999, nticks: 10, fs: %.1lf, scale: 1, example: 0.0
-max: 5, min: -4.999, nticks: 9, fs: %.0lf, scale: 1, example: 0
-max: 5, min: 0, nticks: 10, fs: %.1lf, scale: 1, example: 2.5
-max: 0, min: -5, nticks: 9, fs: %.1lf, scale: 1, example: -2.5
-max: 1.001e-95, min: 1e-95, nticks: 10, fs: %.5lf&#8729;10<sup>-95</sup>, scale: 1e+95, example: 1.00050&#8729;10<sup>-95</sup>
-max: 1.001e+98, min: 1e+98, nticks: 10, fs: %.5lf&#8729;10<sup>98</sup>, scale: 1e-98, example: 1.00050&#8729;10<sup>98</sup>
-max: 1.001e+33, min: 1e-22, nticks: 10, fs: %.2lf&#8729;10<sup>33</sup>, scale: 1e-33, example: 0.50&#8729;10<sup>33</sup>
+lower: 1000, interval: 10, nticks: 10, fs: %.0lf, scale: 1, ex: 1030, ex 2: 1040
+lower: 10000, interval: 10, nticks: 10, fs: %.0lf, scale: 1, ex: 10030, ex 2: 10040
+lower: 100000, interval: 10, nticks: 10, fs: %.0lf, scale: 1, ex: 100030, ex 2: 100040
+lower: 1e+06, interval: 10, nticks: 10, fs: %.0lf, scale: 1, ex: 1000030, ex 2: 1000040
+lower: 1e+07, interval: 10, nticks: 10, fs: %.0lf, scale: 1, ex: 10000030, ex 2: 10000040
+lower: 1e+08, interval: 10, nticks: 10, fs: %.0lf, scale: 1, ex: 100000030, ex 2: 100000040
+lower: 0.1, interval: 0.01, nticks: 10, fs: %.2lf, scale: 1, ex: 0.13, ex 2: 0.14
+lower: 0.01, interval: 0.001, nticks: 10, fs: %.3lf, scale: 1, ex: 0.013, ex 2: 0.014
+lower: 0.001, interval: 0.0001, nticks: 10, fs: %.4lf, scale: 1, ex: 0.0013, ex 2: 0.0014
+lower: 0.0001, interval: 1e-05, nticks: 10, fs: %.1lf&#8901;10<sup>-4</sup>, scale: 10000, ex: 1.3&#8901;10<sup>-4</sup>, ex 2: 1.4&#8901;10<sup>-4</sup>
+lower: 1e-05, interval: 1e-07, nticks: 10, fs: %.2lf&#8901;10<sup>-5</sup>, scale: 100000, ex: 1.03&#8901;10<sup>-5</sup>, ex 2: 1.04&#8901;10<sup>-5</sup>
+lower: 1e-07, interval: 1e-08, nticks: 10, fs: %.1lf&#8901;10<sup>-7</sup>, scale: 1e+07, ex: 1.3&#8901;10<sup>-7</sup>, ex 2: 1.4&#8901;10<sup>-7</sup>
+lower: -5, interval: 1, nticks: 10, fs: %.0lf, scale: 1, ex: -2, ex 2: -1
+lower: -5, interval: 0.5, nticks: 10, fs: %.1lf, scale: 1, ex: -3.5, ex 2: -3.0
+lower: -5, interval: 0.2, nticks: 9, fs: %.1lf, scale: 1, ex: -4.4, ex 2: -4.2
+lower: -5, interval: 2, nticks: 10, fs: %.0lf, scale: 1, ex: 1, ex 2: 3
+lower: -0.5, interval: 0.1, nticks: 9, fs: %.1lf, scale: 1, ex: -0.2, ex 2: -0.1
+lower: 9.75e+08, interval: 5e+06, nticks: 9, fs: %.3lf&#8901;10<sup>9</sup>, scale: 1e-09, ex: 0.990&#8901;10<sup>9</sup>, ex 2: 0.995&#8901;10<sup>9</sup>
+lower: 9.7e+08, interval: 1e+07, nticks: 9, fs: %.2lf&#8901;10<sup>9</sup>, scale: 1e-09, ex: 1.00&#8901;10<sup>9</sup>, ex 2: 1.01&#8901;10<sup>9</sup>
+lower: -4e+07, interval: 1e+07, nticks: 9, fs: %.0lf&#8901;10<sup>7</sup>, scale: 1e-07, ex: -1&#8901;10<sup>7</sup>, ex 2: 0&#8901;10<sup>7</sup>
+lower: -3e+07, interval: 5e+06, nticks: 9, fs: %.1lf&#8901;10<sup>7</sup>, scale: 1e-07, ex: -1.5&#8901;10<sup>7</sup>, ex 2: -1.0&#8901;10<sup>7</sup>
+lower: 1.001e-95, interval: 2e-99, nticks: 10, fs: %.4lf&#8901;10<sup>-95</sup>, scale: 1e+95, ex: 1.0016&#8901;10<sup>-95</sup>, ex 2: 1.0018&#8901;10<sup>-95</sup>
+lower: 1.001e+98, interval: 2e+94, nticks: 10, fs: %.4lf&#8901;10<sup>98</sup>, scale: 1e-98, ex: 1.0016&#8901;10<sup>98</sup>, ex 2: 1.0018&#8901;10<sup>98</sup>
+lower: 5984, interval: 1e-05, nticks: 10, fs: %.5lf, scale: 1, ex: 5984.00003, ex 2: 5984.00004
+lower: 3e+33, interval: 1e-22, nticks: 10, fs: %lg, scale: 1, ex: 3e+33, ex 2: 3e+33
+lower: 3e+33, interval: 1000, nticks: 10, fs: %.8lf&#8901;10<sup>33</sup>, scale: 1e-33, ex: 3.00000000&#8901;10<sup>33</sup>, ex 2: 3.00000000&#8901;10<sup>33</sup>
+lower: 0.1, interval: 2e-42, nticks: 10, fs: %.8lf, scale: 1, ex: 0.10000000, ex 2: 0.10000000
 ])
-
 AT_CLEANUP
index d4cbe18eb03f5a1094cde4bacb619b9773901f11..6f2ca711d0bea538fabf2f920db08a63215fc9fb 100644 (file)
@@ -23,7 +23,6 @@
 
 #include "libpspp/compiler.h"
 
-#include "math/decimal.h"
 #include "math/chart-geometry.h"
 #include <limits.h>
 #include <float.h>
 
 #if 0
 static void
-dump_scale (const struct decimal *low, const struct decimal *interval, int n_ticks)
+dump_scale (const double low, const double interval, int n_ticks)
 {
   int i;
-  struct decimal tick = *low;
+  double tick = low;
   for (i = 0; i <= n_ticks; ++i)
     {
-      printf ("Tick %d: %s (%g)\n", i, decimal_to_string (&tick), decimal_to_double (&tick));
-      decimal_add (&tick, interval);
+      printf ("Tick %d: %g\n", i, tick);
+      tick += interval;
     }
 }
 #endif
@@ -48,50 +47,52 @@ static void
 test_range (double low, double high)
 {
   int n_ticks = 0;
-  struct decimal interval;
-  struct decimal lower;
+  double interval;
+  double lower;
 
   chart_get_scale (high, low,
                   &lower, &interval, &n_ticks);
 
-  assert (n_ticks > 0);
-  assert (n_ticks < 12);
-
-  //  dump_scale (&lower, &interval, n_ticks);
-
-  assert (decimal_to_double (&lower) <= low);
-  
-  {
-    struct decimal  l = lower;
-    decimal_add (&l, &interval);
-    assert (decimal_to_double (&l) > low);
+  if ((high - low) < 10 * DBL_MIN){
+    assert (n_ticks == 0);
+    assert (lower == low);
+    assert (interval <= 10 * DBL_MIN);
   }
+  else
+    assert (n_ticks > 4);
 
-  {
-    struct decimal  i = interval;
-
-    decimal_int_multiply (&i, n_ticks - 1);
-
-    decimal_add (&i, &lower);
+  assert (n_ticks <= 10);
 
-    /* i now contains the upper bound minus one tick */
-    assert (decimal_to_double (&i) < high);
-
-    decimal_add (&i, &interval);
+#if 0
+  printf("%s: high: %lg, low %lg, interval: %lg, nticks: %d\n", 
+        __FUNCTION__, high, low, interval, n_ticks);
+  dump_scale (lower, interval, n_ticks);
+#endif
 
-    assert (decimal_to_double (&i) >= high);
+  if ((high - low) > 10 * DBL_MIN) {
+    assert (lower <= low);
+    assert (lower + interval > low);
+    assert (lower + n_ticks * interval < high);
+    assert (lower + (n_ticks + 1) * interval >= high);
   }
-
 }
 
 
 int 
 main (int argc UNUSED, char **argv UNUSED)
 {
+  test_range (0, 0);
+  test_range (5, 5);
+  test_range (-5, -5);
+  test_range (0, 7);
   test_range (0.2, 11);
   test_range (-0.2, 11);
   test_range (-10, 0.2);
   test_range (-10, -0.2);
+  test_range (-10000, 10003);
+  test_range (50042,50053);
+  test_range (-50010, -49999);
+  test_range (0.000100002, 0.000100010);
 
   test_range (102, 50030); 
   test_range (0.00102, 0.0050030); 
index 6dcab5077462ca2aa95ae729f4064bb59837921f..3dbeac6557a1f65c4545d4d56996e19d7c1d6906 100644 (file)
@@ -21,8 +21,8 @@
 #include "libpspp/compiler.h"
 
 struct range {
-  double max;
-  double min;
+  double lower;
+  double interval;
   int nticks;
 };
 
@@ -39,17 +39,21 @@ struct range tv[] = {
   {       0.0001,         0.00001,     10},
   {      0.00001,       0.0000001,     10},
   {    0.0000001,      0.00000001,     10},
-  { 0.0000100001,         0.00001,     10},
-  {  100000010.0,     100000000.0,     10},
-  {     100000.0,       -500000.0,     10},
-  {          5.0,            -5.0,     10},
-  {          5.0,          -4.999,     10},
-  {          5.0,          -4.999,      9},
-  {          5.0,             0.0,     10},
-  {          0.0,            -5.0,      9},
-  {    1.001E-95,         1.0E-95,     10},
-  {     1.001E98,          1.0E98,     10},
-  {     1.001E33,         1.0E-22,     10},
+  {         -5.0,             1.0,     10},
+  {         -5.0,             0.5,     10},
+  {         -5.0,             0.2,      9},
+  {         -5.0,             2.0,     10},
+  {         -0.5,             0.1,      9},
+  {      0.975E9,         0.005E9,      9},
+  {      0.970E9,          0.01E9,      9},
+  {         -4E7,             1E7,      9},
+  {         -3E7,           0.5E7,      9},
+  {    1.001E-95,      0.0002E-95,     10},
+  {     1.001E98,       0.0002E98,     10},
+  {         5984,         0.00001,     10},
+  {         3E33,           1E-22,     10},
+  {         3E33,            1000,     10},
+  {          0.1,           2E-42,     10},
   {          0.0,             0.0,     -1}
 };
 
@@ -59,18 +63,20 @@ main (int argc UNUSED, char **argv UNUSED)
   char *fs;
   double scale;
   int i = 0;
-  double max, min;
+  double lower, interval;
   int nticks;
 
   for(i=0;tv[i].nticks > 0;i++)
     {
-      max = tv[i].max;
-      min = tv[i].min;
+      lower = tv[i].lower;
+      interval = tv[i].interval;
       nticks = tv[i].nticks;
-      fs = chart_get_ticks_format (max, min, nticks, &scale);
-      printf("max: %lg, min: %lg, nticks: %d, fs: %s, scale: %lg, example: ",
-            max, min, nticks, fs, scale);
-      printf(fs,((max-min)/2.0+min)*scale);
+      fs = chart_get_ticks_format (lower, interval, nticks, &scale);
+      printf("lower: %lg, interval: %lg, nticks: %d, fs: %s, scale: %lg, ex: ",
+            lower, interval, nticks, fs, scale);
+      printf(fs,(lower + 3 * interval)*scale);
+      printf(", ex 2: ");
+      printf(fs,(lower + 4 * interval)*scale);
       printf("\n");
       free(fs);
     }
diff --git a/tests/math/decimal-test.c b/tests/math/decimal-test.c
deleted file mode 100644 (file)
index 791483e..0000000
+++ /dev/null
@@ -1,348 +0,0 @@
-/* PSPP - a program for statistical analysis.
-   Copyright (C) 2015 Free Software Foundation, Inc.
-
-   This program is free software: you can redistribute it and/or modify
-   it under the terms of the GNU General Public License as published by
-   the Free Software Foundation, either version 3 of the License, or
-   (at your option) any later version.
-
-   This program is distributed in the hope that it will be useful,
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-   GNU General Public License for more details.
-
-   You should have received a copy of the GNU General Public License
-   along with this program.  If not, see <http://www.gnu.org/licenses/>. */
-
-#include <config.h>
-
-#include <stdlib.h>
-#include <stdbool.h>
-#include <assert.h>
-#include <string.h>
-
-#include "libpspp/compiler.h"
-#include "math/decimal.h"
-#include <limits.h>
-#include <float.h>
-#include <math.h>
-
-/* Canonicalise a string  holding the decimal representation of a number.
-   For example, leading zeros left of the decimal point are removed, as are
-   trailing zeros to the right.
-
-   This function is used purely for testing, and need not and is not intended
-   to be efficient.
- */
-static char *
-canonicalise_string (const char *s)
-{
-  char *out = NULL;
-  char *dot = NULL;
-  bool negative = false;
-  char *p;
-  char *temp = malloc (strlen (s) + 3);
-  char *last_leading_zero = NULL;
-
-  /* Strip leading - if present */
-  if (*s == '-')
-    {
-      negative = true;
-      s++;
-    }
-  
-  strcpy (temp, "00");
-  strcat (temp, s);
-
-  char *first_trailing_zero = NULL;
-  char *significant_digit = NULL;
-  for (p = temp; *p; p++)
-    {
-      if (*p == '0' && dot == NULL && significant_digit == NULL)
-       last_leading_zero = p;
-
-      if (*p == '0' && first_trailing_zero == NULL)
-       first_trailing_zero = p;
-
-      if (*p == '.')
-       {
-         dot = p;
-         first_trailing_zero = NULL;
-       }
-
-      if (*p >= '1' && *p <= '9')
-       {
-         significant_digit = p;
-         first_trailing_zero = NULL;
-       }
-    }
-
-  if (first_trailing_zero && dot)
-    *first_trailing_zero = '\0';
-
-  if (last_leading_zero)
-    {
-      /* Strip leading zeros */
-      out = last_leading_zero + 1;
-
-      /* But if we now start with . put a zero back again */
-      if (dot == last_leading_zero + 1)
-       out--;
-    }
-
-
-  if (negative)
-    {
-      out--;
-      out[0] = '-';
-    }
-  
-  if (!significant_digit)
-    {
-      *out = '0';
-      *(out+1) = '\0';
-    }
-    
-
-  return out;
-}
-
-
-/* Tests both the decimal_to_string function, and the decimal_input_from_string 
-   function */
-static void
-test_run (const char *input)
-  {
-    struct decimal test;
-    struct decimal number;
-    decimal_init_from_string (&number, input);
-
-    char *s = decimal_to_string (&number);
-    char *canon = canonicalise_string (input);
-    if (0 != strcmp (canon, s))
-      {
-       fprintf (stdout, "\"%s\" does not match \n\"%s\"\n", canon, s);
-       exit (1);
-      }
-
-    decimal_init_from_string (&test, s);
-    assert (0 == decimal_cmp (&test, &number));
-
-    free (s);
-  }
-
-
-static void
-test_can (const char *in, const char *soll)
-{
-  char *ist = canonicalise_string (in);
-  if (0 != strcmp (soll, ist))
-    {
-      printf ("\"%s\" canonicalises to \"%s\" (should be \"%s\")\n", in, ist, soll);
-    }
-}
-
-
-#if 0
-static void
-dump_scale (const struct decimal *low, const struct decimal *interval, int n_ticks)
-{
-  int i;
-  struct decimal tick = *interval;
-  printf ("Lowest: %s\n", decimal_to_string (low));
-  for (i = 0; i <= n_ticks; ++i)
-    {
-      printf ("Tick %d: %s (%g)\n", i, decimal_to_string (&tick), decimal_to_double (&tick));
-      decimal_add (&tick, interval);
-    }
-}
-#endif
-
-
-
-static void
-test_ceil (double x)
-{
-  struct decimal dx;
-  decimal_from_double (&dx, x);
-  int act = decimal_ceil (&dx);
-  int expected = ceil (x);
-  
-  assert (act == expected);
-}
-
-static void
-test_floor (double x)
-{
-  struct decimal dx;
-  decimal_from_double (&dx, x);
-  int act = decimal_floor (&dx);
-  int expected = floor (x);
-  
-  assert (act == expected);
-}
-
-
-static void
-test_addition (const struct decimal *one_, const struct decimal *two)
-{
-  struct decimal one = *one_;
-  
-  decimal_add (&one, two);
-  
-  double dsum = decimal_to_double (&one);
-
-  char sdsum1[256];
-  char sdsum2[256];
-
-  snprintf (sdsum1, 256, "%s", decimal_to_string (&one));
-  snprintf (sdsum2, 256, "%g", dsum);
-
-  assert (strcmp (sdsum1, sdsum2) == 0);
-}
-
-
-static void
-test_multiplication (const struct decimal *d, int m)
-{
-  char b1[256];
-  char b2[256];
-  struct decimal dest = *d;
-  double x = decimal_to_double (&dest);
-
-  decimal_int_multiply (&dest, m);
-
-  double y = decimal_to_double (&dest);
-
-  snprintf (b1, 256, "%g", m * x);
-  snprintf (b2, 256, "%g", y);
-  assert (0 == strcmp (b1, b2));
-}
-
-
-
-int 
-main (int argc UNUSED, char **argv UNUSED)
-{
-  /* Test that our canonicalise function works for all corner cases we
-     can think of. */
-
-  test_can ("500", "500");
-  test_can ("5", "5");
-  test_can ("-3", "-3");
-  test_can ("-3.001", "-3.001");
-  test_can ("-03.001", "-3.001");
-  test_can ("-.0301", "-0.0301");
-  test_can ("0314.09", "314.09");
-  test_can ("0314.090", "314.09");
-  test_can ("0314.0900340", "314.090034");
-  test_can ("0.0", "0");
-  test_can ("0.", "0");
-  test_can (".0", "0");
-  test_can ("-.1", "-0.1");
-  test_can (".090", "0.09");
-  test_can ("03410.098700", "3410.0987");
-  test_can ("-03410.098700", "-3410.0987");
-
-  /* Test the conversion functions */
-  test_run ("-90000");
-  test_run ("-3");
-  test_run ("50001");
-  test_run ("500");
-  test_run ("350");
-  test_run ("050");
-  test_run ("4");
-  test_run ("0");
-  test_run (".45");
-  test_run ("-.45");
-  test_run ("666666666");
-  test_run ("6000000000");
-  test_run ("0.000000005");
-  test_run ("0.00000000000000000000000000000000000000005");
-  test_run ("0.0234");
-  test_run ("0.234");
-  test_run ("-0123.45600");
-
-  test_ceil (5.21);
-  test_ceil (-4.32);
-  test_ceil (0);
-  test_ceil (0.0009);
-
-  test_floor (4.09);
-  test_floor (-4.09);
-  test_floor (0);
-  test_floor (0.004);
-
-
-  {
-    struct decimal high = {2, 0};
-    struct decimal low = {2, -1};
-
-    test_addition (&high, &low);
-  }
-
-
-  {
-    struct decimal high = {10, 0};
-    struct decimal low = {2, -1};
-
-    test_addition (&high, &low);
-  }
-
-
-  {
-    struct decimal high = {10, 0};
-    struct decimal low = {-2, -1};
-
-    test_addition (&high, &low);
-  }
-
-  {
-    struct decimal high = {12, -5};
-    struct decimal low = {-2, -1};
-
-    test_addition (&high, &low);
-  }
-
-  {
-    struct decimal high = {-112, -1};
-    struct decimal low = {2, -1};
-
-    test_addition (&high, &low);
-  }
-
-
-  {
-    struct decimal m = {10, 0};
-
-    test_multiplication (&m, 11);
-  }
-
-
-  {
-    struct decimal m = {ORD_MAX - 2, 0};
-
-    test_multiplication (&m, 11);
-  }
-
-
-  {
-    struct decimal m = {34, 0};
-
-    test_multiplication (&m, 0);
-  }
-
-  {
-    struct decimal m = {34, -20};
-
-    test_multiplication (&m, 33);
-  }
-
-  {
-    struct decimal m = {304, 2};
-
-    test_multiplication (&m, -33);
-  }
-
-  return 0;
-}
diff --git a/tests/math/decimal.at b/tests/math/decimal.at
deleted file mode 100644 (file)
index b3e71d1..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-AT_BANNER([Decimal floating point])
-
-AT_SETUP([Decimal float])
-
-AT_CHECK([../../math/decimal-test], [0], [ignore])
-
-AT_CLEANUP