changeset 4612:313c2cc696b9

Fix the broken bigfloat-to-string conversion function.
author Jerry James <james@xemacs.org>
date Wed, 11 Feb 2009 09:20:47 -0700
parents 9c97a5a8c241
children e254bf96eb9e
files src/number-gmp.c
diffstat 1 files changed, 51 insertions(+), 33 deletions(-) [+]
line wrap: on
line diff
--- a/src/number-gmp.c	Wed Feb 11 15:30:59 2009 +0000
+++ b/src/number-gmp.c	Wed Feb 11 09:20:47 2009 -0700
@@ -26,7 +26,7 @@
 #include "lisp.h"
 #include "sysproc.h"    /* For qxe_getpid */
 
-static mpf_t float_print_min, float_print_max;
+static mp_exp_t float_print_min, float_print_max;
 gmp_randstate_t random_state;
 
 CIbyte *
@@ -38,40 +38,56 @@
   const int neg = (sign < 0) ? 1 : 0;
   int len = strlen (str) + 1;  /* Count the null terminator */
 
-  if (sign == 0 || (mpf_cmp (float_print_min, f) <= 0 &&
-                    mpf_cmp (f, float_print_max) <= 0))
+  if (sign == 0)
+    {
+      XREALLOC_ARRAY (str, CIbyte, 4);
+      strncpy (str, "0.0", 4);
+    }
+  else if (float_print_min <= expt && expt <= float_print_max)
     {
-      /* Move digits down to insert a radix point */
-      if (expt <= 0)
-        {
-          /* We need room for a radix point and leading zeroes */
-          const int space = -expt + 2;
-          XREALLOC_ARRAY (str, CIbyte, len + space);
-          memmove (&str[space + neg], &str[neg], len - neg);
-          memset (&str[neg], '0', space);
-          str[neg + 1] = '.';
-          len += space;
-        }
+      if (expt < 0)
+	{
+	  /* We need room for a radix point and leading zeroes */
+	  const int space = -expt + 2;
+	  XREALLOC_ARRAY (str, CIbyte, len + space);
+	  memmove (&str[space + neg], &str[neg], len - neg);
+	  memset (&str[neg], '0', space);
+	  str[neg + 1] = '.';
+	}
+      else if (len <= expt + neg + 1)
+	{
+	  /* We need room for a radix point and trailing zeroes */
+	  XREALLOC_ARRAY (str, CIbyte, expt + neg + 3);
+	  memset (&str[len - 1], '0', expt + neg + 3 - len);
+	  str[expt + neg] = '.';
+	  str[expt + neg + 2] = '\0';
+	}
       else
-        {
-          /* We just need room for a radix point */
-          XREALLOC_ARRAY (str, CIbyte, len + 1);
-          memmove (&str[expt + neg + 1], &str[expt + neg], len - (expt + neg));
-          str[expt + neg] = '.';
-          len++;
-        }
+	{
+	  /* We just need room for a radix point */
+	  XREALLOC_ARRAY (str, CIbyte, len + 1);
+	  memmove (&str[expt + neg + 1], &str[expt + neg], len - (expt + neg));
+	  str[expt + neg] = '.';
+	}
     }
   else
     {
-      /* Computerized scientific notation */
-      /* We need room for a radix point, format identifier, and exponent */
-      const int space = (expt < 0)
-        ? (int)(log ((double) (-expt)) / log ((double) base)) + 3
-        : (int)(log ((double) expt) / log ((double) base)) + 2;
+      /* Computerized scientific notation: We need room for a possible radix
+	 point, format identifier, and exponent */
+      /* GMP's idea of the exponent is 1 greater than scientific notation's */
+      expt--;
+      const int point = (len == neg + 2) ? 0 : 1;
+      const int exponent = (expt < 0)
+	? (int)(log ((double) (-expt)) / log ((double) base)) + 3
+	: (int)(log ((double) expt) / log ((double) base)) + 2;
+      const int space = point + exponent;
       XREALLOC_ARRAY (str, CIbyte, len + space);
-      memmove (&str[neg + 2], &str[neg + 1], len - neg);
-      str[len + 1] = 'l';
-      sprintf (&str[len + 2], "%ld", expt);
+      if (point > 0)
+	{
+	  memmove (&str[neg + 2], &str[neg + 1], len - neg);
+	  str[neg + 1] = '.';
+	}
+      sprintf (&str[len + point - 1], "E%ld", expt);
     }
   return str;
 }
@@ -94,11 +110,13 @@
   mp_set_memory_functions ((void *(*) (size_t)) xmalloc, gmp_realloc,
 			   gmp_free);
 
-  /* The smallest number that is printed without exponents */
-  mpf_init_set_d (float_print_min, 0.001);
+  /* Numbers with smaller exponents than this are printed in scientific
+     notation. */
+  float_print_min = -4;
 
-  /* The largest number that is printed without exponents */
-  mpf_init_set_ui (float_print_max, 10000000UL);
+  /* Numbers with larger exponents than this are printed in scientific
+     notation. */
+  float_print_max = 8;
 
   /* Prepare the bignum/bigfloat random number generator */
   gmp_randinit_default (random_state);