gawk-diffs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[gawk-diffs] [SCM] gawk branch, long-double, updated. 26bfdfdc9bb065dfc1


From: John Haque
Subject: [gawk-diffs] [SCM] gawk branch, long-double, updated. 26bfdfdc9bb065dfc1ea7f2494070f826e81b874
Date: Wed, 23 Jan 2013 12:27:58 +0000

This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "gawk".

The branch, long-double has been updated
       via  26bfdfdc9bb065dfc1ea7f2494070f826e81b874 (commit)
      from  ecf5161fabf105c8a50834e5bbc7ada5b322ce03 (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.

- Log -----------------------------------------------------------------
http://git.sv.gnu.org/cgit/gawk.git/commit/?id=26bfdfdc9bb065dfc1ea7f2494070f826e81b874

commit 26bfdfdc9bb065dfc1ea7f2494070f826e81b874
Author: John Haque <address@hidden>
Date:   Wed Jan 23 06:25:50 2013 -0600

    Use different routines to format long double integers and floats.

diff --git a/ChangeLog b/ChangeLog
index 361a0e8..d0daef3 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,9 @@
+2013-01-23         John Haque      <address@hidden>
+
+       * long_double.c (format_uint_1): New inline routines to format integers.
+       * long_double.h (format_float_1): Remove integer formatting code.
+       (format_awkldbl_printf): Use format_uint_1() to format integers.
+       
 2013-01-19         John Haque      <address@hidden>
 
        For C long double and without "%Lf" in printf, provide "%.0Lf" to
diff --git a/float128.c b/float128.c
index 0910a68..15582b8 100644
--- a/float128.c
+++ b/float128.c
@@ -34,28 +34,42 @@
 
 /* end of Macros from quadmath.h */
 
+
 #define LDBL_FRAC_BITS FLT128_MANT_DIG
+#define        LDBL_INT_BITS   128
 
 #define AWKLDBL        __float128
 #define LDBL_VAL(n)    (*((AWKLDBL *) (n)->qnumbr))
 #define LDC(x)         x##Q
 
-#define        LDBL_INT_BITS   128
-
 #define get_long_double(d)     emalloc(d, void *, sizeof(AWKLDBL), "float128")
 #define free_long_double(d)    efree(d)
 
-static int format_float_1(char *str, size_t size, const char *format, ...);
+static int format_float_1(char *str, size_t size, const char *format, int fw, 
int prec, AWKLDBL x);
+static int format_uint_finite_p(char *str, size_t size, AWKLDBL x);
+
+/*
+ * format_uint_1 --- format a AWKLDBL as an unsigned integer. The double value
+ *     must be finite and >= 0.
+ */
+
+static inline int
+format_uint_1(char *str, size_t size, AWKLDBL x)
+{
+       int ret;
+       if ((ret = format_uint_finite_p(str, size, x)) < 0)
+               return snprintf(str, size, "%.0f", (double) x);
+       return ret;
+}
+
 static AWKLDBL double_to_int(AWKLDBL);
 
+/* if have __float128, also have strtold. No ? */
+
 static inline AWKLDBL
 gawk_strtold(const char *str, char **endptr)
 {
-#ifdef HAVE_STRTOLD
        return strtold(str, endptr);
-#else
-       return strtod(str, endptr);
-#endif
 }
 
 /* Define isnan() and isinf() before including the two files */
@@ -73,8 +87,10 @@ static inline int isinf_awkldbl(AWKLDBL x) { return isnan(x 
- x); }
 #define isinf isinf_awkldbl
 
 #define GAWK_INFINITY  HUGE_VALQ
-#define GAWK_NAN       (LDC(0.0Q) / LDC(0.0Q))
+#define GAWK_NAN       (LDC(0.0) / LDC(0.0))
+
 
+/* XXX: Don't want floorl() or ceill() */ 
 
 #ifdef HAVE_FLOORL
 #undef HAVE_FLOORL
diff --git a/long_double.c b/long_double.c
index a2fc40e..593cd97 100644
--- a/long_double.c
+++ b/long_double.c
@@ -181,9 +181,40 @@ gawk_sqrtl(AWKLDBL x)
 #endif /* PRINTF_HAS_LF_FORMAT */
 
 #if ! defined(PRINTF_HAS_LF_FORMAT)
-static int format_float_1(char *str, size_t size, const char *format, ...);
+static int format_float_1(char *str, size_t size, const char *format, int fw, 
int prec, AWKLDBL x);
+static int format_uint_finite_p(char *str, size_t size, AWKLDBL x);
+
+/*
+ * format_uint_finite_p --- format a long double as an unsigned integer. The 
double value
+ *     must be finite and >= 0.
+ */
+
+static inline int
+format_uint_1(char *str, size_t size, AWKLDBL x)
+{
+       int ret;
+       if ((ret = format_uint_finite_p(str, size, x)) < 0)
+               return snprintf(str, size, "%.0f", (double) x);
+       return ret;
+}
 #else
-#define format_float_1 snprintf
+
+/*
+ * format_float_1 --- format a single AWKLDBL value according to FORMAT.
+ *     The value must be finite.       
+ */
+
+static inline int
+format_float_1(char *str, size_t size, const char *format, int fw, int prec, 
AWKLDBL x)
+{
+       return snprintf(str, size, format, fw, prec, x);
+}
+
+static inline int
+format_uint_1(char *str, size_t size, AWKLDBL x)
+{
+       return snprintf(str, size, "%.0Lf", x);
+}
 #endif
 
 #if ! (defined(HAVE_FLOORL) && defined(HAVE_CEILL))
diff --git a/long_double.h b/long_double.h
index f117bb8..023ece1 100644
--- a/long_double.h
+++ b/long_double.h
@@ -1202,8 +1202,8 @@ get_ieee_magic_val(const char *val)
        if (val == ptr) { /* Older strtod implementations don't support inf or 
nan. */
                if (first) {
                        first = false;
-                       nan = gawk_sqrtl(-LDC(1.0));
-                       inf = -gawk_logl(LDC(0.0));
+                       nan = gawk_sqrtl(-LDC(1.0));    /* FIXME -- this isn't 
right */
+                       inf = -gawk_logl(LDC(0.0));     /* Ditto */
                }
                v = ((val[1] == 'i' || val[1] == 'I') ? inf : nan);
                if (val[0] == '-')
@@ -1429,7 +1429,7 @@ format_awkldbl_printf(NODE *arg, struct format_spec 
*spec, struct print_fmt_buf
                 * Use snprintf return value to tell if there
                 * is enough room in the buffer or not.
                 */
-               while ((i = format_float_1(intbuf, intbuf_size, "%.0Lf", 
tmpval)) >= intbuf_size) {
+               while ((i = format_uint_1(intbuf, intbuf_size, tmpval)) >= 
intbuf_size) {
                        if (intbuf == stackbuf)
                                intbuf = NULL;
                        intbuf_size = i + 1;
@@ -1725,8 +1725,8 @@ double_to_int(AWKLDBL x)
 #if ! defined(PRINTF_HAS_LF_FORMAT)
 
 /*
- * format_uint_finite_p --- format a double as an unsigned integer. The double 
value
- *     must be finite and >= 0.
+ * format_uint_finite_p --- format a AWKLDBL as an unsigned integer. The 
AWKLDBL value
+ *     must be finite and in the range 0 <= x < 2^LDBL_FRAC_BITS.
  */
 
 static int
@@ -1772,12 +1772,9 @@ format_uint_finite_p(char *str, size_t size, AWKLDBL x)
        gawk_uint_t d0, d1, d2, d3, d4, q;
        gawk_uint_t chunk[4];
 
-       assert(!!isnan(x) == 0);
-       assert(!!isinf(x) == 0);
        assert(x >= LDC(0.0));
 
-       if (size <= 35)         /* maximum size ever needed excluding 
terminating null */
-               return 35;
+       assert(size > 35);      /* maximum size ever needed excluding 
terminating null */
 
        if (gawk_floorl_finite_p(x, chunk) < LDC(0.0))  /* outside range */
                return -1;
@@ -1814,46 +1811,24 @@ format_uint_finite_p(char *str, size_t size, AWKLDBL x)
 }
 
 /*
- * format_float_1 --- format a single double value according to FORMAT.
- *     The value must be finite and >= 0.      
+ * format_float_1 --- format a single AWKLDBL value according to FORMAT.
+ *     The value must be finite.       
  */
 
 static int
-format_float_1(char *str, size_t size, const char *format, ...)
+format_float_1(char *str, size_t size, const char *format, int fw, int prec, 
AWKLDBL x)
 {
-        va_list argp;
        char alt_format[16];
        size_t len;
-       int ret = -1;
-       AWKLDBL x;
-
-        va_start(argp, format);
 
        len = strlen(format);
 
        /* expect %Lf, %LF, %Le, %LE, %Lg or %LG */
        assert(len >= 2 && format[len - 2] == 'L');
-       
+
        memcpy(alt_format, format, len - 2);
        alt_format[len - 2] = format[len - 1];  /* skip the `L' */ 
        alt_format[len - 1] = '\0';
-
-       if (strcmp(format, "%.0Lf") == 0) {
-               /* format as integer */
-               x = va_arg(argp, AWKLDBL);
-               va_end(argp);
-               if ((ret = format_uint_finite_p(str, size, x)) < 0)
-                       ret = snprintf(str, size, alt_format, (double) x);
-       } else {
-               int fw, prec;
-
-               fw = va_arg(argp, int);
-               prec = va_arg(argp, int);
-               x = va_arg(argp, AWKLDBL);
-               ret = snprintf(str, size, alt_format, fw, prec, (double) x);
-       }
-
-       va_end(argp);
-       return ret;
+       return snprintf(str, size, alt_format, fw, prec, (double) x);
 }
 #endif
diff --git a/misc/fp_math.awk b/misc/fp_math.awk
index 51583fa..80fe7d8 100644
--- a/misc/fp_math.awk
+++ b/misc/fp_math.awk
@@ -2,7 +2,9 @@
 
 #
 #      TODO:   * finish fmod().
-#              * replace all usages of %, and int() or any other math builtin; 
and() is ok!
+#              * replace all usages of %, and int() or any other math builtin; 
and() is ok!.
+#                implement double_to_int() and remove floor/ceil.
+#              * fix sqrt(x) for x > DBL_MAX or x < -DBL_MIN.
 #
 
 
@@ -370,9 +372,17 @@ function __log2( \
        return 2 * sum
 }
 
+function pow2(n, k)
+{
+       if (n <= 64)
+               return __POW2__[n]
+       for (k = 1; n > 64; n -= 64)
+               k *= __POW2__[64]
+       return k * __POW2__[n]
+}
 
 function fp_log(x,     \
-               k, i, y, ypow2, ypow_odd, sum, err, term, sqrt_2, sign)
+               k, i, y, ypow2, ypow_odd, sum, err, term, sign, high, low, mid)
 {
        #
        #       ln(x) = 2 * arctanh(y)
@@ -392,17 +402,33 @@ function fp_log(x,        \
                return __LOG2__
        k = 0
        if (x > 2) {
-               # FIXME -- use power2 table
-               while (x > 2) {
-                       x /= 2
-                       k++
+               low = 0
+               high = LDBL_MAX_EXP - 1         # XXX: should be 4 * 
LDBL_MAX_EXP - 1 if FLT_RADIX = 16
+               while (low <= high) {
+                       mid = int ((low + high) / 2)
+                       y = x / pow2(mid)
+                       if (y > 2)
+                               low = mid + 1
+                       else
+                               high = mid - 1
                }
+               x /= pow2(low)
+               k = low
+#              printf("x = %0.18e, k = %d\n", x / pow2(low), low)
+
        } else if (x < 1) {
-               # FIXME -- use power2 table
-               while (x < 1) {
-                       x *= 2
-                       k--
+               low = 0
+               high = LDBL_MAX_EXP - 1         # could be -LDBL_MIN_EXP, but 
no harm in using LDBL_MAX_EXP
+               while (low <= high) {
+                       mid = int ((low + high) / 2)
+                       y =  x * pow2(mid)
+                       if (y < 1)
+                               low = mid + 1
+                       else
+                               high = mid - 1
                }
+               x *= pow2(low)
+               k = -low
        }
 
        # arctanh(x) series has faster convergence when x is close to 1
@@ -724,7 +750,7 @@ function fixprec(str, numdigs, \
        if (str ~ /^[-+]?(nan|inf)/)
                return str
        if (! numdigs)
-               numdigs = __DIGITS__
+               numdigs = LDBL_DIG
        if (str ~ /^[-+]?0[\.]/)
                return str
        sign = ""
@@ -760,9 +786,24 @@ function fixprec(str, numdigs, \
 BEGIN {
        # define some constants
 
-       # reltive error < 5 X 10^-k for rounding to k significant digits
-       __DIGITS__ = 34
-       __REL_ERROR__ = 5.0e-34
+       LDBL_DIG = 33
+       # relative error < 5 X 10^-k for rounding to k significant digits
+       __REL_ERROR__ = 5.0e-35
+       LDBL_MAX_EXP = 16384
+       LDBL_MANT_DIG = 113
+
+       # We can read hex/octal numbers without using strtod/strtodl
+       if (0x10000000000000000 == 0x10000000000000001) {
+               # x86 long double
+               LDBL_MANT_DIG = 64
+               LDBL_DIG = 18
+               __REL_ERROR__ = 5.0e-20
+       } else if (0x400000000000000000000000000 == 
0x400000000000000000000000001) {
+               # double-double
+               LDBL_MANT_DIG = 106
+               LDBL_DIG = 31
+               LDBL_MAX_EXP = 309
+       }
 
        __PLUS_INF__ = "+inf" + 0
        __MINUS_INF__ = "-inf" + 0
@@ -774,15 +815,7 @@ BEGIN {
        __LOG2__ = __log2()     # cannot use fp_log()
        __PI_OVER_4__ = 4 * euler_atan_one_over(5) - euler_atan_one_over(239)
 
-
-##if LDBL_MANT_DIG == 64
-#       80 bit long double .. 18 or 34 digits?
-#      use 2^64 power 2 table
-##elif LDBL_MANT_DIG == 113
-#       128 bit long double .. 34 digits
-#      use 2^112 power 2 table
-##endif
-
+       # pre-calculate 2^0 - 2^64
        __POW2__[0] = 1
        for (i = 1; i <= 64; i++)
                __POW2__[i] = __POW2__[i - 1] * 2
diff --git a/misc/gawk_math.h b/misc/gawk_math.h
index e34bfae..909bd69 100644
--- a/misc/gawk_math.h
+++ b/misc/gawk_math.h
@@ -50,7 +50,7 @@ gawk_logl(AWKLDBL x)
 static AWKLDBL
 gawk_expl(AWKLDBL x)
 {
-#ifdef HAVE_LOGL
+#ifdef HAVE_EXPL
        return expl( (long double) x);
 #else
        return exp( (double) x);

-----------------------------------------------------------------------

Summary of changes:
 ChangeLog        |    6 ++++
 float128.c       |   32 ++++++++++++++++-----
 long_double.c    |   35 ++++++++++++++++++++++-
 long_double.h    |   47 +++++++------------------------
 misc/fp_math.awk |   79 ++++++++++++++++++++++++++++++++++++++---------------
 misc/gawk_math.h |    2 +-
 6 files changed, 131 insertions(+), 70 deletions(-)


hooks/post-receive
-- 
gawk



reply via email to

[Prev in Thread] Current Thread [Next in Thread]