From keithp at keithp.com Thu Sep 17 15:03:39 2009 From: keithp at keithp.com (Keith Packard) Date: Thu, 17 Sep 2009 15:03:39 -0700 (PDT) Subject: [Nickle] nickle: Changes to 'refs/tags/2.69' Message-ID: <20090917220339.44B23B84006@keithp.com> Tag '2.69' created by Keith Packard at 2009-09-17 23:03 -0700 Version 2.69 -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.10 (GNU/Linux) iD8DBQBKsrIvQp8BWwlsTdMRAkr7AKDVpT/LF5GTBYzxZHsXVkrIQ3gaUwCfZ5eX MAAAqpOmNX2WfWGOj1x5M8s= =3oZy -----END PGP SIGNATURE----- Changes since 2.68-9: --- 0 files changed --- From keithp at keithp.com Thu Sep 17 15:07:36 2009 From: keithp at keithp.com (Keith Packard) Date: Thu, 17 Sep 2009 15:07:36 -0700 (PDT) Subject: [Nickle] nickle: Changes to 'refs/tags/2.69' Message-ID: <20090917220736.B22BDB84011@keithp.com> Tag '2.69' created by Keith Packard at 2009-09-17 23:07 -0700 Version 2.69 -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.10 (GNU/Linux) iD8DBQBKsrMVQp8BWwlsTdMRAgjgAKC16IH87xHr1RVi+nsEG3IQNEg5WQCfXfZ4 i/to+uiCHVpz7t0+aJeWifc= =0SFO -----END PGP SIGNATURE----- Changes since 2.68-15: --- 0 files changed --- From keithp at keithp.com Thu Sep 17 15:07:36 2009 From: keithp at keithp.com (Keith Packard) Date: Thu, 17 Sep 2009 15:07:36 -0700 (PDT) Subject: [Nickle] nickle: Branch 'master' - 10 commits Message-ID: <20090917220736.9B8B6B84006@keithp.com> .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 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 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 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 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 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 -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 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 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 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 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 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 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 -Build-Depends: debhelper (>= 4), libreadline5-dev +Build-Depends: debhelper (>= 4), libreadline-dev Standards-Version: 3.8.0 Package: nickle commit ac6bdfab92361bc999323e1f4bb1fa022527fd16 Author: Keith Packard 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 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 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 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 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 +#include +#include + +#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 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 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)