From keithp at keithp.com Sun Jul 4 21:23:56 2010 From: keithp at keithp.com (Keith Packard) Date: Mon, 05 Jul 2010 00:23:56 -0400 Subject: [Nickle] Fwd: nickle slow for large factorials In-Reply-To: References: Message-ID: On Mon, 5 Jul 2010 02:48:37 +0200, Michel Alexandre Salim wrote: > Ah, thanks. Any reason why the memory consumption is so high even the > tail-recursive implementation? Memory usage should be not much worse > than whatever it takes to represent 666666! in memory. You can't do trivial tail recursion in the factorial function -- you have to perform additional computation after each recursive function: int fact(n) = n > 1 ? n*fact(n-1) : 1; The killer here is the n* -- without that, you have a simple tail recursive function. Refactor this into a pure tail call: int fact2(n,m) { if (n <= 1) return m; return fact2(n-1,n*m); } int fact(n) { return fact2(n,1); } and now you get the tail call behaviour. You'll note that the internal factorial implementation isn't recursive, and so avoids consuming huge amounts of memory; I'm testing a couple of faster factorial functions as described here: http://www.luschny.de/math/factorial/FastFactorialFunctions.htm I've got both the Split and PrimeSwing algorithms implemented and they seem to work reasonably well; your test value (666666) runs in about a minute using the most obvious nickle translation of either function. I'm testing with some larger values; 6666666 appears to take somewhat longer than I'm willing to wait this evening. GMP doesn't appear to use anything much fancier than the most obvious factorial algorithm, simply re-ordering the multiplies to try and get some balance into the terms so that the Karatsuba multiplication code runs more efficiently. -- keith.packard at intel.com -------------- next part -------------- A non-text attachment was scrubbed... Name: not available Type: application/pgp-signature Size: 189 bytes Desc: not available URL: From keithp at keithp.com Mon Jul 5 05:32:25 2010 From: keithp at keithp.com (Keith Packard) Date: Mon, 05 Jul 2010 08:32:25 -0400 Subject: [Nickle] Fwd: nickle slow for large factorials In-Reply-To: References: Message-ID: On Mon, 5 Jul 2010 10:01:21 +0200, Michel Alexandre Salim wrote: > I forgot to mention that this is in fact what I implemented, and htop > still reports memory consumption in the hundreds of megabytes, and ! > does so too. I wonder if nickle's numerical system is leaking memory? I suspect the nickle compiler just didn't figure out that you were doing tail recursion; in particular, it doesn't figure it out if you're using ?: instead of if/then/else. Did you send me a copy of the code before? I can't find it now. -- keith.packard at intel.com -------------- next part -------------- A non-text attachment was scrubbed... Name: not available Type: application/pgp-signature Size: 189 bytes Desc: not available URL: From keithp at keithp.com Mon Jul 5 06:19:19 2010 From: keithp at keithp.com (Keith Packard) Date: Mon, 05 Jul 2010 09:19:19 -0400 Subject: [Nickle] Fwd: nickle slow for large factorials In-Reply-To: References: Message-ID: On Mon, 05 Jul 2010 08:32:25 -0400, Keith Packard wrote: > On Mon, 5 Jul 2010 10:01:21 +0200, Michel Alexandre Salim wrote: > > > I forgot to mention that this is in fact what I implemented, and htop > > still reports memory consumption in the hundreds of megabytes, and ! > > does so too. I wonder if nickle's numerical system is leaking memory? > > I suspect the nickle compiler just didn't figure out that you were doing > tail recursion; in particular, it doesn't figure it out if you're using > ?: instead of if/then/else. Did you send me a copy of the code before? I > can't find it now. Oh, there it is -- yes, nickle detects that as tail recursive and correctly limits memory usage, although it doesn't limit it very hard. You'll note that the memory usage goes up and down during the computation as it is allocating lots of temporary values (it doesn't try to re-use storage). It's not the bignum computations that are slow here; nickle has reasonably fast compute code. Of course, the trivial factorial implementation can't take advantage of the karatsuba multiplication function which only works with terms of comparable size, so it's just doing grade-school multiplication. -- keith.packard at intel.com -------------- next part -------------- A non-text attachment was scrubbed... Name: not available Type: application/pgp-signature Size: 189 bytes Desc: not available URL: From keithp at keithp.com Mon Jul 5 21:30:26 2010 From: keithp at keithp.com (Keith Packard) Date: Mon, 5 Jul 2010 21:30:26 -0700 (PDT) Subject: [Nickle] nickle: Branch 'master' Message-ID: <20100706043026.2C54D760254@keithp.com> Makefile.am | 3 + builtin-math.c | 10 ++++++ builtin.5c | 2 + compile.c | 18 ++++++++++- factorial.5c | 85 +++++++++++++++++++++++++++++++++++++++++++++++++++++ gram.y | 6 +++ math.5c | 3 + nickle.h | 1 prime_sieve.5c | 90 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 9 files changed, 215 insertions(+), 3 deletions(-) New commits: commit b249d719eeb86e8834ccfa2c91c4ead07d497e09 Author: Keith Packard Date: Tue Jul 6 00:28:41 2010 -0400 Replace na??ve factorial algorithm with prime sieve from Peter Luschny diff --git a/Makefile.am b/Makefile.am index 7611173..a66d6b6 100644 --- a/Makefile.am +++ b/Makefile.am @@ -12,7 +12,8 @@ BUILD_DATE := $(shell sh $(top_builddir)/date-sh) NICKLEFILES = builtin.5c math.5c scanf.5c mutex.5c \ arc4.5c prng.5c command.5c abort.5c \ printf.5c history.5c ctype.5c string.5c socket.5c \ - file.5c parse-args.5c svg.5c process.5c + file.5c parse-args.5c svg.5c process.5c \ + prime_sieve.5c factorial.5c DEBIAN = debian/nickle.install debian/changelog debian/compat \ debian/control debian/copyright debian/rules debian/lintian.override diff --git a/builtin-math.c b/builtin-math.c index 5066474..6b2f61c 100644 --- a/builtin-math.c +++ b/builtin-math.c @@ -28,6 +28,10 @@ import_Math_namespace() " int popcount (int i)\n" "\n" " Return the number of '1' bits in 'i'.\n" }, + { do_Math_factorial, "factorial", "i", "i", "\n" + " int factorial (int i)\n" + "\n" + " Return the factorial of 'i'.\n" }, { 0 } }; static const struct fbuiltin_2 funcs_2[] = { @@ -146,3 +150,9 @@ do_Math_popcount(Value v) { ENTER (); RETURN (Popcount (v)); } + +Value +do_Math_factorial(Value v) { + ENTER (); + RETURN (Factorial (v)); +} diff --git a/builtin.5c b/builtin.5c index ae36829..af07fce 100644 --- a/builtin.5c +++ b/builtin.5c @@ -117,6 +117,8 @@ library "command.5c"; # Note that some libraries extend namespaces, and # thus aren't autoload/autoimport candidates. library "math.5c"; +library "prime_sieve.5c" +library "factorial.5c" import Math; library "scanf.5c"; library "socket.5c"; diff --git a/compile.c b/compile.c index 82d7add..c0c6c65 100644 --- a/compile.c +++ b/compile.c @@ -2528,7 +2528,23 @@ _CompileExpr (ObjPtr obj, ExprPtr expr, Bool evaluate, ExprPtr stat, CodePtr cod case UMINUS: obj = CompileUnOp (obj, expr, NegateOp, stat, code); break; case LNOT: obj = CompileUnFunc (obj, expr, Lnot, stat, code,"~"); break; case BANG: obj = CompileUnFunc (obj, expr, Not, stat, code,"!"); break; - case FACT: obj = CompileUnFunc (obj, expr, Factorial, stat, code,"!"); break; + case FACT: + obj = _CompileExpr (obj, expr->tree.left, True, stat, code); + SetPush (obj); + obj = _CompileExpr (obj, expr->tree.right, True, stat, code); + expr->base.type = TypeCombineUnary (expr->tree.right->base.type, + expr->base.tag); + if (!expr->base.type) + { + CompileError (obj, stat, "Incompatible type, value '%T', for ! operation", + expr->tree.right->base.type); + expr->base.type = typePoly; + break; + } + BuildInst (obj, OpCall, inst, stat); + inst->ints.value = 1; + BuildInst (obj, OpNoop, inst, stat); + break; case INC: if (expr->tree.left) { diff --git a/factorial.5c b/factorial.5c new file mode 100644 index 0000000..7b5b8be --- /dev/null +++ b/factorial.5c @@ -0,0 +1,85 @@ +/* + * Copyright ?? 2010 Keith Packard and Bart Massey. + * All Rights Reserved. See the file COPYING in this directory + * for licensing information. + */ + +extend namespace Math { + /* + * PrimeSwing factorial algorithm by Peter Luschny + * + * Translated from the Java version as found here: + * + * http://www.luschny.de/math/factorial/FastFactorialFunctions.htm + * + * That code was released under the MIT license using this reference: + * + * http://www.opensource.org/licenses/mit-license.php + * + * This code is functionally equivalent, although is not a direct copy + */ + public int factorial(int n) + /* + * Return the factorial of 'n' + */ + { + + /* For small values, just do it the na??ve way */ + if (n < 20) { + int r = 1; + while (n > 0) { + r *= n; + n--; + } + return r; + } + + int plen = 2 * floor(sqrt(n) + n / (log2(n) - 1)); + int[plen] prime_list; + int[] primes = PrimeSieve::primes(n); + + static int[] smallOddSwing = { + 1, 1, 1, 3, 3, 15, 5, 35, 35, 315, 63, 693, 231, 3003, 429, + 6435, 6435, 109395, 12155, 230945, 46189, 969969, 88179, + 2028117, 676039, 16900975, 1300075, 35102025, 5014575, + 145422675, 9694845, 300540195, 300540195 + }; + + /* Compute the swing factorial of 'n' */ + int swing(int n) { + if (n < dim(smallOddSwing)) + return smallOddSwing[n]; + int sqrt_n = floor(sqrt(n)); + PrimeSieve::range_t r1 = PrimeSieve::primes_range(&primes, 3, sqrt_n); + PrimeSieve::range_t r2 = PrimeSieve::primes_range(&primes, sqrt_n + 1, n // 3); + int count = 0; + for (int i_p = r1.start; i_p < r1.end; i_p++) { + int prime = primes[i_p]; + int q = n, p = 1; + while ((q //= prime) > 0) + if ((q & 1) == 1) + p *= prime; + if (p > 1) + prime_list[count++] = p; + } + for (int i_p = r2.start; i_p < r2.end; i_p++) { + int prime = primes[i_p]; + if (((n // prime) & 1) == 1) + prime_list[count++] = prime; + } + int prod = PrimeSieve::primorial(&primes, n // 2 + 1, n); + for (int i = 0; i < count; i++) + prod *= prime_list[i]; + return prod; + } + + /* Final factorial computation */ + int recursive_factorial(int n) { + if (n < 2) + return 1; + return recursive_factorial(n>>1) ** 2 * swing(n); + } + + return recursive_factorial(n) << (n - popcount(n)); + } +} diff --git a/gram.y b/gram.y index 4f358f7..d99bfc5 100644 --- a/gram.y +++ b/gram.y @@ -1305,7 +1305,11 @@ simpleexpr : simpleexpr assignop simpleexpr %prec ASSIGN | BANG simpleexpr { $$ = NewExprTree(BANG, $2, (Expr *) 0); } | simpleexpr BANG %prec FACT - { $$ = NewExprTree(FACT, $1, (Expr *) 0); } + { + $$ = NewExprTree(FACT, + BuildName ("Math", "factorial"), + $1); + } | INC simpleexpr { $$ = NewExprTree(INC, $2, (Expr *) 0); } | simpleexpr INC diff --git a/math.5c b/math.5c index a6cd170..b25028e 100644 --- a/math.5c +++ b/math.5c @@ -648,8 +648,10 @@ extend namespace Math { a4 = a**4; iter = prec + 8; v = 0; + int niter = 0; while (iter-- > 0) { + niter++; term = ai/i! - aj/j!; v += term; if (exponent (v) > exponent (term) + iprec) @@ -659,6 +661,7 @@ extend namespace Math { i += 4; j += 4; } + printf ("cos: %d iters\n", niter); return imprecise (v + term); } diff --git a/nickle.h b/nickle.h index 610019d..25c3ade 100644 --- a/nickle.h +++ b/nickle.h @@ -940,6 +940,7 @@ Value do_xor (Value, Value); Value do_Math_pow (Value, Value); Value do_Math_assignpow (Value, Value); Value do_Math_popcount (Value); +Value do_Math_factorial (Value); Value do_File_putb (Value, Value); Value do_File_putc (Value, Value); Value do_File_ungetb (Value, Value); diff --git a/prime_sieve.5c b/prime_sieve.5c new file mode 100644 index 0000000..751455b --- /dev/null +++ b/prime_sieve.5c @@ -0,0 +1,90 @@ +/* + * Copyright ?? 2010 Keith Packard and Bart Massey. + * All Rights Reserved. See the file COPYING in this directory + * for licensing information. + */ + +public namespace PrimeSieve { + + int num_to_pos(int n) = (n - 3) // 2; + int pos_to_num(int p) = (p * 2) + 3; + + /* Generate a list of primes from a boolean array of composite + * test results + */ + int[] sieve_to_array(&bool[] composite, int n_prime) { + int[n_prime] primes; + int p = 0; + for (int i = 0; i < dim(composite); i++) + if (!composite[i]) + primes[p++] = pos_to_num(i); + return primes; + } + + /* Use the sieve of Eratosthenes to compute the set of + * primes <= max + */ + public int[] primes (int max) + { + int n = num_to_pos(max+1); + bool[n] composite = { false ... }; + int n_prime = 0; + + for (int p = 0; p < n; p++) { + if (!composite[p]) { + int prime = pos_to_num(p); + int step = prime; + int init = p + prime; + for (int v = init; v < n; v += step) + composite[v] = true; + n_prime++; + } + } + return sieve_to_array(&composite, n_prime); + } + + public typedef struct { + int start, end; + } range_t; + + /* Binary search in a list of numbers for the value <= 'v' */ + public int primes_search(&int[] primes, int v) { + int min = 0, max = dim(primes); + while (min < max) { + int mid = (max + min) >> 1; + int p = primes[mid]; + if (p == v) + return mid; + if (p > v) + max = mid; + else { + if (min == mid) + return mid; + min = mid; + } + } + return min; + } + + /* Return the indices within a list of primes such that + * primes[start] <= min && max < primes[end] + */ + public range_t primes_range(&int[] primes, int min, int max) { + int start = primes_search(&primes, min); + if (primes[start] < min) start++; + int end = primes_search(&primes, max) + 1; + return (range_t) { start = start, end = end }; + } + + /* + * Multiply all primes between min and max within the + * supplied list. + */ + public int primorial(&int[] primes, int min, int max) { + range_t r = primes_range(&primes, min, max); + int v = 1; + for (int i = r.start; i < r.end; i++) + v *= primes[i]; + return v; + } +} From keithp at keithp.com Mon Jul 5 21:35:34 2010 From: keithp at keithp.com (Keith Packard) Date: Tue, 06 Jul 2010 00:35:34 -0400 Subject: [Nickle] Fwd: nickle slow for large factorials In-Reply-To: References: Message-ID: On Sun, 4 Jul 2010 11:32:46 +0200, Michel Alexandre Salim wrote: > It looks like Nickle's handling of bignums is inefficient -- has there > been thoughts about using GMP for large numbers? The tail recursion > itself is fine, even for mutually recursive functions: I've implemented a more efficient factorial function as described by Peter Luschny as described here: http://www.luschny.de/math/factorial/FastFactorialFunctions.htm This still isn't amazingly fast for large factorials (666666 takes a bit more than a minute), but is a whole lot faster than the na?ve algorithm originally included in nickle, and should be faster than the GMP factorial algorithm for large values, although I haven't compared it myself. This code is on the master branch in the nickle repository; please feel free to give it a try. -- keith.packard at intel.com -------------- next part -------------- A non-text attachment was scrubbed... Name: not available Type: application/pgp-signature Size: 189 bytes Desc: not available URL: From keithp at keithp.com Mon Jul 5 22:22:19 2010 From: keithp at keithp.com (Keith Packard) Date: Mon, 5 Jul 2010 22:22:19 -0700 (PDT) Subject: [Nickle] nickle: Branch 'master' - 4 commits Message-ID: <20100706052219.C7EE0760254@keithp.com> math.5c | 3 --- pretty.c | 2 +- prime_sieve.5c | 2 +- test/Makefile.am | 3 ++- test/factorial.5c | 33 +++++++++++++++++++++++++++++++++ 5 files changed, 37 insertions(+), 6 deletions(-) New commits: commit 601affcbaf587816a6be4b6815efd2cc99cff66e Author: Keith Packard Date: Tue Jul 6 01:20:50 2010 -0400 Fix prime sieve function to include 'max' when 'max' is prime The sieve code would drop the max value from the returned list when it was prime. Signed-off-by: Keith Packard diff --git a/prime_sieve.5c b/prime_sieve.5c index 751455b..25aca84 100644 --- a/prime_sieve.5c +++ b/prime_sieve.5c @@ -26,7 +26,7 @@ public namespace PrimeSieve { */ public int[] primes (int max) { - int n = num_to_pos(max+1); + int n = num_to_pos(max) + 1; bool[n] composite = { false ... }; int n_prime = 0; commit d341e0220d181db50f7a6647433053293b3f45ec Author: Keith Packard Date: Tue Jul 6 01:20:11 2010 -0400 Fix factorial pretty-printing The expr tree built for factorial is different now, so the pretty print code needs to adapt. Signed-off-by: Keith Packard diff --git a/pretty.c b/pretty.c index a7632a0..cc3ae09 100644 --- a/pretty.c +++ b/pretty.c @@ -509,7 +509,7 @@ PrettyExpr (Value f, Expr *e, int parentPrec, int level, Bool nest) PrettyExpr (f, e->tree.right, selfPrec, level, nest); break; case FACT: - PrettyExpr (f, e->tree.left, selfPrec, level, nest); + PrettyExpr (f, e->tree.right, selfPrec, level, nest); FilePuts (f, "!"); break; case LNOT: commit 6d4a60c69eac89ff72004a00a8e9a70876db2325 Author: Keith Packard Date: Tue Jul 6 01:19:15 2010 -0400 Add factorial test This tests factorial accuracy up to 1000, which should catch most errors Signed-off-by: Keith Packard diff --git a/test/Makefile.am b/test/Makefile.am index 96e9f89..7ab6cb7 100644 --- a/test/Makefile.am +++ b/test/Makefile.am @@ -8,7 +8,8 @@ check_SCRIPTS=gcdtest.5c \ hashtest.5c \ signal.5c \ round.5c \ - math.5c + math.5c \ + factorial.5c noinst_PROGRAMS=math-tables diff --git a/test/factorial.5c b/test/factorial.5c new file mode 100644 index 0000000..b2589cc --- /dev/null +++ b/test/factorial.5c @@ -0,0 +1,33 @@ +/* + * Nickle test suite + * + * factorial tests + */ + +int errors = 0; + +int fact(int n) { + int r = 1; + while (n > 1) { + r *= n; + n--; + } + return r; +} + +void check_factorial(int max) { + for (int n = 0; n < max; n++) { + int is = n!; + int should = fact(n); + + if (is != should) { + printf ("check failed %d! (was %d should be %d)\n", + n, is, should); + ++errors; + } + } +} + +check_factorial(1000); + +exit (errors); commit 75187037e714eaadc671daba19a934608fd1069b Author: Keith Packard Date: Tue Jul 6 01:18:08 2010 -0400 Remove accidentally included cos debug printf This was accidentally added in the previous patch Signed-off-by: Keith Packard diff --git a/math.5c b/math.5c index b25028e..a6cd170 100644 --- a/math.5c +++ b/math.5c @@ -648,10 +648,8 @@ extend namespace Math { a4 = a**4; iter = prec + 8; v = 0; - int niter = 0; while (iter-- > 0) { - niter++; term = ai/i! - aj/j!; v += term; if (exponent (v) > exponent (term) + iprec) @@ -661,7 +659,6 @@ extend namespace Math { i += 4; j += 4; } - printf ("cos: %d iters\n", niter); return imprecise (v + term); } From keithp at keithp.com Mon Jul 5 22:30:26 2010 From: keithp at keithp.com (Keith Packard) Date: Mon, 5 Jul 2010 22:30:26 -0700 (PDT) Subject: [Nickle] nickle: Branch 'master' Message-ID: <20100706053026.922F3760254@keithp.com> debian/control | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) New commits: commit 40bde0fbd244462a282f922483ef5aa4994d590b Author: Keith Packard Date: Tue Jul 6 01:29:07 2010 -0400 Update debian bits to standards-version 3.8.4 Signed-off-by: Keith Packard diff --git a/debian/control b/debian/control index 9d8f7e5..e636f24 100644 --- a/debian/control +++ b/debian/control @@ -3,7 +3,7 @@ Section: interpreters Priority: optional Maintainer: Keith Packard Build-Depends: debhelper (>= 7), libreadline-dev -Standards-Version: 3.8.3 +Standards-Version: 3.8.4 Package: nickle Architecture: any From michael.silvanus at gmail.com Sun Jul 4 02:17:18 2010 From: michael.silvanus at gmail.com (Michel Alexandre Salim) Date: Sun, 4 Jul 2010 11:17:18 +0200 Subject: [Nickle] nickle slow for large factorials Message-ID: This occurs on both Fedora 12 and 13, x86_64: https://bugzilla.redhat.com/show_bug.cgi?id=560750 - 666666! takes very long to compute and hundreds of MB of RAM - implementing fac as a tail-recursive function has the same result: $ nickle > int fack (int n, int a) { + if (n==0) return a; + return fack(n-1, a*n); + } > fack (5, 1) 120 > fack (666666, 1) // kill after about 20 seconds ^CUnhandled exception signal (2) :3: return fack (n - 1, a * n); fack (478575, ^C^C) :6: fack (666666, 1); It looks like Nickle's handling of bignums is inefficient -- has there been thoughts about using GMP for large numbers? The tail recursion itself is fine, even for mutually recursive functions: > bool evenp (int n) { + if (n==0) return true; + return oddp (n-1); + } -> return oddp (n - 1); :13: No visible symbol "oddp" in scope > bool oddp (int n); > bool evenp (int n) { + if (n==0) return true; + return oddp (n-1); + } > bool oddp (int n) { + if (n==0) return false; + return evenp (n-1); + } > evenp(10) true > evenp(11) false > evenp(666666) true Thanks, -- Michel Alexandre Salim Fedora Project Contributor: http://fedoraproject.org/ Email: salimma at fedoraproject.org | GPG key ID: 78884778 Jabber: hircus at jabber.ccc.de | IRC: hircus at irc.freenode.net () ascii ribbon campaign - against html e-mail /\ www.asciiribbon.org - against proprietary attachments From michael.silvanus at gmail.com Mon Jul 5 01:01:21 2010 From: michael.silvanus at gmail.com (Michel Alexandre Salim) Date: Mon, 5 Jul 2010 10:01:21 +0200 Subject: [Nickle] Fwd: nickle slow for large factorials In-Reply-To: References: Message-ID: On Mon, Jul 5, 2010 at 6:23 AM, Keith Packard wrote: > On Mon, 5 Jul 2010 02:48:37 +0200, Michel Alexandre Salim wrote: > >> Ah, thanks. Any reason why the memory consumption is so high even the >> tail-recursive implementation? Memory usage should be not much worse >> than whatever it takes to represent 666666! in memory. > > You can't do trivial tail recursion in the factorial function -- you > have to perform additional computation after each recursive function: > The killer here is the n* -- without that, you have a simple tail > recursive function. Refactor this into a pure tail call: > > ? ? int fact2(n,m) { > ? ? ? ? if (n <= 1) > ? ? ? ? ? ?return m; > ? ? ? ? return fact2(n-1,n*m); > ? ? } > ? ? int fact(n) { return fact2(n,1); } > > and now you get the tail call behaviour. > I forgot to mention that this is in fact what I implemented, and htop still reports memory consumption in the hundreds of megabytes, and ! does so too. I wonder if nickle's numerical system is leaking memory? Thanks, -- Michel From keithp at keithp.com Wed Jul 7 12:15:53 2010 From: keithp at keithp.com (Keith Packard) Date: Wed, 7 Jul 2010 12:15:53 -0700 (PDT) Subject: [Nickle] nickle: Branch 'master' - 2 commits Message-ID: <20100707191553.D6B86760254@keithp.com> configure.in | 2 +- debian/changelog | 13 ++++++++++++- test/factorial.5c | 28 ++++++++++++++++++++++++++++ 3 files changed, 41 insertions(+), 2 deletions(-) New commits: commit 1491af33c3bca94c6bb604b483a5eabcf038eef1 Author: Keith Packard Date: Wed Jul 7 15:12:21 2010 -0400 Bump to version 2.70 Signed-off-by: Keith Packard diff --git a/configure.in b/configure.in index 81fd8a6..65063b4 100644 --- a/configure.in +++ b/configure.in @@ -7,7 +7,7 @@ dnl for licensing information. AC_PREREQ(2.59) AC_INIT([nickle], - 2.69, + 2.70, [http://nickle.org], nickle) diff --git a/debian/changelog b/debian/changelog index 6d0e977..3914abb 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,6 +1,17 @@ +nickle (2.70-1) unstable; urgency=low + + * Make parse_csv_t type public + * Throw 'bad_csv_parse' exception on unclosed quotes + * Add factorial tests + * Repliace na??ve factorial algorithm with the prime swing + algorithm defined by Peter Luschny + * Update to standard 3.8.4 + + -- Keith Packard Tue, 06 Jul 2010 01:22:30 -0400 + nickle (2.69-1) unstable; urgency=low - * Make debian build epend on libreadline-dev not libreadline5-dev. + * Make debian build depend on libreadline-dev not libreadline5-dev. * Get math-tables.5c built before tests are run * Fix trig boundary conditions. * Add tests for math functions. commit 7334afef7a4235447e11a948a9d57c354dafac67 Author: Keith Packard Date: Tue Jul 6 11:02:33 2010 -0400 Test factorial function by comparing with Stirling approximation This checks larger factorial values for gross errors. Signed-off-by: Keith Packard diff --git a/test/factorial.5c b/test/factorial.5c index b2589cc..3581ad1 100644 --- a/test/factorial.5c +++ b/test/factorial.5c @@ -28,6 +28,34 @@ void check_factorial(int max) { } } +real stirling (real n) +{ + n = imprecise (n); + return sqrt (2 * pi * n) * (n / Math::e) ** n; +} + +void check_one_stirling(int v) { + real s = stirling(v); + real f = v!; + real r = f/s; + real e = 0.1/v; + if (r < 1 || r > (1 + e)) { + printf("check failed %d! (was %d should be close to %g)\n", + v, f, s); + ++errors; + } +} + +void check_stirling(int rep) { + real v = 13; + while (rep-- > 0) { + int iv = floor(v); + check_one_stirling(iv); + v = v * 3 + 2; + } +} + +check_stirling(10); check_factorial(1000); exit (errors); From keithp at keithp.com Wed Jul 7 12:15:54 2010 From: keithp at keithp.com (Keith Packard) Date: Wed, 7 Jul 2010 12:15:54 -0700 (PDT) Subject: [Nickle] nickle: Changes to 'refs/tags/2.70' Message-ID: <20100707191554.05D7A7603F2@keithp.com> Tag '2.70' created by Keith Packard at 2010-07-07 20:15 -0700 Version 2.70 -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.10 (GNU/Linux) iD8DBQBMNNJJQp8BWwlsTdMRAlIoAKCn8VwyigckxZqxCw9a8LHmC2GPFQCfYzJM 85muwA0ndvj0totHZNNjGAs= =ST6C -----END PGP SIGNATURE----- Changes since 2.69-10: --- 0 files changed ---