[Nickle] nickle: Branch 'master' - 10 commits

Keith Packard keithp at keithp.com
Thu Sep 17 15:07:36 PDT 2009


 .gitignore         |    9 +++
 Makefile.am        |    3 -
 configure.in       |    2 
 debian/changelog   |   14 ++++-
 debian/compat      |    2 
 debian/control     |    6 +-
 debian/rules       |    2 
 math.5c            |   83 +++++++++++++++---------------
 test/Makefile.am   |   14 ++++-
 test/math-tables.c |  129 +++++++++++++++++++++++++++++++++++++++++++++++
 test/math.5c       |  143 +++++++++++++++++++++++++++++++++++++++++++++++++++++
 11 files changed, 356 insertions(+), 51 deletions(-)

New commits:
commit 4c6a840a3f2596bf6565f1b9906b2500852b66c6
Author: Keith Packard <keithp at keithp.com>
Date:   Thu Sep 17 15:03:12 2009 -0700

    Update to version 2.69

diff --git a/configure.in b/configure.in
index 95fe2e3..81fd8a6 100644
--- a/configure.in
+++ b/configure.in
@@ -7,7 +7,7 @@ dnl for licensing information.
 AC_PREREQ(2.59)
 
 AC_INIT([nickle],
-	2.68,
+	2.69,
 	[http://nickle.org],
 	nickle)
 
diff --git a/debian/changelog b/debian/changelog
index fc12f97..6d0e977 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,3 +1,13 @@
+nickle (2.69-1) unstable; urgency=low
+
+  * Make debian build epend on libreadline-dev not libreadline5-dev.
+  * Get math-tables.5c built before tests are run
+  * Fix trig boundary conditions.
+  * Add tests for math functions.
+  * math.5c: fix quadrant errors in atan/asin/acos
+
+ -- Keith Packard <keithp at keithp.com>  Thu, 17 Sep 2009 14:30:42 -0700
+
 nickle (2.68-1) unstable; urgency=low
 
   * Add README.release
@@ -22,7 +32,7 @@ nickle (2.67-1) unstable; urgency=low
 nickle (2.66-1) unstable; urgency=low
   * Support autoload/autoimport of nested namespaces.
   * Allow 'print' to find unpublished names
-  
+
  -- Keith Packard <keithp at keithp.com>  Sun, 13 Jan 2008 17:39:49 -0800
 
 nickle (2.65-1) unstable; urgency=low
@@ -31,7 +41,7 @@ nickle (2.65-1) unstable; urgency=low
   * Check for duplicate func param/struct member names
 
  -- Keith Packard <keithp at keithp.com>  Sun, 06 Jan 2008 16:38:51 -0800
- 
+
 nickle (2.64-1) unstable; urgency=low
   * Fix float floor/ceil with small values
   * Copy hash key/value on insert
commit eaf3950ad5308e33a5dbfd8b1c921ae2603fd5c5
Author: Keith Packard <keithp at keithp.com>
Date:   Thu Sep 17 14:59:31 2009 -0700

    Update to standards 3.8.3 and debhelper 7

diff --git a/debian/compat b/debian/compat
index b8626c4..7f8f011 100644
--- a/debian/compat
+++ b/debian/compat
@@ -1 +1 @@
-4
+7
diff --git a/debian/control b/debian/control
index bec3cb3..9d8f7e5 100644
--- a/debian/control
+++ b/debian/control
@@ -2,12 +2,12 @@ Source: nickle
 Section: interpreters
 Priority: optional
 Maintainer: Keith Packard <keithp at keithp.com>
-Build-Depends: debhelper (>= 4), libreadline-dev 
-Standards-Version: 3.8.0
+Build-Depends: debhelper (>= 7), libreadline-dev 
+Standards-Version: 3.8.3
 
 Package: nickle
 Architecture: any
-Depends: ${shlibs:Depends} ${misc:Depends}
+Depends: ${shlibs:Depends}, ${misc:Depends}
 Description: desk calculator language
  Nickle is a language with powerful programming and scripting capabilities.
  Nickle supports a variety of datatypes, especially arbitrary precision
diff --git a/debian/rules b/debian/rules
index e53b769..a24c3fd 100755
--- a/debian/rules
+++ b/debian/rules
@@ -28,7 +28,7 @@ clean:
 install: build
 	dh_testdir
 	dh_testroot
-	dh_clean -k
+	dh_prep
 	dh_installdirs
 	$(MAKE) install DESTDIR=$(CURDIR)/debian/tmp
 	pwd
commit b9bae75689465f0572deed07d0514f546648d32a
Author: Keith Packard <keithp at keithp.com>
Date:   Thu Sep 17 14:58:49 2009 -0700

    Remove debian dir from debian orig.tar.gz file

diff --git a/Makefile.am b/Makefile.am
index 4d1cf69..7611173 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -110,6 +110,7 @@ $(DEB_TAR): $(TARFILE)
 	rm -rf $(DEB_TAR_DIR)
 	tar xzf $(TARFILE)
 	mv $(distdir) $(DEB_TAR_DIR)
+	rm -rf $(DEB_TAR_DIR)/debian
 	tar czf $(DEB_TAR) $(DEB_TAR_DIR)
 
 nickle.1: nickle.1.in config.h
commit bb5e73b56f322a04d914f48856d72c4d00626214
Author: Keith Packard <keithp at keithp.com>
Date:   Thu Sep 17 14:39:48 2009 -0700

    Ignore more files

diff --git a/.gitignore b/.gitignore
index 0ec1e2d..d3d90bb 100644
--- a/.gitignore
+++ b/.gitignore
@@ -22,3 +22,12 @@ version-sh
 nickle-[1-9].*
 nickle_[1-9].*
 nickle
+ChangeLog
+build-stamp
+configure-stamp
+debian/files
+debian/nickle.debhelper.log
+debian/nickle.substvars
+test/math-tables
+test/math-tables.5c
+ylwrap
commit a85c4aba193b67294c8bafeec24ce7c2b32ea75c
Author: Keith Packard <keithp at keithp.com>
Date:   Thu Sep 17 14:28:30 2009 -0700

    Byacc now makes tables const by default. Remove Makefile.am hacks.
    
    The Makefile.am hacks served to turn the parser tables into constant
    data to save a bit of memory. That's no longer necessary now that
    byacc does this automatically.
    
    Signed-off-by: Keith Packard <keithp at keithp.com>

diff --git a/Makefile.am b/Makefile.am
index 168115e..4d1cf69 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -85,8 +85,6 @@ USES_GRAM_H = \
 
 $(USES_GRAM_H): gram.h
 
-YACCCOMPILE = $(YACC) $(YFLAGS) $(AM_YFLAGS) && sed -i 's/^short yy/static const short yy/' y.tab.c && echo
-
 builtin.o main.o: Makefile
 
 TARFILE=$(PACKAGE)-$(VERSION).tar.gz
commit fb02b3053b9615b6872352fa0581ee68d047b625
Author: Keith Packard <keithp at keithp.com>
Date:   Thu Sep 17 11:56:09 2009 -0700

    Make debian build epend on libreadline-dev not libreadline5-dev.
    
    This ensures that we'll pick up any new readline versions as released.
    
    Signed-off-by: Keith Packard <keithp at keithp.com>

diff --git a/debian/control b/debian/control
index 64bf0c3..bec3cb3 100644
--- a/debian/control
+++ b/debian/control
@@ -2,7 +2,7 @@ Source: nickle
 Section: interpreters
 Priority: optional
 Maintainer: Keith Packard <keithp at keithp.com>
-Build-Depends: debhelper (>= 4), libreadline5-dev 
+Build-Depends: debhelper (>= 4), libreadline-dev 
 Standards-Version: 3.8.0
 
 Package: nickle
commit ac6bdfab92361bc999323e1f4bb1fa022527fd16
Author: Keith Packard <keithp at keithp.com>
Date:   Thu Sep 17 10:20:11 2009 -0700

    Get math-tables.5c built before tests are run
    
    This file is used by math.5c and is built by running the math-tables
    program; adding a dependency from math.5c appears to make sure it is
    built at the right time.
    
    Signed-off-by: Keith Packard <keithp at keithp.com>

diff --git a/test/Makefile.am b/test/Makefile.am
index 5e12384..96e9f89 100644
--- a/test/Makefile.am
+++ b/test/Makefile.am
@@ -14,13 +14,14 @@ noinst_PROGRAMS=math-tables
 
 TABLES=math-tables.5c
 
+CLEANFILES=$(TABLES)
+
 TESTS_ENVIRONMENT=NICKLESTART=$(top_srcdir)/builtin.5c NICKLEPATH=$(top_srcdir) ../nickle
 TESTS=$(check_SCRIPTS)
 
 EXTRA_DIST=$(check_SCRIPTS)
 
+math.5c: $(TABLES)
+
 $(TABLES): math-tables
 	./math-tables > $(TABLES)
-
-
-check-TESTS: math-tables.5c
commit 0a80c1f7816a19970a0751af5baaaf0643f68bdd
Author: Keith Packard <keithp at keithp.com>
Date:   Thu Sep 17 10:00:11 2009 -0700

    Fix trig boundary conditions.
    
    limit angles to -π - π, make sincos generate correct signs, make
    atan2(0,0) return 0.

diff --git a/math.5c b/math.5c
index 0bebd2e..a6cd170 100644
--- a/math.5c
+++ b/math.5c
@@ -37,6 +37,9 @@ extend namespace Math {
 	    return abs (1/cur);
 	}
 
+	if (v == 0)
+		return 0;
+
 	if (is_rational (v))
 	{
 	    int	num, den;
@@ -544,15 +547,17 @@ extend namespace Math {
 	return imprecise (local_pi, prec);
     }
     
+    /* Normalize angle to -π < aa <= π */
     real limit_angle_to_pi (real aa)
     {
 	real	my_pi;
 
 	aa = imprecise (aa);
 	my_pi = pi_value (precision (aa));
+	aa %= 2 * my_pi;
 	if (aa > my_pi)
-	    aa = aa - 2 * my_pi;
-	return aa % (2 * my_pi);
+		aa -= 2 * my_pi;
+	return aa;
     }
     
     public real sin (real a)
@@ -690,7 +695,7 @@ extend namespace Math {
 
 	a = limit_angle_to_pi (a);
 	c = cos (a);
-	s = sign(a) * abs (cos_to_sin(c));
+	s = sign(a) * cos_to_sin(c);
         *cosp = c;
         *sinp = s;
     }
@@ -702,7 +707,7 @@ extend namespace Math {
     {
 	real	c, s;
 
-	a = imprecise (a);
+	a = imprecise(a);
 	sin_cos (a, &s, &c);
 	return s/c;
     }
@@ -783,6 +788,8 @@ extend namespace Math {
 	x = imprecise (x);
 
 	if (x == 0) {
+		if (y == 0)
+			return 0;
 		if (y >= 0)
 			return pi_value(precision(y))/2;
 		else
commit 8aa40d0d867bcfe8b917c49b7d36138c835130c2
Author: Keith Packard <keithp at keithp.com>
Date:   Thu Sep 17 09:58:56 2009 -0700

    Add tests for math functions.
    
    These compare the results of nickle with the C library math functions
    to provide a rough check of correctness as well as checking various
    boundary conditions for the functions.
    
    Signed-off-by: Keith Packard <keithp at keithp.com>

diff --git a/test/Makefile.am b/test/Makefile.am
index f3d78e4..5e12384 100644
--- a/test/Makefile.am
+++ b/test/Makefile.am
@@ -7,9 +7,20 @@ check_SCRIPTS=gcdtest.5c \
 	modtest.5c \
 	hashtest.5c \
 	signal.5c \
-	round.5c
+	round.5c \
+	math.5c
+
+noinst_PROGRAMS=math-tables
+
+TABLES=math-tables.5c
 
 TESTS_ENVIRONMENT=NICKLESTART=$(top_srcdir)/builtin.5c NICKLEPATH=$(top_srcdir) ../nickle
 TESTS=$(check_SCRIPTS)
 
 EXTRA_DIST=$(check_SCRIPTS)
+
+$(TABLES): math-tables
+	./math-tables > $(TABLES)
+
+
+check-TESTS: math-tables.5c
diff --git a/test/math-tables.c b/test/math-tables.c
new file mode 100644
index 0000000..129c989
--- /dev/null
+++ b/test/math-tables.c
@@ -0,0 +1,129 @@
+#include <math.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#define FMT	"%25.17f"
+
+double
+print_val(double x)
+{
+	if (isnan(x))
+		return 10000;
+	if (x > 1e10)
+		return 9999;
+	if (x < -1e10)
+		return 9999;
+	if (fabs(x) < 1e-20)
+		return 0;
+	return x;
+}
+
+static void
+sin_cos_table(void)
+{
+	double	a;
+	double	r;
+
+	printf ("/* %20.15f */\n", asin(-1));
+	printf ("typedef struct { real angle, sin, cos; } sin_cos_t;\n");
+	printf ("sin_cos_t[] sin_cos_table = {\n");
+	for (a = -800; a <= 800; a += 1) {
+		double a_f = a / 100;
+		printf ("\t{ .angle =     " FMT ", .sin = " FMT ", .cos = " FMT " },\n",
+			a_f, print_val(sin(a_f)), print_val(cos(a_f)));
+		printf ("\t{ .angle = π * " FMT ", .sin = " FMT ", .cos = " FMT " },\n",
+			a_f, print_val(sin(M_PI * a_f)), print_val(cos(M_PI * a_f)));
+	}
+	printf ("};\n");
+
+	printf ("typedef struct { real ratio, asin, acos; } asin_acos_t;\n");
+	printf ("asin_acos_t[] asin_acos_table = {\n");
+	for (r = -200; r <= 200; r += 1) {
+		double r_f = r / 100;
+		printf ("\t{ .ratio = " FMT ", .asin = " FMT ", .acos = " FMT " },\n",
+			r_f, print_val(asin(r_f)), print_val(acos(r_f)));
+	}
+	printf ("};\n");
+}
+
+static void
+tan_table(void)
+{
+	double	a;
+	double	r;
+	double	x, y;
+
+	printf ("typedef struct { real angle, tan; } tan_t;\n");
+	printf ("tan_t[] tan_table = {\n");
+	for (a = -800; a <= 800; a += 1) {
+		double a_f = a/100;
+		printf ("\t{ .angle =     " FMT ", .tan = " FMT " },\n",
+			a_f, print_val(tan(a_f)));
+		printf ("\t{ .angle = π * " FMT ", .tan = " FMT " },\n",
+			a_f, print_val(tan(M_PI * a_f)));
+	}
+	printf ("};\n");
+
+	printf ("typedef struct { real ratio, atan; } atan_t;\n");
+	printf ("atan_t[] atan_table = {\n");
+	for (r = -1000; r <= 1000; r += 1) {
+		double r_f = r / 10;
+		printf ("\t{ .ratio = " FMT ", .atan = " FMT " },\n",
+			r_f, print_val(atan(r_f)));
+	}
+	printf ("};\n");
+	
+	printf ("typedef struct { real y, x, atan2; } atan2_t;\n");
+	printf ("atan2_t[] atan2_table = {\n");
+	for (y = -30; y <= 30; y += 1) {
+		double y_f = y / 10;
+		for (x = -30; x <= 30; x += 1) {
+			double x_f = x/10;
+			double v;
+
+			/*
+			 * looks like glibc has a bug -- atan2(0,0) returns
+			 * π/4 instead of 0
+			 */
+			if (y_f == 0 && x_f == 0)
+				v = 0;
+			else
+				v = atan2(y_f,x_f);
+
+			printf ("\t{ .y = " FMT ", .x = " FMT ", .atan2 = " FMT " },\n",
+				y_f, x_f, print_val(v));
+		}
+	}
+	printf ("};\n");
+}
+
+void
+log_table(void)
+{
+	double	v;
+	printf ("typedef struct { real in, log; } log_t;\n");
+	printf ("log_t[] log_table = {\n");
+	for (v = 1; v < 1e20; v *= 2) {
+		double v_f = v/1e6;
+		printf("\t{ .in = " FMT ", .log = " FMT " },\n",
+		       v_f, log(v_f));
+	}
+	printf ("};\n");
+	printf ("typedef struct { real in, exp; } exp_t;\n");
+	printf ("exp_t[] exp_table = {\n");
+	for (v = -1000; v < 1000; v += 1) {
+		double v_f = v/100;
+		printf("\t{ .in = " FMT ", .exp = " FMT " },\n",
+		       v_f, exp(v_f));
+	}
+	printf ("};\n");
+}
+
+int
+main(int argc, char **argv)
+{
+	sin_cos_table();
+	tan_table();
+	log_table();
+	exit(0);
+}
diff --git a/test/math.5c b/test/math.5c
new file mode 100644
index 0000000..902f03b
--- /dev/null
+++ b/test/math.5c
@@ -0,0 +1,143 @@
+/*
+ * Nickle test suite
+ *
+ * Trig operator tests
+ */
+
+load "math-tables.5c"
+
+int precision = 64;
+int errors = 0;
+
+real checked(real(real) f, real a) {
+	try {
+		real r = f(imprecise (a, precision));
+		if (r > 1e10)
+			return 9999;
+		if (r < -1e10)
+			return 9999;
+		return r;
+	} catch invalid_argument(string type, int i, real v) {
+		return 10000;
+	}
+	return 0;
+}
+
+real checked2(real(real, real) f, real a, real b) {
+	try {
+		real r = f(imprecise(a, precision), imprecise(b, precision));
+
+		/* Just return the same value for large magnitudes
+		 * as small variations in input cause the sign to flip
+		 */
+		 
+		if (r > 1e10)
+			return 9999;
+		if (r < -1e10)
+			return 9999;
+		return r;
+	} catch invalid_argument(string type, int i, real v) {
+		return 10000;
+	}
+	return 0;
+}
+
+void check(string op, real(real) f, real input, real correct)
+{
+	real	value = checked(f, input);
+	
+	if (is_number (value))
+	{
+		real	error = abs (value - correct);
+
+		if (abs(correct) >= 1 && error < abs(correct) * 1e-8)
+			return;
+		if (abs(correct) < 1 && error < 1e-8)
+			return;
+		printf ("error %v value %v\n", error, value);
+	}
+	if (value != correct) {
+		printf ("check failed %s(%v) (was %.-g, should be %.-g)",
+			op, input, value, correct);
+		errors++;
+	}
+}
+
+void check2(string op, real(real, real) f, real input1, real input2, real correct)
+{
+	real	value = checked2(f, input1, input2);
+	
+	if (is_number (value))
+	{
+		real	error = abs (value - correct);
+
+		if (abs(correct) >= 1 && error < abs(correct) * 1e-10)
+			return;
+		if (abs(correct) < 1 && error < 1e-10)
+			return;
+		printf ("error %v value %v\n", error, value);
+	}
+	if (value != correct) {
+		printf ("check failed %s(%.-g, %.-g) (was %.-g, should be %.-g)",
+			op, input1, input2, value, correct);
+		errors++;
+	}
+}
+
+void check_sin_cos()
+{
+	for (int i = 0; i < dim(sin_cos_table); i++) {
+		real	angle = sin_cos_table[i].angle;
+		real	sin_value = sin_cos_table[i].sin;
+		real	cos_value = sin_cos_table[i].cos;
+		check("sin", sin, angle, sin_value);
+		check("cos", cos, angle, cos_value);
+	}
+	for (int i = 0; i < dim(asin_acos_table); i++) {
+		real	ratio = asin_acos_table[i].ratio;
+		real	asin_value = asin_acos_table[i].asin;
+		real	acos_value = asin_acos_table[i].acos;
+		check("asin", asin, ratio, asin_value);
+		check("acos", acos, ratio, acos_value);
+	}
+}
+
+void check_tan()
+{
+	for (int i = 0; i < dim(tan_table); i++) {
+		real angle = tan_table[i].angle;
+		real tan_value = tan_table[i].tan;
+		check("tan", tan, angle, tan_value);
+	}
+	for (int i = 0; i < dim(atan_table); i++) {
+		real ratio = atan_table[i].ratio;
+		real atan_value = atan_table[i].atan;
+		check("atan", atan, ratio, atan_value);
+	}
+	for (int i = 0; i < dim(atan2_table); i++) {
+		real y = atan2_table[i].y;
+		real x = atan2_table[i].x;
+		real atan2_value = atan2_table[i].atan2;
+		check2("atan2", atan2, y, x, atan2_value);
+	}
+}
+
+void check_log()
+{
+	for (int i = 0; i < dim(log_table); i++) {
+		real in = log_table[i].in;
+		real log_value = log_table[i].log;
+		check("log", log, in, log_value);
+	}
+	for (int i = 0; i < dim(exp_table); i++) {
+		real in = exp_table[i].in;
+		real exp_value = exp_table[i].exp;
+		check("exp", exp, in, exp_value);
+	}
+}
+
+check_sin_cos();
+check_tan();
+check_log();
+
+exit (errors);
commit cab93dd5f5a04ce53bf826d9a0e5e8063bd293a6
Author: Keith Packard <keithp at keithp.com>
Date:   Sun Jun 14 17:27:16 2009 -0700

    math.5c: fix quadrant errors in atan/asin/acos
    
    All of these had various quadrant related errors.
    
    Signed-off-by: Keith Packard <keithp at keithp.com>

diff --git a/math.5c b/math.5c
index 16993df..0bebd2e 100644
--- a/math.5c
+++ b/math.5c
@@ -772,6 +772,34 @@ extend namespace Math {
     }
     
     /*
+     * atan (y/x)
+     */
+    public real atan2 (real y, real x)
+	/*
+	 * return atan (y/x), but adjust for quadrant correctly
+	 */
+    {
+	y = imprecise (y);
+	x = imprecise (x);
+
+	if (x == 0) {
+		if (y >= 0)
+			return pi_value(precision(y))/2;
+		else
+			return -pi_value(precision(y))/2;
+	}
+	real a = atan(y/x);
+	if (x < 0) {
+		real p = pi_value(precision(y));
+		if (y >= 0)
+			a += p;
+		else
+			a -= p;
+	}
+	return a;
+    }
+
+    /*
      *	atan(v) = asin(v/sqrt(1+v**2))
      *
      *	q = v/sqrt(1+v**2)
@@ -783,7 +811,7 @@ extend namespace Math {
      *  v**2 = q**2/(1-q**2)
      *  v = q/sqrt(1-q**2)
      *
-     *  asin(q) = atan(q/sqrt(1-q**2))
+     *  asin(q) = atan2(q, sqrt(1-q**2))
      */
     
     public real asin (real v)
@@ -798,14 +826,14 @@ extend namespace Math {
 	    return pi_value (precision (v))/2;
 	if (v == -1)
 	    return -pi_value (precision (v))/2;
-	return atan (v/sqrt(1-v**2));
+	return atan2(v, sqrt(1-v**2));
     }
 
     /*
      * acos(v) = asin (sqrt (1 - v**2))
      *		= atan (sqrt(1-v**2) / sqrt (1-(sqrt (1-v**2))**2))
      *		= atan (sqrt(1-v**2) / sqrt (1-(1-v**2)))
-     *		= atan (sqrt(1-v**2) / v)
+     *		= atan2 (sqrt(1-v**2), v)
      */
     public real acos (real v)
 	/*
@@ -821,42 +849,10 @@ extend namespace Math {
 	    return pi_value(precision(v));
 	if (v == 0)
 	    return pi_value(precision(v))/2;
-	return atan (sqrt (1-v**2)/v);
+	return atan2 (sqrt (1-v**2), v);
     }
 	
     /*
-     * atan (y/x)
-     */
-    public real atan2 (real y, real x)
-	/*
-	 * return atan (y/x), but adjust for quadrant correctly
-	 */
-    {
-	y = imprecise (y);
-	x = imprecise (x);
-	if (y == 0)
-	{
-	    if (x >= 0)
-		return 0;
-	    return pi_value (precision (y));
-	}
-	if (x == 0)
-	    return sign(y) * pi_value (precision (y))/2;
-
-	real	a;
-
-	a = atan (y/x);
-	if (x < 0)
-	{
-	    if (y >= 0)
-		a += pi_value (precision (a));
-	    else
-		a -= pi_value (precision (a));
-	}
-	return a;
-    }
-
-    /*
      * These two are used for the '**' and '**=' operators
      */
     public real pow (real a, real b)


More information about the Nickle mailing list