]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
c-common.c (builtin_define_with_hex_fp_value): New.
authorRichard Henderson <rth@redhat.com>
Wed, 4 Sep 2002 17:11:32 +0000 (10:11 -0700)
committerRichard Henderson <rth@gcc.gnu.org>
Wed, 4 Sep 2002 17:11:32 +0000 (10:11 -0700)
        * c-common.c (builtin_define_with_hex_fp_value): New.
        (builtin_define_float_constants): Use it.  Fix H_FLOAT mant_dig.

From-SVN: r56800

gcc/ChangeLog
gcc/c-common.c

index 0778a30aa5ddd39ad90330fa97f03e3388fe59ed..511d469b0964a244d9462a014ef4d2e4e8416551 100644 (file)
@@ -1,3 +1,8 @@
+2002-09-04  Richard Henderson  <rth@redhat.com>
+
+       * c-common.c (builtin_define_with_hex_fp_value): New.
+       (builtin_define_float_constants): Use it.  Fix H_FLOAT mant_dig.
+
 2002-09-04  Janis Johnson  <janis187@us.ibm.com>
 
        * doc/invoke.texi (-fshort-wchar): Move to Code Generation Options.
index 2cdc4357d2e83be89439b6e60ec1bdbecbdb30eb..1a03d7c8b1cdfc9d1302c340ef105d4abadec7bb 100644 (file)
@@ -764,6 +764,9 @@ static void builtin_define_with_value PARAMS ((const char *, const char *,
                                                int));
 static void builtin_define_with_int_value PARAMS ((const char *,
                                                   HOST_WIDE_INT));
+static void builtin_define_with_hex_fp_value PARAMS ((const char *, tree,
+                                                     int, const char *,
+                                                     const char *));
 static void builtin_define_type_max PARAMS ((const char *, tree, int));
 static void cpp_define_data_format PARAMS ((cpp_reader *));
 static void builtin_define_type_precision PARAMS ((const char *, tree));
@@ -4806,6 +4809,7 @@ builtin_define_float_constants (name_prefix, fp_suffix, type)
   char name[64], buf[128];
   int mant_dig, max_exp, min_exp;
   int dig, min_10_exp, max_10_exp;
+  int decimal_dig;
 
   /* ??? This information should be shared with real.c.  */
 
@@ -4879,7 +4883,7 @@ builtin_define_float_constants (name_prefix, fp_suffix, type)
            }
          break;
        case 128: /* H_FLOAT */
-         mant_dig = 114;
+         mant_dig = 113;
          min_exp = -16383;
          max_exp = 16383;
          break;
@@ -4994,54 +4998,56 @@ builtin_define_float_constants (name_prefix, fp_suffix, type)
   sprintf (name, "__%s_MAX_10_EXP__", name_prefix);
   builtin_define_with_int_value (name, max_10_exp);
 
+  /* The number of decimal digits, n, such that any floating-point number
+     can be rounded to n decimal digits and back again without change to
+     the value. 
+
+       p * log10(b)                    if b is a power of 10
+       ceil(1 + p * log10(b))          otherwise
+
+     The only macro we care about is this number for the widest supported
+     floating type, but we want this value for rendering constants below.  */
+  {
+    double d_decimal_dig = 1 + mant_dig * log10_b;
+    decimal_dig = d_decimal_dig;
+    if (decimal_dig < d_decimal_dig)
+      decimal_dig++;
+  }
+  if (type == long_double_type_node)
+    builtin_define_with_int_value ("__DECIMAL_DIG__", decimal_dig);
+
   /* Since, for the supported formats, B is always a power of 2, we
-     construct the following numbers directly as a hexadecimal constants.  */
+     construct the following numbers directly as a hexadecimal
+     constants.  */
 
   /* The maximum representable finite floating-point number,
-       (1 - b**-p) * b**max_exp  */
+     (1 - b**-p) * b**max_exp  */
   {
     int i, n;
     char *p;
-    sprintf (name, "__%s_MAX__", name_prefix);
 
     strcpy (buf, "0x0.");
-
     n = mant_dig * log2_b;
     for (i = 0, p = buf + 4; i + 3 < n; i += 4)
       *p++ = 'f';
     if (i < n)
       *p++ = "08ce"[n - i];
-    sprintf (p, "p%d%s", max_exp * log2_b, fp_suffix);
-    builtin_define_with_value (name, buf, 0);
+    sprintf (p, "p%d", max_exp * log2_b);
   }
+  sprintf (name, "__%s_MAX__", name_prefix);
+  builtin_define_with_hex_fp_value (name, type, decimal_dig, buf, fp_suffix);
 
-  /* The minimum normalized positive floating-point number, b**(min_exp-1).  */
+  /* The minimum normalized positive floating-point number,
+     b**(min_exp-1).  */
   sprintf (name, "__%s_MIN__", name_prefix);
-  sprintf (buf, "0x1p%d%s", (min_exp - 1) * log2_b, fp_suffix);
-  builtin_define_with_value (name, buf, 0);
+  sprintf (buf, "0x1p%d", (min_exp - 1) * log2_b);
+  builtin_define_with_hex_fp_value (name, type, decimal_dig, buf, fp_suffix);
 
   /* The difference between 1 and the least value greater than 1 that is
      representable in the given floating point type, b**(1-p).  */
   sprintf (name, "__%s_EPSILON__", name_prefix);
-  sprintf (buf, "0x1p%d%s", (1 - mant_dig) * log2_b, fp_suffix);
-  builtin_define_with_value (name, buf, 0);
-
-  if (type == long_double_type_node)
-    {
-      /* The number of decimal digits, n, such that any floating-point number
-        in the widest supported floating type with pmax radix b digits can be
-        rounded to a floating-point number with n decimal digits and back
-        again without change to the value,
-
-               pmax log10(b)                   if b is a power of 10
-               ceil(1 + pmax * log10(b))       otherwise
-      */
-      double d_decimal_dig = 1 + mant_dig * log10_b;
-      int decimal_dig = d_decimal_dig;
-      if (decimal_dig < d_decimal_dig)
-       decimal_dig++;
-      builtin_define_with_int_value ("__DECIMAL_DIG__", decimal_dig);
-    }
+  sprintf (buf, "0x1p%d", (1 - mant_dig) * log2_b);
+  builtin_define_with_hex_fp_value (name, type, decimal_dig, buf, fp_suffix);
 }
 
 /* Hook that registers front end and target-specific built-ins.  */
@@ -5256,6 +5262,35 @@ builtin_define_with_int_value (macro, value)
   cpp_define (parse_in, buf);
 }
 
+/* Pass an object-like macro a hexadecimal floating-point value.  */
+static void
+builtin_define_with_hex_fp_value (macro, type, digits, hex_str, fp_suffix)
+     const char *macro;
+     tree type;
+     int digits;
+     const char *hex_str;
+     const char *fp_suffix;
+{
+  REAL_VALUE_TYPE real;
+  char dec_str[64], buf[256];
+
+  /* Hex values are really cool and convenient, except that they're
+     not supported in strict ISO C90 mode.  First, the "p-" sequence
+     is not valid as part of a preprocessor number.  Second, we get a
+     pedwarn from the preprocessor, which has no context, so we can't
+     suppress the warning with __extension__.
+
+     So instead what we do is construct the number in hex (because 
+     it's easy to get the exact correct value), parse it as a real,
+     then print it back out as decimal.  */
+
+  real = REAL_VALUE_HTOF (hex_str, TYPE_MODE (type));
+  REAL_VALUE_TO_DECIMAL (real, dec_str, digits);
+
+  sprintf (buf, "%s=%s%s", macro, dec_str, fp_suffix);
+  cpp_define (parse_in, buf);
+}
+
 /* Define MAX for TYPE based on the precision of the type, which is assumed
    to be signed.  IS_LONG is 1 for type "long" and 2 for "long long".  */