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. e8561893a3ca3f7cee


From: John Haque
Subject: [gawk-diffs] [SCM] gawk branch, long-double, updated. e8561893a3ca3f7cee6ca23e4361abbb510502bb
Date: Sat, 12 Jan 2013 15:27:19 +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  e8561893a3ca3f7cee6ca23e4361abbb510502bb (commit)
       via  c5b44e77f250e364a5c3a677722d513f88977eef (commit)
       via  2fec7545cd5e31c073d72caf69ac3507302c919b (commit)
      from  42dd95107c29fc8f2e1ca370a083a2d63e17fb57 (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=e8561893a3ca3f7cee6ca23e4361abbb510502bb

commit e8561893a3ca3f7cee6ca23e4361abbb510502bb
Author: John Haque <address@hidden>
Date:   Sat Jan 12 09:24:26 2013 -0600

    Adding cast to long double, and suffix L for constants.

diff --git a/TODO.LDBL b/TODO.LDBL
new file mode 100644
index 0000000..3e2732f
--- /dev/null
+++ b/TODO.LDBL
@@ -0,0 +1,20 @@
+* Don't trust compiler with type promotion:
+       **** If an operation involves two operands, and one of them is of type 
long double,
+       **** the other one is converted to long double. 
+The latest version of GCC I have (4.4.3) seems to have different ideas. Start 
using cast
+to long double even when it seems unnecessary address@hidden@#
+
+Also, append suffix L to all long double constants.
+
+* Convert gawk math routines to C for platforms lacking any. Without ceil() 
and floor()
+for long doubles, these can't even get 64 bit integers!
+       -- finish fp_fmod() in misc/fp_math.awk.
+       -- write test script(s) to verify (some) output, but DON'T add it to 
the dist.
+       80 bit vs 128 bit, and the C math library CANNOT be trusted to produce
+       correctly rounded results. Double check any discrepencies using 
arbitrary-precision
+       math.
+
+* Don't use adjust_uint(uintmax_t n) from floatcomp.c, it is for AWKNUM. What 
is the point
+of floor() and ceil() wrappers? Don't have a clue.
+
+
diff --git a/long_double.c b/long_double.c
index 7d94afd..e85fea2 100644
--- a/long_double.c
+++ b/long_double.c
@@ -26,19 +26,18 @@
 #include "awk.h"
 
 #ifdef USE_LONG_DOUBLE
-#include "math.h"
+#include <math.h>
 #include "random.h"
 #include "floatmagic.h"        /* definition of isnan */
 
 #include "format.h"
 
-
 #define AWKLDBL        long double
 
-
 #include "long_double.h"
 
-#define LDBL(n)        (*((AWKLDBL *) (n)->qnumbr))
+#define LDBL_VAL(n)    (*((AWKLDBL *) (n)->qnumbr))
+#define LDC(x)         x##L
 
 /* Can declare these, since we always use the random shipped with gawk */
 extern char *initstate(unsigned long seed, char *state, long n);
@@ -189,12 +188,12 @@ awkldbl_init(bltin_t **numbr_bltins)
 
        /* set the numeric value of null string */
        get_long_double(Nnull_string->qnumbr);
-       LDBL(Nnull_string) = 0.0;
+       LDBL_VAL(Nnull_string) = LDC(0.0);
        Nnull_string->flags |= (NUMCUR|NUMBER);
 
        /* initialize TRUE and FALSE nodes */
-       false_node = make_awkldbl(0.0);
-       true_node = make_awkldbl(1.0);
+       false_node = make_awkldbl(LDC(0.0));
+       true_node = make_awkldbl(LDC(1.0));
        false_node->flags |= NUMINT;
        true_node->flags |= NUMINT;
 
@@ -207,7 +206,7 @@ awkldbl_init(bltin_t **numbr_bltins)
 static unsigned long
 awkldbl_toulong(const NODE *n)
 {
-       return LDBL(n);
+       return LDBL_VAL(n);
 }
 
 /* awkldbl_tolong --- conversion to long */
@@ -215,7 +214,7 @@ awkldbl_toulong(const NODE *n)
 static long
 awkldbl_tolong(const NODE *n)
 {
-       return LDBL(n);
+       return LDBL_VAL(n);
 }
 
 /* awkldbl_todouble --- conversion to double */
@@ -223,7 +222,7 @@ awkldbl_tolong(const NODE *n)
 static double
 awkldbl_todouble(const NODE *n)
 {
-       return LDBL(n);
+       return LDBL_VAL(n);
 }
 
 /* awkldbl_touintmax_t --- conversion to uintmax_t */
@@ -231,7 +230,7 @@ awkldbl_todouble(const NODE *n)
 static uintmax_t
 awkldbl_touintmax_t(const NODE *n)
 {
-       return LDBL(n);
+       return LDBL_VAL(n);
 }
 
 /* awkldbl_sgn --- return 1 if number > 0, zero if number == 0, and -1 if 
number < 0 */
@@ -239,8 +238,8 @@ awkldbl_touintmax_t(const NODE *n)
 static int
 awkldbl_sgn(const NODE *n)
 {
-       AWKLDBL d = LDBL(n);
-       return (d < 0.0 ? -1 : d > 0.0);
+       AWKLDBL d = LDBL_VAL(n);
+       return (d < LDC(0.0) ? -1 : d > LDC(0.0));
 }
 
 /* awkldbl_isinteger --- check if a number is an integer */
@@ -248,7 +247,7 @@ awkldbl_sgn(const NODE *n)
 static bool
 awkldbl_isinteger(const NODE *n)
 {
-       AWKLDBL d = LDBL(n);
+       AWKLDBL d = LDBL_VAL(n);
 
        if (isnan(d) || isinf(d))
                return false;
@@ -260,7 +259,7 @@ awkldbl_isinteger(const NODE *n)
 static bool
 awkldbl_isnan(const NODE *n)
 {
-       return isnan(LDBL(n));
+       return isnan(LDBL_VAL(n));
 }
 
 /* awkldbl_isinf --- check if number is infinity */
@@ -268,7 +267,7 @@ awkldbl_isnan(const NODE *n)
 static bool
 awkldbl_isinf(const NODE *n)
 {
-       return isinf(LDBL(n));
+       return isinf(LDBL_VAL(n));
 }
 
 /* negate_awkldbl --- negate number in NODE */
@@ -276,7 +275,7 @@ awkldbl_isinf(const NODE *n)
 static void
 negate_awkldbl(NODE *n)
 {
-       LDBL(n) = - LDBL(n);
+       LDBL_VAL(n) = - LDBL_VAL(n);
 }
 
 /* awkldbl_add --- add two numbers */
@@ -284,7 +283,7 @@ negate_awkldbl(NODE *n)
 static NODE *
 awkldbl_add(const NODE *t1, const NODE *t2)
 {
-       return make_awkldbl(LDBL(t1) + LDBL(t2));
+       return make_awkldbl(LDBL_VAL(t1) + LDBL_VAL(t2));
 }
 
 /* awkldbl_sub --- subtract two numbers */
@@ -292,7 +291,7 @@ awkldbl_add(const NODE *t1, const NODE *t2)
 static NODE *
 awkldbl_sub(const NODE *t1, const NODE *t2)
 {
-       return make_awkldbl(LDBL(t1) - LDBL(t2));
+       return make_awkldbl(LDBL_VAL(t1) - LDBL_VAL(t2));
 }
 
 /* awkldbl_mul --- multiply two numbers */
@@ -300,7 +299,7 @@ awkldbl_sub(const NODE *t1, const NODE *t2)
 static NODE *
 awkldbl_mul(const NODE *t1, const NODE *t2)
 {
-       return make_awkldbl(LDBL(t1) * LDBL(t2));
+       return make_awkldbl(LDBL_VAL(t1) * LDBL_VAL(t2));
 }
 
 /* awkldbl_add --- quotient of two numbers */
@@ -308,10 +307,10 @@ awkldbl_mul(const NODE *t1, const NODE *t2)
 static NODE *
 awkldbl_div(const NODE *t1, const NODE *t2)
 {
-       AWKLDBL d = LDBL(t2);
+       AWKLDBL d = LDBL_VAL(t2);
        if (d == 0)
                fatal(_("division by zero attempted"));
-       return make_awkldbl(LDBL(t1) / d);
+       return make_awkldbl(LDBL_VAL(t1) / d);
 }
 
 /* awkldbl_add_long --- add long value to a number */
@@ -319,7 +318,7 @@ awkldbl_div(const NODE *t1, const NODE *t2)
 static NODE *
 awkldbl_add_long(const NODE *t1, long n)
 {
-       return make_awkldbl(LDBL(t1) + n);
+       return make_awkldbl(LDBL_VAL(t1) + (AWKLDBL) n);
 }
 
 /* awkldbl_copy --- copy a number */
@@ -327,7 +326,7 @@ awkldbl_add_long(const NODE *t1, long n)
 static NODE *
 awkldbl_copy(const NODE *t1)
 {
-       return make_awkldbl(LDBL(t1));
+       return make_awkldbl(LDBL_VAL(t1));
 }
 
 /* awkldbl_update_var --- update a special variable from internal variables */
@@ -338,14 +337,14 @@ awkldbl_update_var(NODE *var)
        NODE *val = var->var_value;
        AWKLDBL d;
 
-       d = LDBL(val);
+       d = LDBL_VAL(val);
        if (var == NR_node) {
                if (MNR == 0 && d != NR) {
                        unref(val);
-                       val = NR_node->var_value = make_awkldbl(NR);
+                       val = NR_node->var_value = make_awkldbl((AWKLDBL) NR);
                } else if (MNR != 0) {
                        unref(val);
-                       d = ((AWKLDBL) MNR) * LONG_MAX + NR;
+                       d = ((AWKLDBL) MNR) * LONG_MAX + (AWKLDBL) NR;
                        val = var->var_value = make_awkldbl(d);
                }
                return val;
@@ -354,10 +353,10 @@ awkldbl_update_var(NODE *var)
        assert(var == FNR_node);
        if (MFNR == 0 && d != FNR) {
                unref(val);
-               val = FNR_node->var_value = make_awkldbl(FNR);
+               val = FNR_node->var_value = make_awkldbl((AWKLDBL) FNR);
        } else if (MFNR != 0) {
                unref(val);
-               d = ((AWKLDBL) MFNR) * LONG_MAX + FNR;
+               d = ((AWKLDBL) MFNR) * LONG_MAX + (AWKLDBL) FNR;
                val = var->var_value = make_awkldbl(d);
        }
        return val;
@@ -374,7 +373,7 @@ awkldbl_set_var(const NODE *var)
        NODE *val = var->var_value;
        AWKLDBL d;
 
-       d = LDBL(val);
+       d = LDBL_VAL(val);
        if (var == NR_node) {
                MNR = d / LONG_MAX;
                NR = d - ((AWKLDBL) MNR) * LONG_MAX;
@@ -421,7 +420,7 @@ make_awkldbl(AWKLDBL x)
        getnode(r);
        r->type = Node_val;
        get_long_double(r->qnumbr);
-       LDBL(r) = x;
+       LDBL_VAL(r) = x;
        r->flags = MALLOC|NUMBER|NUMCUR;
        r->valref = 1;
        r->stptr = NULL;
@@ -442,7 +441,7 @@ make_awknum(AWKNUM x)
        getnode(r);
        r->type = Node_val;
        get_long_double(r->qnumbr);
-       LDBL(r) = (AWKLDBL) x;
+       LDBL_VAL(r) = (AWKLDBL) x;
        r->flags = MALLOC|NUMBER|NUMCUR;
        r->valref = 1;
        r->stptr = NULL;
@@ -494,8 +493,8 @@ do_lshift(int nargs)
 
        (void) force_number(s1);
        (void) force_number(s2);
-       val = LDBL(s1);
-       shift = LDBL(s2);
+       val = LDBL_VAL(s1);
+       shift = LDBL_VAL(s2);
 
        if (do_lint) {
                if (val < 0 || shift < 0)
@@ -536,8 +535,8 @@ do_rshift(int nargs)
        }
        (void) force_number(s1);
        (void) force_number(s2);
-       val = LDBL(s1);
-       shift = LDBL(s2);
+       val = LDBL_VAL(s1);
+       shift = LDBL_VAL(s2);
        if (do_lint) {
                if (val < 0 || shift < 0)
                        lintwarn(_("rshift(%Lf, %Lf): negative values will give 
strange results"),
@@ -578,7 +577,7 @@ do_and(int nargs)
                        lintwarn(_("and: argument %d is non-numeric"), i);
 
                (void) force_number(s1);
-               val = LDBL(s1);
+               val = LDBL_VAL(s1);
                if (do_lint && val < 0)
                        lintwarn(_("and: argument %d negative value %Lg will 
give strange results"),
                                        i, val);
@@ -611,7 +610,7 @@ do_or(int nargs)
                        lintwarn(_("or: argument %d is non-numeric"), i);
 
                (void) force_number(s1);
-               val = LDBL(s1);
+               val = LDBL_VAL(s1);
                if (do_lint && val < 0)
                        lintwarn(_("or: argument %d negative value %Lg will 
give strange results"),
                                        i, val);
@@ -645,7 +644,7 @@ do_xor(int nargs)
                        lintwarn(_("xor: argument %d is non-numeric"), i);
 
                (void) force_number(s1);
-               val = LDBL(s1);
+               val = LDBL_VAL(s1);
                if (do_lint && val < 0)
                        lintwarn(_("xor: argument %d negative value %Lg will 
give strange results"),
                                        i, val);
@@ -674,7 +673,7 @@ do_compl(int nargs)
        if (do_lint && (tmp->flags & (NUMCUR|NUMBER)) == 0)
                lintwarn(_("compl: received non-numeric argument"));
        (void) force_number(tmp);
-       d = LDBL(tmp);
+       d = LDBL_VAL(tmp);
        DEREF(tmp);
 
        if (do_lint) {
@@ -746,7 +745,7 @@ nondec2awkldbl(char *str, size_t len)
                        default:
                                goto done;
                        }
-                       retval = (retval * 16) + val;
+                       retval = (retval * LDC(16.0)) + (AWKLDBL) val;
                }
        } else if (*str == '0') {
                for (; len > 0; len--) {
@@ -756,7 +755,7 @@ nondec2awkldbl(char *str, size_t len)
                                str = start;
                                goto decimal;
                        }
-                       retval = (retval * 8) + (*str - '0');
+                       retval = (retval * LDC(8.0)) + (AWKLDBL) (*str - '0');
                        str++;
                }
        } else {
@@ -820,7 +819,7 @@ do_srand(int nargs)
                if (do_lint && (tmp->flags & (NUMCUR|NUMBER)) == 0)
                        lintwarn(_("srand: received non-numeric argument"));
                (void) force_number(tmp);
-               d = LDBL(tmp);
+               d = LDBL_VAL(tmp);
                srandom((unsigned int) (save_seed = (long) d));
                DEREF(tmp);
        }
@@ -846,7 +845,7 @@ str2awkldbl(char *str, char **endptr, int base, bool 
is_integer ATTRIBUTE_UNUSED
                errno = 0;
                d = gawk_strtold(str, endptr);
                if (errno != 0)
-                       d = 0;
+                       d = LDC(0.0);
        } else {
                if (base == 8 || base == 16)
                        d = nondec2awkldbl(str, strlen(str));
@@ -855,7 +854,7 @@ str2awkldbl(char *str, char **endptr, int base, bool 
is_integer ATTRIBUTE_UNUSED
                        errno = 0;
                        d = gawk_strtold(str, NULL);
                        if (errno != 0)
-                               d = 0;
+                               d = LDC(0.0);
                        errno = 0;
                }
        }
@@ -876,10 +875,10 @@ awkldbl_mod(const NODE *t1, const NODE *t2)
 {
        AWKLDBL d2;
 
-       d2 = LDBL(t2);
-       if (d2 == 0)
+       d2 = LDBL_VAL(t2);
+       if (d2 == LDC(0.0))
                fatal(_("division by zero attempted in `%%'"));
-       return make_awkldbl(gawk_fmodl(LDBL(t1), d2));
+       return make_awkldbl(gawk_fmodl(LDBL_VAL(t1), d2));
 }
 
 /* awkldbl_pow --- power function */
@@ -887,7 +886,7 @@ awkldbl_mod(const NODE *t1, const NODE *t2)
 static NODE *
 awkldbl_pow(const NODE *t1, const NODE *t2)
 {
-       return make_awkldbl(calc_exp(LDBL(t1), LDBL(t2)));
+       return make_awkldbl(calc_exp(LDBL_VAL(t1), LDBL_VAL(t2)));
 }
 
 
@@ -899,7 +898,7 @@ awkldbl_pow(const NODE *t1, const NODE *t2)
 static AWKLDBL
 calc_exp_posint(AWKLDBL x, long n)
 {
-       AWKLDBL mult = 1;
+       AWKLDBL mult = LDC(1.0);
 
        while (n > 1) {
                if ((n % 2) == 1)
@@ -915,13 +914,13 @@ calc_exp_posint(AWKLDBL x, long n)
 static AWKLDBL
 calc_exp(AWKLDBL x1, AWKLDBL x2)
 {
-       long lx;
+       long lx = x2;
 
-       if ((lx = x2) == x2) {          /* integer exponent */
+       if (((AWKLDBL) lx) == x2) {             /* integer exponent */
                if (lx == 0)
-                       return 1;
+                       return LDC(1.0);
                return (lx > 0) ? calc_exp_posint(x1, lx)
-                               : 1.0 / calc_exp_posint(x1, -lx);
+                               : LDC(1.0) / calc_exp_posint(x1, -lx);
        }
        return gawk_powl(x1, x2);
 }
@@ -939,8 +938,8 @@ cmp_awkldbls(const NODE *t1, const NODE *t2)
         * comparison at the awk level is a different issue, and needs to be 
dealt
         * with in the interpreter for each opcode seperately.
         */
-       AWKLDBL d1 = LDBL(t1);
-       AWKLDBL d2 = LDBL(t2);
+       AWKLDBL d1 = LDBL_VAL(t1);
+       AWKLDBL d2 = LDBL_VAL(t2);
 
        if (isnan(d1))
                return ! isnan(d2);
@@ -973,7 +972,7 @@ force_awkldbl(NODE *n)
        /* Note: only set NUMCUR if we actually convert some digits */
 
        get_long_double(n->qnumbr);
-       LDBL(n) = 0.0;
+       LDBL_VAL(n) = LDC(0.0);
 
        if (n->stlen == 0) {
                return n;
@@ -994,7 +993,7 @@ force_awkldbl(NODE *n)
                        if ((n->flags & MAYBE_NUM) != 0)
                                n->flags &= ~MAYBE_NUM;
                        n->flags |= NUMBER|NUMCUR;
-                       LDBL(n) = get_ieee_magic_val(n->stptr);
+                       LDBL_VAL(n) = get_ieee_magic_val(n->stptr);
                        return n;
                }
                /* else
@@ -1024,7 +1023,7 @@ force_awkldbl(NODE *n)
 
        if (cpend - cp == 1) {          /* only one character */
                if (isdigit((unsigned char) *cp)) {     /* it's a digit! */
-                       LDBL(n) = (AWKLDBL)(*cp - '0');
+                       LDBL_VAL(n) = (AWKLDBL)(*cp - '0');
                        n->flags |= newflags;
                        n->flags |= NUMCUR;
                        if (cp == n->stptr)             /* no leading spaces */
@@ -1036,7 +1035,7 @@ force_awkldbl(NODE *n)
        if (do_non_decimal_data) {      /* main.c assures false if do_posix */
                errno = 0;
                if (! do_traditional && get_numbase(cp, true) != 10) {
-                       LDBL(n) = nondec2awkldbl(cp, cpend - cp);
+                       LDBL_VAL(n) = nondec2awkldbl(cp, cpend - cp);
                        n->flags |= NUMCUR;
                        ptr = cpend;
                        goto finish;
@@ -1046,7 +1045,7 @@ force_awkldbl(NODE *n)
        errno = 0;
        save = *cpend;
        *cpend = '\0';
-       LDBL(n) = gawk_strtold((const char *) cp, &ptr);
+       LDBL_VAL(n) = gawk_strtold((const char *) cp, &ptr);
 
        /* POSIX says trailing space is OK for NUMBER */
        while (isspace((unsigned char) *ptr))
@@ -1108,7 +1107,7 @@ format_awkldbl_val(const char *format, int index, NODE *s)
         * < and > so that things work correctly on systems with 64 bit 
integers.
         */
 
-       d = LDBL(s);
+       d = LDBL_VAL(s);
 
        if ((s->flags & STRCUR) != 0)
                efree(s->stptr);
@@ -1116,7 +1115,7 @@ format_awkldbl_val(const char *format, int index, NODE *s)
 
        /* not an integral value, or out of range */
        if ((ival = double_to_int(d)) != d
-                       || ival <= LONG_MIN || ival >= LONG_MAX
+                       || ival <= (AWKLDBL) LONG_MIN || ival >= (AWKLDBL) 
LONG_MAX
        ) {
                struct format_spec spec;
                struct print_fmt_buf *outb;
@@ -1209,8 +1208,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(-1.0);
-                       inf = -gawk_logl(0.0);
+                       nan = gawk_sqrtl(-LDC(1.0));
+                       inf = -gawk_logl(LDC(0.0));
                }
                v = ((val[1] == 'i' || val[1] == 'I') ? inf : nan);
                if (val[0] == '-')
@@ -1225,7 +1224,7 @@ get_ieee_magic_val(const char *val)
 static AWKLDBL
 double_to_int(AWKLDBL d)
 {
-       if (d >= 0)
+       if (d >= LDC(0.0))
                d = gawk_floorl(d);
        else
                d = gawk_ceill(d);
@@ -1244,7 +1243,7 @@ do_int(int nargs)
        if (do_lint && (tmp->flags & (NUMCUR|NUMBER)) == 0)
                lintwarn(_("int: received non-numeric argument"));
        (void) force_number(tmp);
-       d = LDBL(tmp);
+       d = LDBL_VAL(tmp);
        DEREF(tmp);
        return make_awkldbl(double_to_int(d));
 }
@@ -1261,8 +1260,8 @@ do_log(int nargs)
        if (do_lint && (tmp->flags & (NUMCUR|NUMBER)) == 0)
                lintwarn(_("log: received non-numeric argument"));
        (void) force_number(tmp);
-       arg = LDBL(tmp);
-       if (arg < 0.0)
+       arg = LDBL_VAL(tmp);
+       if (arg < LDC(0.0))
                warning(_("log: received negative argument %Lg"), arg);
        d = gawk_logl(arg);
        DEREF(tmp);
@@ -1281,9 +1280,9 @@ do_sqrt(int nargs)
        if (do_lint && (tmp->flags & (NUMCUR|NUMBER)) == 0)
                lintwarn(_("sqrt: received non-numeric argument"));
        (void) force_number(tmp);
-       arg = LDBL(tmp);
+       arg = LDBL_VAL(tmp);
        DEREF(tmp);
-       if (arg < 0.0)
+       if (arg < LDC(0.0))
                warning(_("sqrt: called with negative argument %Lg"), arg);
        return make_awkldbl(gawk_sqrtl(arg));
 }
@@ -1300,7 +1299,7 @@ do_exp(int nargs)
        if (do_lint && (tmp->flags & (NUMCUR|NUMBER)) == 0)
                lintwarn(_("exp: received non-numeric argument"));
        (void) force_number(tmp);
-       d = LDBL(tmp);
+       d = LDBL_VAL(tmp);
        DEREF(tmp);
        errno = 0;
        res = gawk_expl(d);
@@ -1327,8 +1326,8 @@ do_atan2(int nargs)
        }
        (void) force_number(t1);
        (void) force_number(t2);
-       d1 = LDBL(t1);
-       d2 = LDBL(t2);
+       d1 = LDBL_VAL(t1);
+       d2 = LDBL_VAL(t2);
        DEREF(t1);
        DEREF(t2);
        return make_awkldbl(gawk_atan2l(d1, d2));
@@ -1347,7 +1346,7 @@ do_sin(int nargs)
        if (do_lint && (tmp->flags & (NUMCUR|NUMBER)) == 0)
                lintwarn(_("sin: received non-numeric argument"));
        (void) force_number(tmp);
-       d = gawk_sinl(LDBL(tmp));
+       d = gawk_sinl(LDBL_VAL(tmp));
        DEREF(tmp);
        return make_awkldbl(d);
 }
@@ -1364,7 +1363,7 @@ do_cos(int nargs)
        if (do_lint && (tmp->flags & (NUMCUR|NUMBER)) == 0)
                lintwarn(_("cos: received non-numeric argument"));
        (void) force_number(tmp);
-       d = gawk_cosl(LDBL(tmp));
+       d = gawk_cosl(LDBL_VAL(tmp));
        DEREF(tmp);
        return make_awkldbl(d);
 }
@@ -1380,12 +1379,12 @@ do_strtonum(int nargs)
        tmp = POP_SCALAR();
        if ((tmp->flags & (NUMBER|NUMCUR)) != 0) {
                (void) force_number(tmp);
-               d = LDBL(tmp);
+               d = LDBL_VAL(tmp);
        } else if (get_numbase(tmp->stptr, use_lc_numeric) != 10)
                d = nondec2awkldbl(tmp->stptr, tmp->stlen);
        else {
                (void) force_number(tmp);
-               d = LDBL(tmp);
+               d = LDBL_VAL(tmp);
        }
 
        DEREF(tmp);
@@ -1413,7 +1412,7 @@ format_awkldbl_printf(NODE *arg, struct format_spec 
*spec, struct print_fmt_buf
 #      define CEND             cpbuf_end(outb)
 #      define CPBUF            cpbuf(outb)
 
-       tmpval = LDBL(arg);
+       tmpval = LDBL_VAL(arg);
        spec->fill = space_string;
        spec->chbuf = lchbuf;
 
@@ -1431,17 +1430,17 @@ format_awkldbl_printf(NODE *arg, struct format_spec 
*spec, struct print_fmt_buf
                 * ``The result of converting a zero value with a
                 * precision of zero is no characters.''
                 */
-               if (spec->have_prec && spec->prec == 0 && tmpval == (AWKLDBL) 
0) {
+               if (spec->have_prec && spec->prec == 0 && tmpval == LDC(0.0)) {
                        pr_num_tail(cp, spec->prec, spec, outb);
                        return 0;
                }
 
-               if (tmpval < 0) {
+               if (tmpval < LDC(0.0)) {
                        tmpval = -tmpval;
                        sgn = true;
                } else {
-                       if (tmpval == - (AWKLDBL) 0.0)  /* avoid printing -0 */
-                               tmpval = (AWKLDBL) 0.0;
+                       if (tmpval == - LDC(0.0))       /* avoid printing -0; 
XXX: does not really detect -0.0, +0.0 == -0.0 -- JH */
+                               tmpval = LDC(0.0);
                        sgn = false;
                }
 
@@ -1539,12 +1538,12 @@ format_awkldbl_printf(NODE *arg, struct format_spec 
*spec, struct print_fmt_buf
                 * prints a single 0.
                 */
        
-               if (! spec->alt && spec->have_prec && spec->prec == 0 && tmpval 
== 0) {
+               if (! spec->alt && spec->have_prec && spec->prec == 0 && tmpval 
== LDC(0.0)) {
                        pr_num_tail(cp, spec->prec, spec, outb);
                        return 0;
                }
 
-               if (tmpval < 0) {
+               if (tmpval < LDC(0.0)) {
                        uval = (uintmax_t) (intmax_t) tmpval;
                        if ((AWKLDBL)(intmax_t) uval != double_to_int(tmpval))
                                goto out_of_range;
@@ -1561,8 +1560,8 @@ format_awkldbl_printf(NODE *arg, struct format_spec 
*spec, struct print_fmt_buf
 out_of_range:
                /* out of range - emergency use of %g format */
                if (do_lint)
-                       lintwarn(_("[s]printf: value %g is out of range for 
`%%%c' format"),
-                                       (double) tmpval, cs1);
+                       lintwarn(_("[s]printf: value %Lg is out of range for 
`%%%c' format"),
+                                       tmpval, cs1);
                cs1 = 'g';
                goto fmt1;
 
@@ -1619,6 +1618,9 @@ fmt1:
        }
 
        return -1;
+#undef CP
+#undef CEND
+#undef CPBUF
 }
 
 #else
diff --git a/misc/fp_math.awk b/misc/fp_math.awk
new file mode 100644
index 0000000..634d128
--- /dev/null
+++ b/misc/fp_math.awk
@@ -0,0 +1,790 @@
+# fp_math.awk --- finite precision math functions
+
+#
+#      TODO:   * finish fmod().
+#              * replace all usages of %, and int() or any other math builtin; 
and() is ok!
+#
+
+
+#
+# Machin's formula to compute pi 
(http://mathworld.wolfram.com/MachinsFormula.html):
+#      pi / 4 = 4 acot(5) - acot(239)
+#            = 4 atan(1/5) - atan(1/239)
+#
+# Euler atan formula (http://mathworld.wolfram.com/InverseTangent.html):
+#      atan(x) = (y/x) (1 + 2/3 y + (2·4)/(3·5) y^2 + (2·4·6)/(3·5·7) 
y^3 + ...)
+# where
+#      y = (x^2) / (1 + x^2) and -1 <= x <= 1
+#
+# Substituting x = 1/x, for x >= 1
+#      atan(1/x) = (x / (1 + x^2))    + (2/3) * (x / (1 + x^2)^2)
+#                                     + (2*4/(3*5)) * (x / (1 + x^2)^3)
+#                                     + (2*4*6/(3*5*7)) * (x / (1 + x^2)^4) + 
...
+#
+
+function euler_atan_one_over(x,        \
+               xpow2_plus_one, term, sum, i, sign, err)
+{
+       sign = 1
+       if (x < 0) {
+               sign = -1
+               x = -x
+       }
+
+       xpow2_plus_one = x * x + 1
+       term = x / xpow2_plus_one
+       sum = term
+       i = 0
+
+       do {
+               term *= (i + 2) / (i + 3)
+               err = term /= xpow2_plus_one
+               i += 2
+               sum += term
+               err = term / sum
+       } while (err > __REL_ERROR__)
+
+       return sign * sum
+}
+
+#
+# atan2(y, x) =        atan(y/x),              x > 0
+#             =        atan(y/x) + pi,         x < 0, y >= 0
+#             =        atan(y/x) - pi,         x < 0, y < 0
+#             =        pi/2,                   x = 0, y > 0
+#             =        -pi/2,                  x = 0, y < 0
+#             =        ?                       x = 0, y = 0
+#
+
+function fp_atan2(y, x,        \
+               sign, plus_inf, minus_inf)
+{
+       # Using Euler atan(1/x) and the identity:
+       #       atan(x) = - pi / 2 - atan(1/x),         x < 0
+       #               = pi / 2 - atan(1/x),           x > 0
+
+       # detect all the "abnormal" cases first
+       x = + x                 # or x += 0.0 or x = x + 0.0
+       y = + y
+       if (isnan(x) || isnan(y))
+               return __PLUS_NAN__
+
+       if (y == __PLUS_INF__) {
+               if (x == __MINUS_INF__)
+                       return 3 * __PI_OVER_4__
+               else if (x == __PLUS_INF__)
+                       return __PI_OVER_4__
+               else
+                       return 2 * __PI_OVER_4__
+       } else if (y == __MINUS_INF__) {
+               if (x == __MINUS_INF__)
+                       return - 3 * __PI_OVER_4__
+               else if (x == __PLUS_INF__)
+                       return - __PI_OVER_4__
+               else
+                       return - 2 * __PI_OVER_4__
+       }
+
+       if (x == __PLUS_INF__)
+               return atan2(y, x)      # use builtin, returns +0 or -0
+       if (x == __MINUS_INF__) {
+               if (y >= 0)
+                       return 4 * __PI_OVER_4__
+               # y < 0
+               return - 4 * __PI_OVER_4__
+       }
+
+       if (x > 0) {
+               if (y == 0)
+                       return atan2(y, x);     # use builtin; returns +0 or -0
+               sign = 1
+               if (y < 0) {
+                       sign = -1
+                       y = -y
+               }
+               if (y > x)
+                       return sign * (2 * __PI_OVER_4__ - 
euler_atan_one_over(y / x))
+               return sign * euler_atan_one_over(x / y)
+       }
+
+       if (x < 0) {
+               if (y == 0) {
+                       if (atan2(y, x) < 0)    # use builtin to detect sign
+                               return - 4 * __PI_OVER_4__
+                       return 4 * __PI_OVER_4__
+               }
+
+               if (y < 0) {
+                       y = -y
+                       x = -x
+                       if (y > x)
+                               return - 2 * __PI_OVER_4__ - 
euler_atan_one_over(y / x)
+                       return euler_atan_one_over(x / y) - 4 * __PI_OVER_4__
+               }
+               # y > 0
+               x = -x
+               if (y > x)
+                       return 2 * __PI_OVER_4__ + euler_atan_one_over(y / x)
+               return - euler_atan_one_over(x / y) + 4 * __PI_OVER_4__
+       }
+
+       if (atan2(y, x) < 0)    # atan2(-0, -0)
+               return - 4.0 * __PI_OVER_4__
+       if (atan2(y, x) > 0)    # atan2(+0, -0)
+               return 4.0 * __PI_OVER_4__
+       return 0;       # atan2(+0, +0) or atan2(-0, 0)
+}
+
+#
+#      Collect two terms in each iteration for the Taylor series:
+#              sin(x) = (x - x^3/3!) + (x^5/7! - x^9/9!) + ...
+#
+
+function taylor_sin(x, \
+               i, fact, xpow2, xpow_odd, sum, term, err)
+{
+       # XXX: this assumes x >= 0
+
+       if (x == 0)
+               return x
+       i = 3
+       fact = 6        # 3!
+       xpow2 = x * x
+       xpow_odd = xpow2 * x
+       sum = x - xpow_odd / fact
+
+       do {
+               fact *= (i + 1) * (i + 2)
+               i += 2
+               xpow_odd *= xpow2
+               term = xpow_odd / fact
+
+               fact *= (i + 1) * (i + 2)
+               i += 2
+               xpow_odd *= xpow2
+               term -= xpow_odd / fact
+
+               sum += term
+               err = term / sum
+       } while (err > __REL_ERROR__)
+
+       return sum
+}
+
+#
+#      Collect two terms in each iteration for the Taylor series:
+#              cos(x) = (1 - x^2/2!) + (x^4/4! - x^6/6!)...
+#
+
+function taylor_cos(x, \
+               i, fact, xpow2, xpow_even, sum, term, err)
+{
+       if (x == 0)
+               return 1
+
+       i = 2
+       fact = 2        # 2!
+       xpow2 = x * x
+       xpow_even = xpow2
+       sum = 1 - xpow2 / fact
+
+       do {
+               fact *= (i + 1) * (i + 2)
+               i += 2
+               xpow_even *= xpow2
+               term = xpow_even / fact
+
+               fact *= (i + 1) * (i + 2)
+               i += 2
+               xpow_even *= xpow2
+               term -= xpow_even / fact
+
+               sum += term
+               err = term / sum
+       } while (err > __REL_ERROR__)
+
+       return sum
+}
+
+#
+# For 0 <= x <= PI/4, using Taylor series approximation for sin(x):
+#      x - x^3/5! + x^5/7! - ...
+#
+# for PI/4 < x <= PI/2, use identity sin(x) = cos(PI/2 - x).
+#
+
+function fp_sin(x,     \
+               k, sign, y, sv)
+{
+       x = + x         # or x += 0.0 or x = x + 0.0 
+       if (isinf(x) || isnan(x))
+               return __PLUS_NAN__
+       if (x == 0)
+               return x
+       
+       if (x < 0) {
+               # sin(-x) = - sin(x)
+               sign = -1
+               x = -x
+       } else
+               sign = 1
+
+       # range reduction -- 0 <= y <= pi / 4
+
+       k = int(x / __PI_OVER_4__)
+       sign *= ( int(k / 4) % 2 ? -1 : 1 )
+
+       # XXX --- make sure y >= 0
+       switch (k % 4) {
+       case 0: y = x - k * __PI_OVER_4__; sv = taylor_sin(y); break;
+       case 1: y = (k + 1) * __PI_OVER_4__ - x; sv = taylor_cos(y); break;
+       case 2: y = x - k * __PI_OVER_4__; sv = taylor_cos(y); break;
+       case 3: y = (k + 1) * __PI_OVER_4__ - x; sv = taylor_sin(y); break;
+       }
+       sv *= sign
+       return sv; 
+}
+
+#
+# Using Taylor series approximation for sin(x) for 0 <= x <= PI/4:
+#      1 - x^2/2! + x^4/4! - ...
+# for PI/4 < x < PI/2, use identity cos(x) = sin(PI/2 - x).
+#
+
+function fp_cos(x,     \
+               k, sign, y, cv)
+{
+       x = + x         # or x += 0.0 or x = x + 0.0
+       if (isinf(x) || isnan(x))
+               return __PLUS_NAN__
+
+       if (x < 0)      # cos(x) = cos(-x)
+               x = -x
+       if (x == 0)
+               return 1.0
+
+       # range reduction -- 0 <= y <= pi / 4
+
+       k = int(x / __PI_OVER_4__)
+       sign = ( int(k / 4) % 2 ? -1 : 1 )
+
+       # XXX -- make sure y >= 0
+       switch (k % 4) {
+       case 0: y = x - k * __PI_OVER_4__; cv = taylor_cos(y); break;
+       case 1: y = (k + 1) * __PI_OVER_4__ - x; cv = taylor_sin(y); break;
+       case 2: y = x - k * __PI_OVER_4__; cv = -taylor_sin(y); break;
+       case 3: y = (k + 1) * __PI_OVER_4__ - x; cv = -taylor_cos(y); break;
+       }
+       cv *= sign
+       return cv
+}
+
+function fp_atan2(y, x)
+{
+       return euler_atan2(y, x)
+}
+
+function isinf(x)
+{
+       x = + x 
+       return x == __PLUS_INF__ || x == __MINUS_INF__
+}
+
+function isnan(x)
+{
+       x = + x 
+       return x == __PLUS_NAN__ || x == __MINUS_NAN__
+}
+
+#################################################################
+# Detecting a negative zero in gawk (signbit(x) in C where x is a signed 0):
+# $ gawk 'BEGIN { x = -0.0; print atan2(0.0, x) == atan2(-0.0, x)}'
+# 0
+# $ gawk 'BEGIN { x = 0.0; print atan2(0.0, x) == atan2(-0.0, x)}'
+# 1
+#
+#################################################################
+
+function ispluszero(x)
+{
+       x = +x
+       if (x != 0)
+               return 0 
+       return atan2(0.0, x) == atan2(-0.0, x)
+}
+
+function isminuszero(x)
+{
+       x = +x
+       if (x != 0)
+               return 0
+       return ! (atan2(0.0, x) == atan2(-0.0, x))
+}
+
+#
+# Newton-Raphson to calculate higher precision result from already known fixed
+# precision value. This usually converges in 2 to 3 iterations.
+#
+
+function fp_sqrt(x,    \
+               yn, err, last)
+{
+       if (isnan(x) || x == __PLUS_INF__)
+               return x
+       if (x == __MINUS_INF__ || x < 0)
+               return __MINUS_NAN__    # set errno = EDOM for x < -0?
+       if (x == 0)
+               return x        # return +0 or -0
+
+       yn = sqrt(x)    # double-precision sqrt
+       do {
+               last = yn
+               yn = (yn + x / yn) \
+                               / 2
+               err = (yn - last) / yn
+       } while (err > __REL_ERROR__)
+       return yn
+}
+
+# __log2 -- compute log(2)
+
+function __log2( \
+               i, three_pow, sum, err, term)
+{
+       #
+       #       ln(2) = 2 * arctanh(2)
+       #             = 2 * ((1/3) + (1/3)^3 / 3 + (1/3)^5 / 5 + ..) 
+       #
+
+       # y = (x - 1) / (x + 1) => y = 1 / 3
+       i = 1
+       three_pow = 3
+       sum = 1 / 3
+
+       do {
+               three_pow *= 9
+               i += 2
+               term = 1 / (three_pow * i)
+               sum += term
+               err = term / sum
+       } while (err > __REL_ERROR__)
+       return 2 * sum
+}
+
+
+function fp_log(x,     \
+               k, i, y, ypow2, ypow_odd, sum, err, term, sqrt_2, sign)
+{
+       #
+       #       ln(x) = 2 * arctanh(y)
+       #             = 2 * (y + y^3 / 3 + y^5 /5 + ..) where y = (x - 1) / (x 
+ 1) 
+       #
+       x = +x
+       if (isnan(x) || x == __PLUS_INF__)
+               return x
+       if (x == __MINUS_INF__ || x < 0)        # errno EDOM ?
+               return __PLUS_NAN__
+       if (x == 0)     # errno ERANGE ?
+               return __MINUS_INF__
+       
+       if (x == 1)     # special case
+               return 0
+       if (x == 2)     # special case
+               return __LOG2__
+       k = 0
+       if (x > 2) {
+               # FIXME -- use power2 table
+               while (x > 2) {
+                       x /= 2
+                       k++
+               }
+       } else if (x < 1) {
+               # FIXME -- use power2 table
+               while (x < 1) {
+                       x *= 2
+                       k--
+               }
+       }
+
+       # arctanh(x) series has faster convergence when x is close to 1
+       # range reduction -- 1/sqrt(2) <= x <= sqrt(2)
+       if (x > __SQRT_2__ || x < __1_OVER_SQRT_2__) {
+               x *= __1_OVER_SQRT_2__
+               k += 0.5
+       }
+
+       y = (x - 1) / (x + 1)
+       sign = 1
+       if (y < 0) {
+               sign = -1
+               y = -y
+       }
+
+       i = 1
+       ypow2 = y * y
+       ypow_odd = y
+       sum = y
+
+       do {
+               ypow_odd *= ypow2
+               i += 2
+               term = ypow_odd / i
+               sum += term
+               err = term / sum
+       } while (err > __REL_ERROR__)
+
+       return sign * (sum = 2 * sum + k * __LOG2__)
+}
+
+
+function taylor_exp(x, \
+               xpow2, xpow_even, i, fact, cosh, sinh, err, term)
+{
+       # x < 1
+       # cosh(x) = (exp(x) + exp(-x)) / 2      -- faster convergence than 
exp(x)
+       # sinh(x) = sqrt(cosh(x) * cosh(x) - 1)
+       # exp(x) = cosh(x) + sinh(x)
+
+       xpow2 = x * x
+       xpow_even = 1
+       i = 0
+       fact = 1
+       cosh = 1
+
+       do {
+               fact *= (i + 1) * (i + 2)
+               xpow_even *= xpow2
+               term = xpow_even / fact
+               i += 2
+               cosh += term
+               err  = term / cosh
+       } while (err > __REL_ERROR__)
+
+       sinh = fp_sqrt(cosh * cosh - 1) # sqrt is cheap
+       return (sinh + cosh)
+}
+
+function fp_exp(x,     \
+               exp_val, k, sign)
+{
+       x = +x
+       if (isnan(x) || x == __PLUS_INF__)
+               return x
+       if (x == __MINUS_INF__)
+               return 0
+
+       if (x == 0)     # special case
+               return 1
+       sign = 1
+       if (x < 0) {
+               sign = -1
+               x = -x
+       }
+       k = fp_floor(x / __LOG2__)
+
+       # range reduction -- 0 < x < log(2) (0.693...)
+       if (k == 0)
+               exp_val = taylor_exp(x)
+       else {
+               exp_val = taylor_exp(x - k * __LOG2__)
+               while (k >= 64) {
+                       exp_val *= __POW2__[64]
+                       k -= 64
+               }
+               exp_val *= __POW2__[k]
+       }
+       return sign < 0 ? (1 / exp_val) : exp_val
+}
+
+function isinteger(x)
+{
+       # assume != NaN or inf
+       return fp_floor(x) == fp_ceil(x)
+}
+
+function isodd(x)
+{
+       # assume != NaN or inf
+       # XXX -- not using % operator, either fmodl() is missing, or will get 
into
+       #       situation like: fp_fmod() -> isodd() -> fp_fmod() ..
+
+       return isinteger(x) && and(x, 1)
+}
+
+function iseven(x)
+{
+       # assume != NaN or inf
+       return isinteger(x) && ! and(x, 1)
+}
+
+function fp_abs(x)
+{
+       # assume != NaN or inf
+       return x < 0 ? -x : x
+}
+
+function fp_pow(x, y,  \
+               i, result, sign)
+{
+       x = +x
+       y = +y
+       if ((! isnan(x) && x == 1) || (! isnan(y) && y == 0))
+               return 1
+       if (isnan(x) || isnan(y))
+               return __PLUS_NAN__
+
+       # x or y not NaN
+       if (isinf(x)) {
+               if (x == __PLUS_INF__) {
+                       if (y < 0)
+                               return 0
+                       if (y > 0)
+                               return __PLUS_INF__
+               }
+               # x == -inf
+               if (y < 0) {
+                       if (! isinf(y) && isodd(y))
+                               return -0.0
+                       return 0
+               }
+               if (y > 0) {
+                       if (! isinf(y) && isodd(y))
+                               return __MINUS_INF__
+                       return __PLUS_INF__
+               }
+               # y == 0 handled above
+       } else {
+               # x isn't infinity
+               if (x < 0 && ! isinf(y) && ! isinteger(y))
+                       return __PLUS_NAN__
+
+               if (isinf(y)) {
+                       if (x == -1)
+                               return 1
+                       # x == +1 handled above
+                       if (fp_abs(x) < 1) {
+                               if (y == __MINUS_INF__)
+                                       return __PLUS_INF__
+                               return 0
+                       }
+                       # fp_abs(x) > 1)
+                       if (y == __MINUS_INF__)
+                               return 0
+                       return __PLUS_INF__
+               }
+               # y isn't infinity
+               if (x == 0 && y > 0) {
+                       if (isodd(y))
+                               return x        # +0 or -0
+                       else
+                               return 0
+               }
+               if (x == 0 && y < 0) {
+                       if (isodd(y)) {
+                               # HUGE_VALL with same sign as x
+                               if (ispluszero(x))
+                                       return __PLUS_INF__
+                               return __MINUS_INF__
+                       }
+                       # + HUGE_VALL
+                       return __PLUS_INF__ 
+               }
+               # x == 0 && y == 0 handled above 
+       }
+
+       if (x < 0) {
+               # y is integer, and != 0
+               # gawk has special code to handle this; can return junk!
+               # XXX: move the special code (at least for x < 0) in gawk_powl 
instead?
+               result = x
+               sign = 1
+               if (y < 0) {
+                       sign = -1
+                       y = -y
+               }
+               for (i = 1; i < y; i++)
+                       result *= x
+               return sign > 0 ? result : 1 / result
+       }
+
+       # x^y =  exp(y * log(x)), x > 0
+       return fp_exp(y * fp_log(x))
+}
+
+
+function fp_floor(x,   d)
+{
+       x = +x
+       if (isnan(x) || isinf(x) || x == 0)
+               return x
+       d = sprintf("%d", x) + 0
+       if (x == d || x > 0)
+               return d
+       return d - 1
+}
+
+function fp_ceil(x,    d)
+{
+       x = +x
+       if (isnan(x) || isinf(x) || x == 0)
+               return x
+       d = sprintf("%d", x) + 0
+       if (x == d || x < 0)
+               return d
+       return d + 1
+}
+
+#
+#      Calculating fmod with correctly rounded output isn't easy:
+#
+# BEGIN {
+#      POW2[0] = 1
+#      for (i = 1; i <= 64; i++) {
+#              POW2[i] = POW2[i - 1] * 2
+#      }
+#      x = 343.4341
+#      y = 1.324355
+#      printf("builtin: %0.18f\n", x % y)
+#
+#      q = int(x / y)  # floor
+#      printf("simple : %0.18f\n", x - q * y)
+#
+#      r = calc_fmod(x, y)
+#      printf("pow2   : %0.18f\n", r)
+# }
+#
+# function calc_fmod(x, y,     q, j)
+# {
+#      # x > 0, y > 0
+#      q = int(x / y)  # floor, q < 2^64
+#      while (q > 2) {
+#              # XXX: use binary search?
+#              for (j = 1; j <= 64; j++) {
+#                      if (q <= POW2[j]) {
+#                              x -= POW2[j - 1] * y
+#                              q -= POW2[j - 1]
+#                              break
+#                      }
+#              }
+#      }
+#      x -= q * y
+#      return x
+# }
+#
+# We can only get correctly rounded 16 digits (with 80 bit long double),
+# using math library or not:
+#
+# $ ./gawk -B -f fmod.awk 
+# builtin: 0.426155000000000019
+# simple : 0.426155000000000006
+# pow2   : 0.426155000000000019
+#
+# For comparison, MPFR quad precision output:
+#
+# $ ./gawk -M -vPREC=quad 'BEGIN { printf("%0.18f\n",  343.4341 % 1.324355) }'
+# 0.426155000000000000
+#
+
+
+function fp_fmod(x, y, \
+               z, sign)
+{
+       x = +x
+       y = +y
+       if (isnan(x) || isnan(y) \
+                       || isinf(x) || y == 0)          # errno = EDOM ?
+               return __PLUS_NAN__
+       if (x == 0)
+               return x        # +0 or -0
+       if (isinf(y))
+               return x
+
+       sign = 1
+       if (x < 0) {
+               sign = -1
+               x = -x
+       }
+       if (y < 0)
+               y = -y
+
+       if (x < y) # nothing to do
+               return sign * x
+
+       q = fp_floor(x / y)
+
+       # FIXME -- see above, and also consider integer overflow (q >= 
2^LDBL_MANT_DIG)
+       return sign * (x - q * y)
+}
+
+
+# fixprec -- fixes "0.18e" output
+
+function fixprec(str, numdigs, \
+               sign, j, exponent, sigdigs, lastdig, nextdig)
+{
+       if (str ~ /^[-+]?(nan|inf)/)
+               return str
+       if (! numdigs)
+               numdigs = __DIGITS__
+       if (str ~ /^[-+]?0[\.]/)
+               return str
+       sign = ""
+       if (str ~ /^-/) {
+               sign = "-"
+               str = substr(str, 2)
+       } else if (str ~ /^+/) {
+               sign = "+"
+               str = substr(str, 2)
+       }
+       sub(/\./, "", str)
+
+       if ((j = index(str, "e-")) > 0) {
+               exponent = substr(str, j + 2)
+               exponent--
+               exponent = sprintf("e-%02d", exponent)
+       } else if ((j = index(str, "e+")) > 0) {
+               exponent = substr(str, j + 2)
+               exponent++
+               exponent = sprintf("e+%02d", exponent)
+       }
+       sigdigs = substr(str, 1, numdigs)
+       lastdig = substr(str, numdigs, 1) + 0
+       nextdig = substr(str, numdigs + 1, 1) + 0
+
+       # XXX: Don't use % to test even or odd, may not have fmodl() !
+       if (nextdig > 5 || (nextdig == 5 && and(lastdig, 1) != 0))
+               sub(/[0-9]$/, lastdig + 1, sigdigs)
+       return sign "0." sigdigs exponent
+}
+
+
+BEGIN {
+       # define some constants
+
+       # reltive error < 5 X 10^-k for rounding to k significant digits
+       __DIGITS__ = 34
+       __REL_ERROR__ = 5.0e-34
+
+       __PLUS_INF__ = "+inf" + 0
+       __MINUS_INF__ = "-inf" + 0
+       __PLUS_NAN__ = "+nan" + 0
+       __MINUS_NAN__ = "-nan" + 0
+
+       __SQRT_2__ = fp_sqrt(2)
+       __1_OVER_SQRT_2__ = 1 / __SQRT_2__
+       __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
+
+       __POW2__[0] = 1
+       for (i = 1; i <= 64; i++)
+               __POW2__[i] = __POW2__[i - 1] * 2
+}

http://git.sv.gnu.org/cgit/gawk.git/commit/?id=c5b44e77f250e364a5c3a677722d513f88977eef

commit c5b44e77f250e364a5c3a677722d513f88977eef
Merge: 42dd951 2fec754
Author: John Haque <address@hidden>
Date:   Sat Jan 12 08:31:23 2013 -0600

    Merge branch 'num-handler' into long-double.

diff --cc Makefile.in
index f4f28bc,3144c0e..202d362
--- a/Makefile.in
+++ b/Makefile.in
@@@ -107,13 -106,13 +107,14 @@@ PROGRAMS = $(bin_PROGRAMS
  am__objects_1 = array.$(OBJEXT) awkgram.$(OBJEXT) builtin.$(OBJEXT) \
        cint_array.$(OBJEXT) command.$(OBJEXT) debug.$(OBJEXT) \
        dfa.$(OBJEXT) double.$(OBJEXT) eval.$(OBJEXT) ext.$(OBJEXT) \
-       field.$(OBJEXT) floatcomp.$(OBJEXT) gawkapi.$(OBJEXT) \
-       gawkmisc.$(OBJEXT) getopt.$(OBJEXT) getopt1.$(OBJEXT) \
-       int_array.$(OBJEXT) io.$(OBJEXT) long_double.$(OBJEXT) \
-       main.$(OBJEXT) mpfr.$(OBJEXT) msg.$(OBJEXT) node.$(OBJEXT) \
-       profile.$(OBJEXT) random.$(OBJEXT) re.$(OBJEXT) \
-       regex.$(OBJEXT) replace.$(OBJEXT) str_array.$(OBJEXT) \
-       symbol.$(OBJEXT) version.$(OBJEXT)
+       field.$(OBJEXT) floatcomp.$(OBJEXT) format.$(OBJEXT) \
+       gawkapi.$(OBJEXT) gawkmisc.$(OBJEXT) getopt.$(OBJEXT) \
+       getopt1.$(OBJEXT) int_array.$(OBJEXT) io.$(OBJEXT) \
 -      main.$(OBJEXT) mpfr.$(OBJEXT) msg.$(OBJEXT) node.$(OBJEXT) \
 -      profile.$(OBJEXT) random.$(OBJEXT) re.$(OBJEXT) \
 -      regex.$(OBJEXT) replace.$(OBJEXT) str_array.$(OBJEXT) \
 -      symbol.$(OBJEXT) version.$(OBJEXT)
++      long_double.$(OBJEXT) main.$(OBJEXT) mpfr.$(OBJEXT) \
++      msg.$(OBJEXT) node.$(OBJEXT) profile.$(OBJEXT) \
++      random.$(OBJEXT) re.$(OBJEXT) regex.$(OBJEXT) \
++      replace.$(OBJEXT) str_array.$(OBJEXT) symbol.$(OBJEXT) \
++      version.$(OBJEXT)
  am_gawk_OBJECTS = $(am__objects_1)
  gawk_OBJECTS = $(am_gawk_OBJECTS)
  gawk_LDADD = $(LDADD)

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

Summary of changes:
 ChangeLog                                       |    7 +
 Makefile.am                                     |    1 +
 Makefile.in                                     |   17 +-
 TODO.LDBL                                       |   20 +
 awk.h                                           |    1 -
 builtin.c                                       |  758 +----------------------
 debug.c                                         |    1 +
 double.c                                        |    2 +-
 format.c                                        |  776 ++++++++++++++++++++++
 format.h                                        |   10 +-
 long_double.c                                   |  176 +++---
 awklib/eg/lib/repl_math.awk => misc/ap_math.awk |  156 +++--
 misc/fp_math.awk                                |  790 +++++++++++++++++++++++
 mpfr.c                                          |    5 -
 msg.c                                           |    1 +
 15 files changed, 1798 insertions(+), 923 deletions(-)
 create mode 100644 TODO.LDBL
 create mode 100644 format.c
 rename awklib/eg/lib/repl_math.awk => misc/ap_math.awk (71%)
 create mode 100644 misc/fp_math.awk


hooks/post-receive
-- 
gawk



reply via email to

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