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. 3e6f4db8c8724164a5


From: John Haque
Subject: [gawk-diffs] [SCM] gawk branch, long-double, updated. 3e6f4db8c8724164a52b12216746c6bb3e050b69
Date: Mon, 04 Feb 2013 12:18:44 +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  3e6f4db8c8724164a52b12216746c6bb3e050b69 (commit)
      from  fddb32fc890cabd6175ab022302ca3d852a4731d (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=3e6f4db8c8724164a52b12216746c6bb3e050b69

commit 3e6f4db8c8724164a52b12216746c6bb3e050b69
Author: John Haque <address@hidden>
Date:   Mon Feb 4 06:17:09 2013 -0600

    Added replacement trig functions for long double.

diff --git a/misc/ChangeLog b/misc/ChangeLog
index 4dd9c3f..d668726 100644
--- a/misc/ChangeLog
+++ b/misc/ChangeLog
@@ -1,3 +1,10 @@
+2013-02-04         John Haque            <address@hidden>
+
+       * gawk_math.c (gawk_sinl, gawk_cosl, gawk_atan2l):
+       Replacement long double math functions.
+       * ldbl-tests/*.awk: Tests for the math functions.
+       * floatcmp.awk: Added diff mode.
+
 2013-02-02         John Haque            <address@hidden>
 
        * float80.c: New file. Provides 80-bit long-double support
diff --git a/misc/Makefile b/misc/Makefile
index bafec60..2a07457 100644
--- a/misc/Makefile
+++ b/misc/Makefile
@@ -42,9 +42,14 @@ LDBL_TESTS = \
        exp64 \
        exp113 \
        pow64 \
-       pow113
+       pow113 \
+       sin64 \
+       sin113 \
+       cos64 \
+       cos113
 
 INFILE = ldbl-tests/data.in
+INFILE32 = ldbl-tests/sincos.in
 
 # An attempt to print something that can be grepped for in build logs
 pass-fail:
@@ -61,6 +66,10 @@ ldbl-tests: $(LDBL_TESTS)
 $(INFILE):
        @$(AWK) -M -vPREC=quad -f ldblin.awk > $(INFILE) 2>&1
 
+$(INFILE32): $(INFILE)
+       @$(AWK) -M -vPREC=quad -f ldblin.awk | \
+$(AWK) -M -vPREC=quad '($$1 > -2^32 && $$1 < 2^32){ print $$0 }' > $(INFILE32) 
2>&1
+
 ldblint64:
        @echo $@
        @$(AWK) -B0 -f ldbl-tests/address@hidden > ldbl-tests/_$@ 2>&1
@@ -73,48 +82,72 @@ ldblint128:
 
 sqrt64: $(INFILE)
        @echo $@
-       @$(AWK) -B0 -vDIG=17 -f ldbl-tests/sqrt.awk > ldbl-tests/_$@ $(INFILE) 
2>&1
-       @$(AWK) -M -vDIG=17 -vPREC=64 -f ldbl-tests/sqrt.awk > 
ldbl-tests/address@hidden $(INFILE) 2>&1
+       @$(AWK) -B0 -vDIG=17 -f ldbl-tests/sqrt.awk $(INFILE) > ldbl-tests/_$@ 
2>&1
+       @$(AWK) -M -vDIG=17 -vPREC=64 -f ldbl-tests/sqrt.awk $(INFILE) > 
ldbl-tests/address@hidden 2>&1
        @-$(AWK) -M -f floatcmp.awk ldbl-tests/_$@ ldbl-tests/address@hidden && 
rm ldbl-tests/_$@
 
 sqrt113: $(INFILE)
        @echo $@
-       @$(AWK) -B1 -vDIG=32 -f ldbl-tests/sqrt.awk > ldbl-tests/_$@ $(INFILE) 
2>&1
-       @$(AWK) -M -vDIG=32 -vPREC=113 -f ldbl-tests/sqrt.awk > 
ldbl-tests/address@hidden $(INFILE) 2>&1
+       @$(AWK) -B1 -vDIG=32 -f ldbl-tests/sqrt.awk $(INFILE) > ldbl-tests/_$@ 
2>&1
+       @$(AWK) -M -vDIG=32 -vPREC=113 -f ldbl-tests/sqrt.awk $(INFILE) > 
ldbl-tests/address@hidden 2>&1
        @-$(AWK) -M -f floatcmp.awk ldbl-tests/_$@ ldbl-tests/address@hidden && 
rm ldbl-tests/_$@
 
 log64: $(INFILE)
        @echo $@
-       @$(AWK) -B0 -vDIG=17 -f ldbl-tests/log.awk > ldbl-tests/_$@ $(INFILE) 
2>&1
-       @$(AWK) -M -vDIG=17 -vPREC=64 -f ldbl-tests/log.awk > 
ldbl-tests/address@hidden $(INFILE) 2>&1
+       @$(AWK) -B0 -vDIG=17 -f ldbl-tests/log.awk $(INFILE) > ldbl-tests/_$@ 
2>&1
+       @$(AWK) -M -vDIG=17 -vPREC=64 -f ldbl-tests/log.awk $(INFILE) > 
ldbl-tests/address@hidden 2>&1
        @-$(AWK) -M -f floatcmp.awk ldbl-tests/_$@ ldbl-tests/address@hidden && 
rm ldbl-tests/_$@
 
 log113: $(INFILE)
        @echo $@
-       @$(AWK) -B1 -vDIG=32 -f ldbl-tests/log.awk > ldbl-tests/_$@ $(INFILE) 
2>&1
-       @$(AWK) -M -vDIG=32 -vPREC=113 -f ldbl-tests/log.awk > 
ldbl-tests/address@hidden $(INFILE) 2>&1
+       @$(AWK) -B1 -vDIG=32 -f ldbl-tests/log.awk $(INFILE) > ldbl-tests/_$@ 
2>&1
+       @$(AWK) -M -vDIG=32 -vPREC=113 -f ldbl-tests/log.awk $(INFILE) > 
ldbl-tests/address@hidden 2>&1
        @-$(AWK) -M -f floatcmp.awk ldbl-tests/_$@ ldbl-tests/address@hidden && 
rm ldbl-tests/_$@
 
 exp64: $(INFILE)
        @echo $@
-       @$(AWK) -B0 -vDIG=17 -f ldbl-tests/exp.awk > ldbl-tests/_$@ $(INFILE) 
2>&1
-       @$(AWK) -M -vDIG=17 -vPREC=64 -f ldbl-tests/exp.awk > 
ldbl-tests/address@hidden $(INFILE) 2>&1
+       @$(AWK) -B0 -vDIG=17 -f ldbl-tests/exp.awk $(INFILE) > ldbl-tests/_$@ 
2>&1
+       @$(AWK) -M -vDIG=17 -vPREC=64 -f ldbl-tests/exp.awk $(INFILE) > 
ldbl-tests/address@hidden 2>&1
        @-$(AWK) -M -f floatcmp.awk ldbl-tests/_$@ ldbl-tests/address@hidden && 
rm ldbl-tests/_$@
 
 exp113: $(INFILE)
        @echo $@
-       @$(AWK) -B1 -vDIG=32 -f ldbl-tests/exp.awk > ldbl-tests/_$@ $(INFILE) 
2>&1
-       @$(AWK) -M -vDIG=32 -vPREC=113 -f ldbl-tests/exp.awk > 
ldbl-tests/address@hidden $(INFILE) 2>&1
+       @$(AWK) -B1 -vDIG=32 -f ldbl-tests/exp.awk $(INFILE) > ldbl-tests/_$@ 
2>&1
+       @$(AWK) -M -vDIG=32 -vPREC=113 -f ldbl-tests/exp.awk $(INFILE) > 
ldbl-tests/address@hidden 2>&1
        @-$(AWK) -M -f floatcmp.awk ldbl-tests/_$@ ldbl-tests/address@hidden && 
rm ldbl-tests/_$@
 
 pow64: $(INFILE)
        @echo $@
-       @$(AWK) -B0 -vDIG=17 -f ldbl-tests/pow.awk > ldbl-tests/_$@ $(INFILE) 
2>&1
-       @$(AWK) -M -vDIG=17 -vPREC=64 -f ldbl-tests/pow.awk > 
ldbl-tests/address@hidden $(INFILE) 2>&1
+       @$(AWK) -B0 -vDIG=17 -f ldbl-tests/pow.awk $(INFILE) > ldbl-tests/_$@ 
2>&1
+       @$(AWK) -M -vDIG=17 -vPREC=64 -f ldbl-tests/pow.awk $(INFILE) > 
ldbl-tests/address@hidden 2>&1
        @-$(AWK) -M -vTOL=10 -f floatcmp.awk ldbl-tests/_$@ 
ldbl-tests/address@hidden && rm ldbl-tests/_$@
 
 pow113: $(INFILE)
        @echo $@
-       @$(AWK) -B1 -vDIG=32 -f ldbl-tests/pow.awk > ldbl-tests/_$@ $(INFILE) 
2>&1
-       @$(AWK) -M -vDIG=32 -vPREC=113 -f ldbl-tests/pow.awk > 
ldbl-tests/address@hidden $(INFILE) 2>&1
-       @-$(AWK) -M -vTOL=10 -f floatcmp.awk ldbl-tests/_$@ 
ldbl-tests/address@hidden && rm ldbl-tests/_$@
+       @$(AWK) -B1 -vDIG=32 -f ldbl-tests/pow.awk $(INFILE) > ldbl-tests/_$@ 
2>&1
+       @$(AWK) -M -vDIG=32 -vPREC=113 -f ldbl-tests/pow.awk $(INFILE) > 
ldbl-tests/address@hidden 2>&1
+       @-$(AWK) -M -vTOL=20 -f floatcmp.awk ldbl-tests/_$@ 
ldbl-tests/address@hidden && rm ldbl-tests/_$@
+
+sin64:
+       @echo $@
+       @$(AWK) -B0 -vDIG=17 -f ldbl-tests/sin.awk $(INFILE32) > ldbl-tests/_$@ 
2>&1
+       @$(AWK) -M -vDIG=17 -vPREC=64 -f ldbl-tests/sin.awk $(INFILE32) > 
ldbl-tests/address@hidden 2>&1
+       @-$(AWK) -M -f floatcmp.awk ldbl-tests/_$@ ldbl-tests/address@hidden && 
rm ldbl-tests/_$@
+
+sin113: $(INFILE32)
+       @echo $@
+       @$(AWK) -B1 -vDIG=32 -f ldbl-tests/sin.awk $(INFILE32) > ldbl-tests/_$@ 
2>&1
+       @$(AWK) -M -vDIG=32 -vPREC=113 -f ldbl-tests/sin.awk $(INFILE32) > 
ldbl-tests/address@hidden 2>&1
+       @-$(AWK) -M -f floatcmp.awk ldbl-tests/_$@ ldbl-tests/address@hidden && 
rm ldbl-tests/_$@
+
+cos64:
+       @echo $@
+       @$(AWK) -B0 -vDIG=17 -f ldbl-tests/cos.awk $(INFILE32) > ldbl-tests/_$@ 
2>&1
+       @$(AWK) -M -vDIG=17 -vPREC=64 -f ldbl-tests/cos.awk $(INFILE32) > 
ldbl-tests/address@hidden 2>&1
+       @-$(AWK) -M -f floatcmp.awk ldbl-tests/_$@ ldbl-tests/address@hidden && 
rm ldbl-tests/_$@
+
+cos113: $(INFILE32)
+       @echo $@
+       @$(AWK) -B1 -vDIG=32 -f ldbl-tests/cos.awk $(INFILE32) > ldbl-tests/_$@ 
2>&1
+       @$(AWK) -M -vDIG=32 -vPREC=113 -f ldbl-tests/cos.awk $(INFILE32) > 
ldbl-tests/address@hidden 2>&1
+       @-$(AWK) -M -f floatcmp.awk ldbl-tests/_$@ ldbl-tests/address@hidden && 
rm ldbl-tests/_$@
diff --git a/misc/floatcmp.awk b/misc/floatcmp.awk
index 87c8ea2..ac2a08e 100644
--- a/misc/floatcmp.awk
+++ b/misc/floatcmp.awk
@@ -1,9 +1,14 @@
-# floatcmp.awk --- check floating-point numbers for differences in
-#       sig digs.
+# floatcmp.awk --- check floating-point numbers for differences in sig digs.
+#      -vMODE=[diff|plot] -- diff mode or output data suitable fro plotting
+#      -vTOL=tol       -- ignore sig dig difference <= tol
 
 BEGIN {
+       if (! ("mpfr_version" in PROCINFO)) {
+               print "floatcmp.awk: requires -M option" > "/dev/stderr"
+               exit(1)
+       } 
        if (ARGC < 3) {
-               printf("Usage: gawk -M [-vTOL=1] -f floatcmp.awk file1 file2\n")
+               print "Usage: gawk -M [-vTOL=tol] [-vMODE=diff|plot] -f 
floatcmp.awk file1 file2" > "/dev/stderr"
                exit(1)
        }
 
@@ -20,10 +25,11 @@ BEGIN {
                ret1 = (getline v1 < file1) 
                ret2 = (getline v2 < file2) 
 
+               f1 = v1; f2 = v2;       # save originals for diff mode
                if (ret1 > 0 && ret2 > 0) {
                        line++
                        if ((v1 "") == (v2 ""))
-                               continue;
+                               continue
                        e1 = index(v1, "e")
                        e2 = index(v2, "e")
                        if (e1 > 0 && e2 > 0 &&         # exclude nans and 
infinities
@@ -41,8 +47,17 @@ BEGIN {
                                        continue
                        }
 
-                       printf("%s %s differ: byte ?, line %d\n", file1, file2, 
line)
-                       exit(1)
+                       if (! MODE) {
+                               printf("%s %s differ: byte ?, line %d\n", 
file1, file2, line)
+                               exit(1)
+                       }
+                       if (MODE == "plot")
+                               printf("%d\t%d\n", line, diff)
+                       else {
+                               dig = length(v1)
+                               printf("%-*.*s %-*.*s %+*.*d\n", dig+7, dig+7, 
f1, dig+7, dig+7, f2, dig, dig, diff)
+                       }
+                               continue
                }
 
                if (ret1 == 0 && ret2 == 0)
diff --git a/misc/fp_math.awk b/misc/fp_math.awk
index e2847e6..60048b1 100644
--- a/misc/fp_math.awk
+++ b/misc/fp_math.awk
@@ -39,7 +39,7 @@ function euler_atan_one_over(x,       \
 
        do {
                term *= (i + 2) / (i + 3)
-               err = term /= xpow2_plus_one
+               term /= xpow2_plus_one
                i += 2
                sum += term
                err = term / sum
diff --git a/misc/gawk_math.c b/misc/gawk_math.c
index 6981725..27ca215 100644
--- a/misc/gawk_math.c
+++ b/misc/gawk_math.c
@@ -27,40 +27,250 @@
 #define _0L    LDC(0.0)
 #define _1L    LDC(1.0)
 #define _2L    LDC(2.0)
+#define _3L    LDC(3.0)
+#define _4L    LDC(4.0)
 
 /*
  * Constants for computation using long doubles with enough digits for the 
128-bit quad.
  */
 
-#define GAWK_LOG2      LDC(0.693147180559945309417232121458176568)  /* log 2 
(base e) */
+#define        GAWK_LOG2       LDC(0.693147180559945309417232121458176568)  /* 
log 2 (base e) */
 #define        GAWK_LOG2_HIGH  LDC(0.6931471801362931728363037109375)       /* 
high 32 bits (exact representation) */
-#define GAWK_LOG2_LOW  LDC(4.236521365809284105206765680755001344e-10) /* 
variable precision low bits */
+#define        GAWK_LOG2_LOW   LDC(4.236521365809284105206765680755001344e-10) 
/* variable precision low bits */
 
-#define GAWK_SQRT2     LDC(1.414213562373095048801688724209698079)     /* 
sqrt(2) */
-#define GAWK_SQRT1_2   LDC(0.707106781186547524400844362104849039)     /* 
1/sqrt(2) */
+#define        GAWK_SQRT2      LDC(1.414213562373095048801688724209698079)     
/* sqrt(2) */
+#define        GAWK_SQRT1_2    LDC(0.707106781186547524400844362104849039)     
/* 1/sqrt(2) */
 
+#define        GAWK_PI         LDC(3.141592653589793238462643383279502884)     
/* pi */
+#define        GAWK_PI_2       LDC(1.570796326794896619231321691639751442)     
/* pi/2 */
+#define        GAWK_PI_4       LDC(0.785398163397448309615660845819875721)     
/* pi/4 */
+#define        GAWK_PI_4_HIGH  LDC(0.78539816313423216342926025390625)         
/* 32-bit 1st part */
+#define        GAWK_PI_4_MED   LDC(2.632161460363116600724708860070677474e-10) 
/* 32-bit 2nd part */
+#define        GAWK_PI_4_LOW   LDC(1.500889318411548350422246024296643642e-19) 
/* variable precision 3rd part */
 
 static AWKLDBL taylor_exp(AWKLDBL x);
+static AWKLDBL taylor_cos(AWKLDBL x);
+static AWKLDBL taylor_sin(AWKLDBL x);
+static AWKLDBL euler_atan_1(AWKLDBL x);
 static AWKLDBL gawk_frexpl(AWKLDBL x, int *exponent);
 
+/* gawk_sinl --- Compute sin(x) */
+
 static AWKLDBL
 gawk_sinl(AWKLDBL x)
 {
-       return sin( (double) x);
+       AWKLDBL sinval, dq;
+       int sign = 1;
+
+       if (isinf(x) || isnan(x))
+               return GAWK_NAN;
+
+       if (x == _0L)   /* XXX: sin(-0.0) = -0.0 */
+               return x;
+
+       if (x < _0L) {
+               /* sin(-x) = - sin(x) */
+               sign = -1;
+               x = -x;
+       }
+
+       /* range reduction -- 0 <= x < pi / 4 */
+
+       dq = double_to_int(x / GAWK_PI_4);
+
+       if (dq < pow2ld(32)) {
+               gawk_uint_t q = (gawk_uint_t) dq; 
+
+               sign *= ( (q / 4) % 2 ? -1 : 1 );
+               switch (q % 4) {
+               case 0:
+                       x -= q * GAWK_PI_4_HIGH;
+                       x -= q * GAWK_PI_4_MED;
+                       x -= q * GAWK_PI_4_LOW;
+                       sinval = taylor_sin(x);
+                       break;
+               case 1:
+                       q++;
+                       x -= q * GAWK_PI_4_HIGH;
+                       x -= q * GAWK_PI_4_MED;
+                       x -= q * GAWK_PI_4_LOW;
+                       sinval = taylor_cos(-x);
+                       break;
+               case 2:
+                       x -= q * GAWK_PI_4_HIGH;
+                       x -= q * GAWK_PI_4_MED;
+                       x -= q * GAWK_PI_4_LOW;
+                       sinval = taylor_cos(x);
+                       break;
+               case 3:
+                       q++;
+                       x -= q * GAWK_PI_4_HIGH;
+                       x -= q * GAWK_PI_4_MED;
+                       x -= q * GAWK_PI_4_LOW;
+                       sinval = taylor_sin(-x);
+                       break;
+               default:
+                       break;
+               }
+       } else {
+               /* FIXME -- Payne and Hanek Reduction Algorithm ? */
+
+               sinval = (AWKLDBL) sin( (double) x);
+       }
+
+       return sign > 0 ? sinval : -sinval;
 }
 
+/* gawk_cosl --- Compute cos(x) */
+
 static AWKLDBL
 gawk_cosl(AWKLDBL x)
 {
-       return cos( (double) x);
+       AWKLDBL cosval, dq;
+       int sign = 1;
+
+       if (isinf(x) || isnan(x))
+               return GAWK_NAN;
+       if (x < _0L) {
+               /* cos(-x) = cos(x) */
+               x = -x;
+       }
+       if (x == _0L)
+               return _1L;
+
+       /* range reduction -- 0 <= x < pi / 4 */
+
+       dq = double_to_int(x / GAWK_PI_4);
+
+       if (dq < pow2ld(32)) {
+               gawk_uint_t q = (gawk_uint_t) dq; 
+
+               sign *= ( (q / 4) % 2 ? -1 : 1 );
+               switch (q % 4) {
+               case 0:
+                       x -= q * GAWK_PI_4_HIGH;
+                       x -= q * GAWK_PI_4_MED;
+                       x -= q * GAWK_PI_4_LOW;
+                       cosval = taylor_cos(x);
+                       break;
+               case 1:
+                       q++;
+                       x -= q * GAWK_PI_4_HIGH;
+                       x -= q * GAWK_PI_4_MED;
+                       x -= q * GAWK_PI_4_LOW;
+                       cosval = taylor_sin(-x);
+                       break;
+               case 2:
+                       x -= q * GAWK_PI_4_HIGH;
+                       x -= q * GAWK_PI_4_MED;
+                       x -= q * GAWK_PI_4_LOW;
+                       cosval = -taylor_sin(x);
+                       break;
+               case 3:
+                       q++;
+                       x -= q * GAWK_PI_4_HIGH;
+                       x -= q * GAWK_PI_4_MED;
+                       x -= q * GAWK_PI_4_LOW;
+                       cosval = -taylor_cos(-x);
+                       break;
+               default:
+                       break;
+               }
+       } else {
+               /* FIXME Payne and Hanek Reduction Algorithm ? */
+
+               cosval = (AWKLDBL) cos( (double) x);
+       }
+
+       return sign > 0 ? cosval : -cosval;
 }
 
+
+/* gawk_atan2l(x) --- Compute atan2(y, x) */
+
 static AWKLDBL
 gawk_atan2l(AWKLDBL y, AWKLDBL x)
 {
-       return atan2( (double) y, (double) x);
+       int sign;
+
+       /*
+        * Using Euler atan(1/x) and the identity:
+        *      atan(x) = - pi / 2 - atan(1/x),         x < 0
+        *              = pi / 2 - atan(1/x),           x > 0
+        */
+
+       if (isnan(x) || isnan(y))
+               return GAWK_NAN;
+
+       if (isinf(y)) {
+               if (y > _0L) {
+                       if (isinf(x))
+                               return x < _0L ? _3L * GAWK_PI_4 : GAWK_PI_4;
+                       return GAWK_PI_2;
+               }
+               if (isinf(x))
+                       return x < _0L ? -_3L * GAWK_PI_4 : -GAWK_PI_4;
+               return -GAWK_PI_2;
+       }
+
+       if (isinf(x)) {
+               if (x > _0L)
+                       return y < _0L ? -_0L : _0L;
+               /* x = -Infinity */
+               return (y >= _0L) ? GAWK_PI : -GAWK_PI;
+       }
+
+       if (x > _0L) {
+               if (y == _0L)
+                       return y;       /* +0 or -0 */
+               sign = 1;
+               if (y < _0L) {
+                       sign = -1;
+                       y = -y;
+               }
+               if (y > x)
+                       return sign * (GAWK_PI_2 - euler_atan_1(y / x));
+               return sign * euler_atan_1(x / y);
+       }
+
+       if (x < _0L) {
+               if (y == _0L)
+                       return atan2( (double) y, -_1L) < 0.0 ? -GAWK_PI : 
GAWK_PI;
+
+               x = -x;
+               if (y < _0L) {
+                       y = -y;
+                       if (y > x)
+                               return -GAWK_PI_2 - euler_atan_1(y / x);
+                       return euler_atan_1(x / y) - GAWK_PI;
+               }
+               /* y > 0 */
+               if (y > x)
+                       return GAWK_PI_2 + euler_atan_1(y / x);
+               return - euler_atan_1(x / y) + GAWK_PI;
+       }
+
+       /*
+        * XXX -- using atan2 instead of trying to detect +0 or -0. No need for 
signbit(x)!
+        * We need to make sure the value of y is in the double range;
+        * Replace positive (negative) y with 1 (-1), the actual value isn't 
important.
+        */
+
+       if ( y > _0L)
+               y = _1L;
+       else if (y < _0L)
+               y = -_1L;
+
+       /* x = +0 or -0 */
+       if (atan2( (double) y, (double) x) < 0.0)
+               return -GAWK_PI;
+       if (atan2( (double) y, (double) x) > 0.0)
+               return GAWK_PI;
+       /* x = +0 and y = +0 or -0 */
+       return _0L;
 }
 
+
 /* gawk_logl --- Compute log(x) */
 
 static AWKLDBL
@@ -459,7 +669,7 @@ taylor_exp(AWKLDBL x)
                return _1L;
 
        k = 1;
-       while (x > 0.001) {
+       while (x > LDC(0.001)) {
                /* XXX: For x <= 0.001, max(k) = 10, and max # of terms 6 
(80-bit) / 10 (128-bit) */
                
                x /= _2L; 
@@ -482,3 +692,117 @@ taylor_exp(AWKLDBL x)
                y = 2 * y + y * y;
        return y + _1L;
 }
+
+/* taylor_sin --- Compute sin(x) using Taylor series */
+
+static AWKLDBL
+taylor_sin(AWKLDBL x)
+{
+       AWKLDBL xpow, xpow_odd, sinval;
+       AWKLDBL err, term, fact;
+       unsigned int i;
+
+       assert(x >= _0L);
+
+       if (x == _0L)
+               return x;
+
+       i = 3;
+       fact = LDC(6.0);        /* 3! */
+       xpow = x * x;
+       xpow_odd = xpow * x;
+       sinval = x - xpow_odd / fact;
+
+       do {
+               fact *= (AWKLDBL) ((i + 1) * (i + 2));
+               i += 2;
+               xpow_odd *= xpow;
+               term = xpow_odd / fact;
+
+               fact *= (AWKLDBL) ((i + 1) * (i + 2));
+               i += 2;
+               xpow_odd *= xpow;
+               term -= xpow_odd / fact;
+
+               sinval += term;
+               err = term / sinval;
+       } while (err > REL_ERROR);
+       return sinval;
+}
+
+/* taylor_cos --- Compute cos(x) using Taylor series */
+
+static AWKLDBL
+taylor_cos(AWKLDBL x)
+{
+       AWKLDBL xpow, xpow_even, cosval;
+       AWKLDBL err, term, fact;
+       unsigned int i;
+
+       if (x == _0L)
+               return _1L;
+
+       i = 2;
+       fact = _2L;     /* 2! */
+       xpow = x * x;
+       xpow_even = xpow;
+       cosval = _1L - xpow / fact;
+
+       do {
+               fact *= (AWKLDBL) ((i + 1) * (i + 2));
+               i += 2;
+               xpow_even *= xpow;
+               term = xpow_even / fact;
+
+               fact *= (AWKLDBL) ((i + 1) * (i + 2));
+               i += 2;
+               xpow_even *= xpow;
+               term -= xpow_even / fact;
+
+               cosval += term;
+               err = term / cosval;
+       } while (err > REL_ERROR);
+       return cosval;
+}
+
+/* euler_atan_1 --- Compute Euler arctan(1/x) approximation */ 
+
+static AWKLDBL
+euler_atan_1(AWKLDBL x)
+{
+       AWKLDBL xpow2_plus_one, term, sum, err;
+       int sign = 1;
+       unsigned int i;
+
+       /*
+        * 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) + ...
+        */
+
+       if (x < _0L) {
+               sign = -1;
+               x = -x;
+       }
+
+       xpow2_plus_one = x * x + _1L;
+       term = x / xpow2_plus_one;
+       sum = term;
+       i = 0;
+
+       do {
+               term *= (AWKLDBL) (i + 2);
+               term /= ((AWKLDBL) (i + 3)) * xpow2_plus_one;
+               i += 2;
+               sum += term;
+               err = term / sum;
+       } while (err > REL_ERROR);
+
+       return sign > 0 ? sum : -sum;
+}
diff --git a/misc/ldbl-tests/pow.awk b/misc/ldbl-tests/pow.awk
index 0e75b56..73cf492 100644
--- a/misc/ldbl-tests/pow.awk
+++ b/misc/ldbl-tests/pow.awk
@@ -16,14 +16,8 @@ BEGIN {
        PREC = "quad"
        y1 += 0; y2 += 0; y3 += 0
 
-       if (y1 <= 1.0e750) {
-               printf("%*.*e\n", 0, DIG, y1)
-       }
-       if (y2 <= 1.0e750) {
-               printf("%*.*e\n", 0, DIG, y2)
-       }
-       if (y3 <= 1.0e750) {
-               printf("%*.*e\n", 0, DIG, y3)
-       }
+       printf("%*.*e\n", 0, DIG, y1)
+       printf("%*.*e\n", 0, DIG, y2)
+       printf("%*.*e\n", 0, DIG, y3)
        PREC = save_PREC
 }

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

Summary of changes:
 misc/ChangeLog          |    7 +
 misc/Makefile           |   69 +++++++---
 misc/floatcmp.awk       |   27 +++-
 misc/fp_math.awk        |    2 +-
 misc/gawk_math.c        |  340 +++++++++++++++++++++++++++++++++++++++++++++-
 misc/ldbl-tests/pow.awk |   12 +--
 6 files changed, 415 insertions(+), 42 deletions(-)


hooks/post-receive
-- 
gawk



reply via email to

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