fix for expt bug

2010-10-31 Thread Ramakrishnan Muthukrishnan
Hi,

As reported here:



expt currently wrongly prints the results for any negative base
numbers. The attached patch (also attached with the bug tracker) has a
fix and also adds a test case.

This is my first patch to guile, so please correct me if I have done
something wrong. I will be happy to rework it. I am yet to recieve the
assignment papers from the FSF (but they have been despatched already
by the FSF), I will mail them back as soon as I get it.

thanks
-- 
  Ramakrishnan
From c23939a1c2b7bfe1b3cf20abb6a7b431699281a1 Mon Sep 17 00:00:00 2001
From: Ramakrishnan Muthukrishnan 
Date: Sun, 31 Oct 2010 23:22:52 +0530
Subject: [PATCH] Fix for bug #31464. expt needs to treat negative bases specially.
 Also adding test-suite cases for expt.

* libguile/numbers.c: if base is negative, find the absolute value
  of the base, find log and then later reapply the negative sign.
  The bug was caused by the fact that log of a negative number is
  undefined.

* test-suite/tests/numbers.test: Two new test cases for expt. For
  cases where the base is negative and the power to be raised is
  not an integer, the result should be a complex number.
---
 libguile/numbers.c|   11 +++
 test-suite/tests/numbers.test |7 ++-
 2 files changed, 17 insertions(+), 1 deletions(-)

diff --git a/libguile/numbers.c b/libguile/numbers.c
index fbc6cc8..07ae95d 100644
--- a/libguile/numbers.c
+++ b/libguile/numbers.c
@@ -5451,6 +5451,17 @@ SCM_DEFINE (scm_expt, "expt", 2, 0, 0,
 {
   return scm_from_double (pow (scm_to_double (x), scm_to_double (y)));
 }
+  else if (scm_is_real (x) &&
+   scm_is_real (y) &&
+   (scm_to_double (x) < 0) &&
+   !SCM_FRACTIONP (y))
+{
+  SCM x_abs;
+
+  x_abs = scm_abs (x);
+  return scm_product(scm_from_double (-1.0),
+ scm_exp (scm_product (scm_log (x_abs), y)));
+}
   else
 return scm_exp (scm_product (scm_log (x), y));
 }
diff --git a/test-suite/tests/numbers.test b/test-suite/tests/numbers.test
index 3c3e14f..3d53bbe 100644
--- a/test-suite/tests/numbers.test
+++ b/test-suite/tests/numbers.test
@@ -2892,7 +2892,12 @@
   (pass-if "(= 1 (expt 0 0))" (= 1 (expt 0 0)))
   (pass-if "(= 1 (expt 0 0.0))" (= 1 (expt 0 0.0)))
   (pass-if "(= 1 (expt 0.0 0))" (= 1 (expt 0.0 0)))
-  (pass-if "(= 1 (expt 0.0 0.0))" (= 1 (expt 0.0 0.0
+  (pass-if "(= 1 (expt 0.0 0.0))" (= 1 (expt 0.0 0.0)))
+  ;; tests for non zero values of base and exponent.
+  (pass-if "(eqv-loosely? -2742638075.5 (expt -2742638075.5 1)"
+   (eqv-loosely? -2742638075.5 (expt -2742638075.5 1)))
+  (pass-if "(eqv-loosely? 1.0002+1.7320508075688772i (expt -8 1/3)"
+   (eqv-loosely? 1.0002+1.7320508075688772i (expt -8 1/3
 
 ;;;
 ;;; asinh
-- 
1.7.2.3



Re: fix for expt bug

2010-10-31 Thread Mark H Weaver
Ramakrishnan,

Your fix is incorrect.  You have assumed that (-a)^b = -(a^b),
but this is true only if b is an odd integer.  A correct relation
is (-a)^b = (-1)^b * a^b.

As reported by Ludovic:

scheme@(guile-user)> (expt -2742638075.5 2)
$8 = 7.52206361318235e18-1842.31337891184i
scheme@(guile-user)> (* -2742638075.5 -2742638075.5)
$9 = 7.52206361318235e18

The reported bug is simply due to roundoff error.  You must know
something about complex numbers and specifically complex exponentials to
understand what's happening here.  The spurious imaginary part is
actually quite miniscule compared with the real part.  If one looks at
these results in polar form, the complex argument (angle) should ideally
be an exact zero, but is instead an inexact number very close to 0
(about 2.45e-16 radians in this case).

The most straightforward solution to this bug is to support a few
special cases, such as:

  (-a)^b = -(a^b)   (where a is positive real and b is an odd integer)
  (-a)^b =   a^b(where a is positive real and b is an even integer)

A more elaborate solution would involve supporting a polar
representation of complex numbers where the angle can be an exact
rational times pi, but this is almost certainly not worth it.

Best,
 Mark


Ramakrishnan Muthukrishnan  wrote:
> 
>
> expt currently wrongly prints the results for any negative base
> numbers. The attached patch (also attached with the bug tracker) has a
> fix and also adds a test case.
>
> This is my first patch to guile, so please correct me if I have done
> something wrong. I will be happy to rework it. I am yet to recieve the
> assignment papers from the FSF (but they have been despatched already
> by the FSF), I will mail them back as soon as I get it.
>
> thanks
> -- 
>   Ramakrishnan
>
> From c23939a1c2b7bfe1b3cf20abb6a7b431699281a1 Mon Sep 17 00:00:00 2001
> From: Ramakrishnan Muthukrishnan 
> Date: Sun, 31 Oct 2010 23:22:52 +0530
> Subject: [PATCH] Fix for bug #31464. expt needs to treat negative bases 
> specially.
>  Also adding test-suite cases for expt.
>
> * libguile/numbers.c: if base is negative, find the absolute value
>   of the base, find log and then later reapply the negative sign.
>   The bug was caused by the fact that log of a negative number is
>   undefined.
>
> * test-suite/tests/numbers.test: Two new test cases for expt. For
>   cases where the base is negative and the power to be raised is
>   not an integer, the result should be a complex number.
> ---
>  libguile/numbers.c|   11 +++
>  test-suite/tests/numbers.test |7 ++-
>  2 files changed, 17 insertions(+), 1 deletions(-)
>
> diff --git a/libguile/numbers.c b/libguile/numbers.c
> index fbc6cc8..07ae95d 100644
> --- a/libguile/numbers.c
> +++ b/libguile/numbers.c
> @@ -5451,6 +5451,17 @@ SCM_DEFINE (scm_expt, "expt", 2, 0, 0,
>  {
>return scm_from_double (pow (scm_to_double (x), scm_to_double (y)));
>  }
> +  else if (scm_is_real (x) &&
> +   scm_is_real (y) &&
> +   (scm_to_double (x) < 0) &&
> +   !SCM_FRACTIONP (y))
> +{
> +  SCM x_abs;
> +
> +  x_abs = scm_abs (x);
> +  return scm_product(scm_from_double (-1.0),
> + scm_exp (scm_product (scm_log (x_abs), y)));
> +}
>else
>  return scm_exp (scm_product (scm_log (x), y));
>  }
> diff --git a/test-suite/tests/numbers.test b/test-suite/tests/numbers.test
> index 3c3e14f..3d53bbe 100644
> --- a/test-suite/tests/numbers.test
> +++ b/test-suite/tests/numbers.test
> @@ -2892,7 +2892,12 @@
>(pass-if "(= 1 (expt 0 0))" (= 1 (expt 0 0)))
>(pass-if "(= 1 (expt 0 0.0))" (= 1 (expt 0 0.0)))
>(pass-if "(= 1 (expt 0.0 0))" (= 1 (expt 0.0 0)))
> -  (pass-if "(= 1 (expt 0.0 0.0))" (= 1 (expt 0.0 0.0
> +  (pass-if "(= 1 (expt 0.0 0.0))" (= 1 (expt 0.0 0.0)))
> +  ;; tests for non zero values of base and exponent.
> +  (pass-if "(eqv-loosely? -2742638075.5 (expt -2742638075.5 1)"
> +   (eqv-loosely? -2742638075.5 (expt -2742638075.5 1)))
> +  (pass-if "(eqv-loosely? 1.0002+1.7320508075688772i (expt -8 
> 1/3)"
> +   (eqv-loosely? 1.0002+1.7320508075688772i (expt -8 
> 1/3
>  
>  ;;;
>  ;;; asinh



[PATCH] Allow user-defined meta-commands

2010-10-31 Thread Andreas Rottmann

Besides allowing user-defined meta-commands, this change also refactors
the meta-command machinery to split reading a command's arguments from
the procedure actually implementing it, and hence allows nesting
meta-commands.  As an example of such a command, ",in" is added as a new
meta-command.

* module/system/repl/command.scm: Export `define-meta-command'.
  (*command-module*): Replaced by the hash table `*command-infos*'.
  (command-info, make-command-info, command-info-procedure)
  (command-info-arguments-reader): New procedures, encapsulating the
  information about a meta-command.
  (command-procedure): Adapted to use the `command-info' lookup
  procedure.
  (read-command-arguments): New auxiliary procedure invoking a command's
  argument reader procedure.
  (meta-command): Adapted to the split of reading arguments and
  executing a command.
  (add-meta-command!): New auxiliary procedure, registers a meta
  command's procedure and argument reader into `*command-infos* and
  `*command-table*.
  (define-meta-command): Extended to allow specification of the command's
  category; split the argument reader and actual command procedure.
  (guile:apropos, guile:load, guile:compile-file, guile:gc): Remove these
  aliases, they are unnecessary as we now use a hash table instead of the
  module to store the commands.
  (in): New meta-command, which evaluates an expression, or alternatively
  executes another meta-command, in the context of a specific module.
* doc/ref/scheme-using.texi (Module Commands): Document the `in'
  meta-command.

From: Andreas Rottmann 
Subject: Allow user-defined meta-commands

Besides allowing user-defined meta-commands, this change also refactors
the meta-command machinery to split reading a command's arguments from
the procedure actually implementing it, and hence allows nesting
meta-commands.  As an example of such a command, ",in" is added as a new
meta-command.

* module/system/repl/command.scm: Export `define-meta-command'.
  (*command-module*): Replaced by the hash table `*command-infos*'.
  (command-info, make-command-info, command-info-procedure)
  (command-info-arguments-reader): New procedures, encapsulating the
  information about a meta-command.
  (command-procedure): Adapted to use the `command-info' lookup
  procedure.
  (read-command-arguments): New auxiliary procedure invoking a command's
  argument reader procedure.
  (meta-command): Adapted to the split of reading arguments and
  executing a command.
  (add-meta-command!): New auxiliary procedure, registers a meta
  command's procedure and argument reader into `*command-infos* and
  `*command-table*.
  (define-meta-command): Extended to allow specification of the command's
  category; split the argument reader and actual command procedure.
  (guile:apropos, guile:load, guile:compile-file, guile:gc): Remove these
  aliases, they are unnecessary as we now use a hash table instead of the
  module to store the commands.
  (in): New meta-command, which evaluates an expression, or alternatively
  executes another meta-command, in the context of a specific module.
* doc/ref/scheme-using.texi (Module Commands): Document the `in'
  meta-command.

---
 doc/ref/scheme-using.texi  |7 ++
 module/system/repl/command.scm |  135 +++
 2 files changed, 100 insertions(+), 42 deletions(-)

diff --git a/doc/ref/scheme-using.texi b/doc/ref/scheme-using.texi
index 223295c..7700cbe 100644
--- a/doc/ref/scheme-using.texi
+++ b/doc/ref/scheme-using.texi
@@ -227,6 +227,13 @@ Load a file in the current module.
 List current bindings.
 @end deffn
 
+...@deffn {REPL Command} in module expression
+...@deffnx {REPL Command} in module command [args ...]
+Evaluate an expression, or alternatively, execute another meta-command
+in the context of a module.  For example, @samp{,in (foo bar) ,binding}
+will show the bindings in the module @code{(foo bar)}.
+...@end deffn
+
 @node Language Commands
 @subsubsection Language Commands
 
diff --git a/module/system/repl/command.scm b/module/system/repl/command.scm
index 4fc2038..9933b0d 100644
--- a/module/system/repl/command.scm
+++ b/module/system/repl/command.scm
@@ -41,7 +41,7 @@
   #:use-module ((ice-9 pretty-print) #:select ((pretty-print . pp)))
   #:use-module ((system vm inspect) #:select ((inspect . %inspect)))
   #:use-module (statprof)
-  #:export (meta-command))
+  #:export (meta-command define-meta-command))
 
 
 ;;;
@@ -50,7 +50,7 @@
 
 (define *command-table*
   '((help (help h) (show) (apropos a) (describe d))
-(module   (module m) (import use) (load l) (binding b))
+(module   (module m) (import use) (load l) (binding b) (in))
 (language (language L))
 (compile  (compile c) (compile-file cc)
 	  (disassemble x) (disassemble-file xx))
@@ -74,12 +74,22 @@
 (define (group-name g) (car g))
 (define (group-commands g) (cdr g))
 
-(define *command-module* (current-module))
+(define *command-infos* (make-hash-table))
 (define (com

Re: fix for expt bug

2010-10-31 Thread Ramakrishnan Muthukrishnan
On Mon, Nov 1, 2010 at 5:33 AM, Mark H Weaver  wrote:
> Ramakrishnan,
>
> Your fix is incorrect.  You have assumed that (-a)^b = -(a^b),

Mark,

Yes, you are right. Not sure what I was thinking when I made the patch. :-(

> The reported bug is simply due to roundoff error.  You must know
> something about complex numbers and specifically complex exponentials to
> understand what's happening here.  The spurious imaginary part is
> actually quite miniscule compared with the real part.  If one looks at
> these results in polar form, the complex argument (angle) should ideally
> be an exact zero, but is instead an inexact number very close to 0
> (about 2.45e-16 radians in this case).
>
> The most straightforward solution to this bug is to support a few
> special cases, such as:
>
>  (-a)^b = -(a^b)   (where a is positive real and b is an odd integer)
>  (-a)^b =   a^b    (where a is positive real and b is an even integer)

Thanks. I will take a dig at doing this solution.

-- 
  Ramakrishnan



Re: [PATCH] Allow user-defined meta-commands

2010-10-31 Thread Jose A. Ortega Ruiz
On Mon, Nov 01 2010, Andreas Rottmann wrote:

> Besides allowing user-defined meta-commands, this change also refactors
> the meta-command machinery to split reading a command's arguments from
> the procedure actually implementing it, and hence allows nesting
> meta-commands.  As an example of such a command, ",in" is added as a new
> meta-command.

As another example of where this patch is useful, i've got a branch of
geiser that uses new meta-commands to implement the interaction between
emacs and guile. Besides making the code cleaner and the interaction
much more robust, it has allowed us to support r6rs libraries. So here's
hope that this patch will be accepted :)

jao