Hi=2C
after reading Tobias' comments=2C I wondered if th=
e Ideas webpage is actually up to date or being updated (which might not be=
part of the high priority things to do).
I have been using guile=
(on and off) &=3B enjoying some of it=2C and I'd be willing to help a b=
it (if needed).
thanks!
Alex =3B
=
_a15a756c84ff47d38bca85ce0bd48ecf_
From MAILERDAEMON Fri Oct 07 01:25:56 2011
Received: from list by lists.gnu.org with archive (Exim 4.71)
id 1RC2wV00084GU8
for mharcguiledevel@gnu.org; Fri, 07 Oct 2011 01:25:55 0400
Received: from eggs.gnu.org ([140.186.70.92]:57634)
by lists.gnu.org with esmtp (Exim 4.71)
(envelopefrom
) id 1RC2wP00083PCd
for guiledevel@gnu.org; Fri, 07 Oct 2011 01:25:53 0400
Received: from Debianexim by eggs.gnu.org with spamscanned (Exim 4.71)
(envelopefrom ) id 1RC2wK0001ae5v
for guiledevel@gnu.org; Fri, 07 Oct 2011 01:25:49 0400
Received: from world.peace.net ([96.39.62.75]:40646)
by eggs.gnu.org with esmtp (Exim 4.71)
(envelopefrom ) id 1RC2wJ0001aMM3
for guiledevel@gnu.org; Fri, 07 Oct 2011 01:25:44 0400
Received: from 20965518.c30.smrubr1.sbosmr.ma.cable.rcn.com
([209.6.55.18] helo=yeeloong.netris.org)
by world.peace.net with esmtpa (Exim 4.69)
(envelopefrom )
id 1RC2vv0002MM47; Fri, 07 Oct 2011 01:25:19 0400
Received: from mhw by yeeloong.netris.org with local (Exim 4.72)
(envelopefrom )
id 1RC2ve0005C7PS; Fri, 07 Oct 2011 01:25:02 0400
From: Mark H Weaver
To: guiledevel@gnu.org
Subject: [PATCH] Improvements to exact rationals et al
Date: Fri, 07 Oct 2011 01:25:02 0400
MessageID: <8739f5tlu9.fsf@yeeloong.netris.org>
MIMEVersion: 1.0
ContentType: multipart/mixed; boundary="==="
Xdetectedoperatingsystem: by eggs.gnu.org: GNU/Linux 2.6 (newer, 3)
XReceivedFrom: 96.39.62.75
XBeenThere: guiledevel@gnu.org
XMailmanVersion: 2.1.14
Precedence: list
ListId: "Developers list for Guile,
the GNU extensibility library"
ListUnsubscribe: ,
ListArchive:
ListPost:
ListHelp:
ListSubscribe: ,
XListReceivedDate: Fri, 07 Oct 2011 05:25:53 0000
===
Hello all,
After a long hiatus, and newly inspired by both peval and the videos
from GHM 2011 (especially Andy's excellent talk on the importance of
extensibility) I'd like to try to find more time to hack on Guile.
However, before embarking on more interesting work, I'd like to submit
some numerics patches that have been lingering in my personal repository
for far too long.
This patch set makes some cleanups and improvements to the numerics
code, especially to the handling of exact rationals. Here are some
examples of the visible improvements:
Before:
(exact>inexact (/ 1000001 (expt 10 310))) ==> 0.0
(exact>inexact (/ (expt 10 310) 1000001)) ==> +inf.0
After:
(exact>inexact (/ 1000001 (expt 10 310))) ==> 1.000001e304
(exact>inexact (/ (expt 10 310) 1000001)) ==> 9.99999000001e303
Before: (on the Yeeloong)
scheme@(guileuser)> ,time (define r (expt 11/13 100000))
;; 3.506000s real time, 3.145000s run time. 0.000000s spent in GC.
scheme@(guileuser)> ,time (define r (expt 11/13 100000))
;; 3.250000s real time, 3.140000s run time. 0.000000s spent in GC.
scheme@(guileuser)> ,time (define r (expt 11/13 100000))
;; 3.242000s real time, 3.141000s run time. 0.000000s spent in GC.
After:
scheme@(guileuser)> ,time (define r (expt 11/13 100000))
;; 0.305000s real time, 0.273000s run time. 0.000000s spent in GC.
scheme@(guileuser)> ,time (define r (expt 11/13 100000))
;; 0.202000s real time, 0.187000s run time. 0.000000s spent in GC.
scheme@(guileuser)> ,time (define r (expt 11/13 100000))
;; 0.208000s real time, 0.190000s run time. 0.000000s spent in GC.
Also, this patch set adds the uservisible procedure `roundash' which I
proposed several months ago, because its functionality was needed
internally to implement proper rounding in exact>inexact for bignums.
While it doesn't strictly need to be made public, it will certainly be
needed to implement many kinds of inexact GOOPS numbers efficiently such
as fixedpoint and arbitraryprecision floats, and I suspect it has
wider utility as well.
I'd like to apply these patches to stable2.0. Comments and suggestions
are welcome.
Mark
===
ContentType: text/xdiff
ContentDisposition: inline;
filename=0001Improvecodeinscm_gcdforinuminumcase.patch
ContentDescription: Improve code in scm_gcd for inum/inum case
>From 80f12d13984dc01ff74620e46c46dda9e3dea226 Mon Sep 17 00:00:00 2001
From: Mark H Weaver
Date: Tue, 1 Mar 2011 20:12:51 0500
Subject: [PATCH 1/7] Improve code in scm_gcd for inum/inum case
* libguile/numbers.c (scm_gcd): Improve implementation of inum/inum case
in scm_gcd to be more clear and efficient.

libguile/numbers.c  54 ++++++++++++++++++++++++++++
1 files changed, 30 insertions(+), 24 deletions()
diff git a/libguile/numbers.c b/libguile/numbers.c
index b01af9f..aa768b4 100644
 a/libguile/numbers.c
+++ b/libguile/numbers.c
@@ 3853,52 +3853,58 @@ SCM_PRIMITIVE_GENERIC (scm_i_gcd, "gcd", 0, 2, 1,
SCM
scm_gcd (SCM x, SCM y)
{
 if (SCM_UNBNDP (y))
+ if (SCM_UNLIKELY (SCM_UNBNDP (y)))
return SCM_UNBNDP (x) ? SCM_INUM0 : scm_abs (x);
 if (SCM_I_INUMP (x))
+ if (SCM_LIKELY (SCM_I_INUMP (x)))
{
 if (SCM_I_INUMP (y))
+ if (SCM_LIKELY (SCM_I_INUMP (y)))
{
scm_t_inum xx = SCM_I_INUM (x);
scm_t_inum yy = SCM_I_INUM (y);
scm_t_inum u = xx < 0 ? xx : xx;
scm_t_inum v = yy < 0 ? yy : yy;
scm_t_inum result;
 if (xx == 0)
+ if (SCM_UNLIKELY (xx == 0))
result = v;
 else if (yy == 0)
+ else if (SCM_UNLIKELY (yy == 0))
result = u;
else
{
 scm_t_inum k = 1;
 scm_t_inum t;
+ int k = 0;
/* Determine a common factor 2^k */
 while (!(1 & (u  v)))
+ while (((u  v) & 1) == 0)
{
 k <<= 1;
+ k++;
u >>= 1;
v >>= 1;
}
/* Now, any factor 2^n can be eliminated */
 if (u & 1)
 t = v;
+ if ((u & 1) == 0)
+ while ((u & 1) == 0)
+ u >>= 1;
else
+ while ((v & 1) == 0)
+ v >>= 1;
+ /* Both u and v are now odd. Subtract the smaller one
+ from the larger one to produce an even number, remove
+ more factors of two, and repeat. */
+ while (u != v)
{
 t = u;
 b3:
 t = SCM_SRS (t, 1);
+ if (u > v)
+ {
+ u = v;
+ while ((u & 1) == 0)
+ u >>= 1;
+ }
+ else
+ {
+ v = u;
+ while ((v & 1) == 0)
+ v >>= 1;
+ }
}
 if (!(1 & t))
 goto b3;
 if (t > 0)
 u = t;
 else
 v = t;
 t = u  v;
 if (t != 0)
 goto b3;
 result = u * k;
+ result = u << k;
}
return (SCM_POSFIXABLE (result)
? SCM_I_MAKINUM (result)

1.7.2.5
===
ContentType: text/xdiff
ContentDisposition: inline;
filename=0002Optimizeandsimplifyfractionscode.patch
ContentDescription: Optimize and simplify fractions code
>From 807de5ec6dab40fc699f7e3353de36ae1ee36604 Mon Sep 17 00:00:00 2001
From: Mark H Weaver
Date: Tue, 1 Mar 2011 16:03:59 0500
Subject: [PATCH 2/7] Optimize and simplify fractions code
* libguile/numbers.c (scm_exact_integer_quotient): New internal static
function that computes the quotient of two exact integers when the
remainder is known in advance to be zero. For large integers this can
be implemented more efficiently than when the remainder is unknown.
(scm_i_make_ratio_already_reduced): New internal static function that
creates a ratio when the numerator and denominator are already known
to be reduced to lowest terms (i.e. when their gcd is 1). This can be
used in several places to avoid unnecessary gcd computations.
(scm_i_make_ratio): Rewrite in terms of
scm_i_make_ratio_already_reduced. Don't bother checking to see if the
denominator divides the numerator evenly. This is wasted effort in
the common case. Instead, compute the gcd, reduce to lowest terms
(using scm_exact_integer_quotient), and let
scm_i_make_ratio_already_reduced do the integer check (by checking for
a unit denominator).
(scm_integer_expt): Optimize fraction case by (a/b)^n ==> (a^n)/(b^n),
to avoid needless effort to reduce intermediate products to lowest
terms. If a and b have no common factors, it follows that a^n and b^n
don't have common factors. Use scm_i_make_ratio_already_reduced to
construct the final result, so that no gcd computations are needed to
exponentiate a fraction.
(scm_abs, scm_magnitude, scm_difference): Use
scm_i_make_ratio_already_reduced to avoid wasteful gcd computations
when negating fractions.
(do_divide): Use scm_i_make_ratio_already_reduced to avoid wasteful
gcd computations when taking the reciprocal of a fraction or integer.
When dividing exact integers, don't bother checking to see if the
denominator divides the numerator evenly. Instead, let
scm_i_make_ratio do the job.
* testsuite/tests/numbers.test (expt, integerexpt): Add tests.

libguile/numbers.c  287 ++++++++++++++++++++++
testsuite/tests/numbers.test  6 +
2 files changed, 161 insertions(+), 132 deletions()
diff git a/libguile/numbers.c b/libguile/numbers.c
index aa768b4..80b46df 100644
 a/libguile/numbers.c
+++ b/libguile/numbers.c
@@ 413,96 +413,58 @@ scm_i_mpz2num (mpz_t b)
/* this is needed when we want scm_divide to make a float, not a ratio, even if passed two ints */
static SCM scm_divide2real (SCM x, SCM y);
+/* scm_i_make_ratio_already_reduced makes a ratio more efficiently,
+ when the following conditions are known in advance:
+
+ 1. numerator and denominator are exact integers
+ 2. numerator and denominator are reduced to lowest terms: gcd(n,d) == 1
+*/
static SCM
scm_i_make_ratio (SCM numerator, SCM denominator)
#define FUNC_NAME "makeratio"
+scm_i_make_ratio_already_reduced (SCM numerator, SCM denominator)
{
 /* First make sure the arguments are proper.
 */
 if (SCM_I_INUMP (denominator))
+ /* Flip signs so that the denominator is positive. */
+ if (scm_is_false (scm_positive_p (denominator)))
{
 if (scm_is_eq (denominator, SCM_INUM0))
+ if (SCM_UNLIKELY (scm_is_eq (denominator, SCM_INUM0)))
scm_num_overflow ("makeratio");
 if (scm_is_eq (denominator, SCM_INUM1))
 return numerator;
 }
 else
 {
 if (!(SCM_BIGP(denominator)))
 SCM_WRONG_TYPE_ARG (2, denominator);
 }
 if (!SCM_I_INUMP (numerator) && !SCM_BIGP (numerator))
 SCM_WRONG_TYPE_ARG (1, numerator);

 /* Then flip signs so that the denominator is positive.
 */
 if (scm_is_true (scm_negative_p (denominator)))
 {
 numerator = scm_difference (numerator, SCM_UNDEFINED);
 denominator = scm_difference (denominator, SCM_UNDEFINED);
 }

 /* Now consider for each of the four fixnum/bignum combinations
 whether the rational number is really an integer.
 */
 if (SCM_I_INUMP (numerator))
 {
 scm_t_inum x = SCM_I_INUM (numerator);
 if (scm_is_eq (numerator, SCM_INUM0))
 return SCM_INUM0;
 if (SCM_I_INUMP (denominator))
+ else
{
 scm_t_inum y;
 y = SCM_I_INUM (denominator);
 if (x == y)
 return SCM_INUM1;
 if ((x % y) == 0)
 return SCM_I_MAKINUM (x / y);
+ numerator = scm_difference (numerator, SCM_UNDEFINED);
+ denominator = scm_difference (denominator, SCM_UNDEFINED);
}
 else
 {
 /* When x == SCM_MOST_NEGATIVE_FIXNUM we could have the negative
 of that value for the denominator, as a bignum. Apart from
 that case, abs(bignum) > abs(inum) so inum/bignum is not an
 integer. */
 if (x == SCM_MOST_NEGATIVE_FIXNUM
 && mpz_cmp_ui (SCM_I_BIG_MPZ (denominator),
  SCM_MOST_NEGATIVE_FIXNUM) == 0)
 return SCM_I_MAKINUM(1);
 }
}
 else if (SCM_BIGP (numerator))
+
+ /* Check for the integer case */
+ if (scm_is_eq (denominator, SCM_INUM1))
+ return numerator;
+
+ return scm_double_cell (scm_tc16_fraction,
+ SCM_UNPACK (numerator),
+ SCM_UNPACK (denominator), 0);
+}
+
+static SCM scm_exact_integer_quotient (SCM x, SCM y);
+
+static SCM
+scm_i_make_ratio (SCM numerator, SCM denominator)
+#define FUNC_NAME "makeratio"
+{
+ /* Make sure the arguments are proper */
+ if (!SCM_LIKELY (SCM_I_INUMP (numerator)  SCM_BIGP (numerator)))
+ SCM_WRONG_TYPE_ARG (1, numerator);
+ else if (!SCM_LIKELY (SCM_I_INUMP (denominator)  SCM_BIGP (denominator)))
+ SCM_WRONG_TYPE_ARG (2, denominator);
+ else
{
 if (SCM_I_INUMP (denominator))
+ SCM the_gcd = scm_gcd (numerator, denominator);
+ if (!(scm_is_eq (the_gcd, SCM_INUM1)))
{
 scm_t_inum yy = SCM_I_INUM (denominator);
 if (mpz_divisible_ui_p (SCM_I_BIG_MPZ (numerator), yy))
 return scm_divide (numerator, denominator);
 }
 else
 {
 if (scm_is_eq (numerator, denominator))
 return SCM_INUM1;
 if (mpz_divisible_p (SCM_I_BIG_MPZ (numerator),
 SCM_I_BIG_MPZ (denominator)))
 return scm_divide(numerator, denominator);
+ /* Reduce to lowest terms */
+ numerator = scm_exact_integer_quotient (numerator, the_gcd);
+ denominator = scm_exact_integer_quotient (denominator, the_gcd);
}
+ return scm_i_make_ratio_already_reduced (numerator, denominator);
}

 /* No, it's a proper fraction.
 */
 {
 SCM divisor = scm_gcd (numerator, denominator);
 if (!(scm_is_eq (divisor, SCM_INUM1)))
 {
 numerator = scm_divide (numerator, divisor);
 denominator = scm_divide (denominator, divisor);
 }

 return scm_double_cell (scm_tc16_fraction,
 SCM_UNPACK (numerator),
 SCM_UNPACK (denominator), 0);
 }
}
#undef FUNC_NAME
@@ 784,8 +746,9 @@ SCM_PRIMITIVE_GENERIC (scm_abs, "abs", 1, 0, 0,
{
if (scm_is_false (scm_negative_p (SCM_FRACTION_NUMERATOR (x))))
return x;
 return scm_i_make_ratio (scm_difference (SCM_FRACTION_NUMERATOR (x), SCM_UNDEFINED),
 SCM_FRACTION_DENOMINATOR (x));
+ return scm_i_make_ratio_already_reduced
+ (scm_difference (SCM_FRACTION_NUMERATOR (x), SCM_UNDEFINED),
+ SCM_FRACTION_DENOMINATOR (x));
}
else
SCM_WTA_DISPATCH_1 (g_scm_abs, x, 1, s_scm_abs);
@@ 853,6 +816,83 @@ SCM_PRIMITIVE_GENERIC (scm_modulo, "modulo", 2, 0, 0,
}
#undef FUNC_NAME
+/* scm_exact_integer_quotient returns the exact integer q such that
+ n = q*d, for exact integers n and d, where d is known in advance to
+ divide n evenly (with zero remainder). */
+static SCM
+scm_exact_integer_quotient (SCM n, SCM d)
+#define FUNC_NAME "exactintegerquotient"
+{
+ if (SCM_LIKELY (SCM_I_INUMP (n)))
+ {
+ scm_t_inum nn = SCM_I_INUM (n);
+ if (SCM_LIKELY (SCM_I_INUMP (d)))
+ {
+ scm_t_inum dd = SCM_I_INUM (d);
+ if (SCM_UNLIKELY (dd == 0))
+ scm_num_overflow ("exactintegerquotient");
+ else
+ {
+ scm_t_inum qq = nn / dd;
+ if (SCM_LIKELY (SCM_FIXABLE (qq)))
+ return SCM_I_MAKINUM (qq);
+ else
+ return scm_i_inum2big (qq);
+ }
+ }
+ else if (SCM_LIKELY (SCM_BIGP (d)))
+ {
+ /* n is an inum and d is a bignum. Given that d is known to
+ divide n evenly, there are only two possibilities: n is 0,
+ or else n is fixnummin and d is abs(fixnummin). */
+ if (nn == 0)
+ return SCM_INUM0;
+ else
+ return SCM_I_MAKINUM (1);
+ }
+ else
+ SCM_WRONG_TYPE_ARG (2, d);
+ }
+ else if (SCM_LIKELY (SCM_BIGP (n)))
+ {
+ if (SCM_LIKELY (SCM_I_INUMP (d)))
+ {
+ scm_t_inum dd = SCM_I_INUM (d);
+ if (SCM_UNLIKELY (dd == 0))
+ scm_num_overflow ("exactintegerquotient");
+ else if (SCM_UNLIKELY (dd == 1))
+ return n;
+ else
+ {
+ SCM q = scm_i_mkbig ();
+ if (dd > 0)
+ mpz_divexact_ui (SCM_I_BIG_MPZ (q), SCM_I_BIG_MPZ (n), dd);
+ else
+ {
+ mpz_divexact_ui (SCM_I_BIG_MPZ (q), SCM_I_BIG_MPZ (n), dd);
+ mpz_neg (SCM_I_BIG_MPZ (q), SCM_I_BIG_MPZ (q));
+ }
+ scm_remember_upto_here_1 (n);
+ return scm_i_normbig (q);
+ }
+ }
+ else if (SCM_LIKELY (SCM_BIGP (d)))
+ {
+ SCM q = scm_i_mkbig ();
+ mpz_divexact (SCM_I_BIG_MPZ (q),
+ SCM_I_BIG_MPZ (n),
+ SCM_I_BIG_MPZ (d));
+ scm_remember_upto_here_2 (n, d);
+ return scm_i_normbig (q);
+ }
+ else
+ SCM_WRONG_TYPE_ARG (2, d);
+ }
+ else
+ SCM_WRONG_TYPE_ARG (1, n);
+}
+#undef FUNC_NAME
+
/* two_valued_wta_dispatch_2 is a version of SCM_WTA_DISPATCH_2 for
twovalued functions. It is called from primitive generics that take
two arguments and return two values, when the core procedure is
@@ 4636,6 +4676,23 @@ SCM_DEFINE (scm_integer_expt, "integerexpt", 2, 0, 0,
else /* return NaN for (0 ^ k) for negative k per R6RS */
return scm_nan ();
}
+ /* Optimize the fraction case, to avoid needless reduction of
+ intermediate products to lowest terms. There will never be any
+ common factor to cancel out, so it would be a waste. */
+ else if (SCM_FRACTIONP (n))
+ {
+ if (scm_is_true (scm_positive_p (k)))
+ return scm_i_make_ratio_already_reduced
+ (scm_integer_expt (SCM_FRACTION_NUMERATOR (n), k),
+ scm_integer_expt (SCM_FRACTION_DENOMINATOR (n), k));
+ else
+ {
+ k = scm_difference (k, SCM_UNDEFINED);
+ return scm_i_make_ratio_already_reduced
+ (scm_integer_expt (SCM_FRACTION_DENOMINATOR (n), k),
+ scm_integer_expt (SCM_FRACTION_NUMERATOR (n), k));
+ }
+ }
if (SCM_I_INUMP (k))
i2 = SCM_I_INUM (k);
@@ 7282,8 +7339,9 @@ scm_difference (SCM x, SCM y)
return scm_c_make_rectangular (SCM_COMPLEX_REAL (x),
SCM_COMPLEX_IMAG (x));
else if (SCM_FRACTIONP (x))
 return scm_i_make_ratio (scm_difference (SCM_FRACTION_NUMERATOR (x), SCM_UNDEFINED),
 SCM_FRACTION_DENOMINATOR (x));
+ return scm_i_make_ratio_already_reduced
+ (scm_difference (SCM_FRACTION_NUMERATOR (x), SCM_UNDEFINED),
+ SCM_FRACTION_DENOMINATOR (x));
else
SCM_WTA_DISPATCH_1 (g_difference, x, SCM_ARG1, s_difference);
}
@@ 7825,14 +7883,14 @@ do_divide (SCM x, SCM y, int inexact)
{
if (inexact)
return scm_from_double (1.0 / (double) xx);
 else return scm_i_make_ratio (SCM_INUM1, x);
+ else return scm_i_make_ratio_already_reduced (SCM_INUM1, x);
}
}
else if (SCM_BIGP (x))
{
if (inexact)
return scm_from_double (1.0 / scm_i_big2dbl (x));
 else return scm_i_make_ratio (SCM_INUM1, x);
+ else return scm_i_make_ratio_already_reduced (SCM_INUM1, x);
}
else if (SCM_REALP (x))
{
@@ 7862,8 +7920,8 @@ do_divide (SCM x, SCM y, int inexact)
}
}
else if (SCM_FRACTIONP (x))
 return scm_i_make_ratio (SCM_FRACTION_DENOMINATOR (x),
 SCM_FRACTION_NUMERATOR (x));
+ return scm_i_make_ratio_already_reduced (SCM_FRACTION_DENOMINATOR (x),
+ SCM_FRACTION_NUMERATOR (x));
else
SCM_WTA_DISPATCH_1 (g_divide, x, SCM_ARG1, s_divide);
}
@@ 7960,32 +8018,9 @@ do_divide (SCM x, SCM y, int inexact)
return x;
else
{
 /* FIXME: HMM, what are the relative performance issues here?
 We need to test. Is it faster on average to test
 divisible_p, then perform whichever operation, or is it
 faster to perform the integer div opportunistically and
 switch to real if there's a remainder? For now we take the
 middle ground: test, then if divisible, use the faster div
 func. */

 scm_t_inum abs_yy = yy < 0 ? yy : yy;
 int divisible_p = mpz_divisible_ui_p (SCM_I_BIG_MPZ (x), abs_yy);

 if (divisible_p)
 {
 SCM result = scm_i_mkbig ();
 mpz_divexact_ui (SCM_I_BIG_MPZ (result), SCM_I_BIG_MPZ (x), abs_yy);
 scm_remember_upto_here_1 (x);
 if (yy < 0)
 mpz_neg (SCM_I_BIG_MPZ (result), SCM_I_BIG_MPZ (result));
 return scm_i_normbig (result);
 }
 else
 {
 if (inexact)
 return scm_from_double (scm_i_big2dbl (x) / (double) yy);
 else return scm_i_make_ratio (x, y);
 }
+ if (inexact)
+ return scm_from_double (scm_i_big2dbl (x) / (double) yy);
+ else return scm_i_make_ratio (x, y);
}
}
else if (SCM_BIGP (y))
@@ 8003,21 +8038,7 @@ do_divide (SCM x, SCM y, int inexact)
return scm_from_double (mpq_get_d (q));
}
else
 {
 int divisible_p = mpz_divisible_p (SCM_I_BIG_MPZ (x),
 SCM_I_BIG_MPZ (y));
 if (divisible_p)
 {
 SCM result = scm_i_mkbig ();
 mpz_divexact (SCM_I_BIG_MPZ (result),
 SCM_I_BIG_MPZ (x),
 SCM_I_BIG_MPZ (y));
 scm_remember_upto_here_2 (x, y);
 return scm_i_normbig (result);
 }
 else
 return scm_i_make_ratio (x, y);
 }
+ return scm_i_make_ratio (x, y);
}
else if (SCM_REALP (y))
{
@@ 8826,8 +8847,9 @@ SCM_PRIMITIVE_GENERIC (scm_magnitude, "magnitude", 1, 0, 0,
{
if (scm_is_false (scm_negative_p (SCM_FRACTION_NUMERATOR (z))))
return z;
 return scm_i_make_ratio (scm_difference (SCM_FRACTION_NUMERATOR (z), SCM_UNDEFINED),
 SCM_FRACTION_DENOMINATOR (z));
+ return scm_i_make_ratio_already_reduced
+ (scm_difference (SCM_FRACTION_NUMERATOR (z), SCM_UNDEFINED),
+ SCM_FRACTION_DENOMINATOR (z));
}
else
SCM_WTA_DISPATCH_1 (g_scm_magnitude, z, SCM_ARG1, s_scm_magnitude);
@@ 8927,8 +8949,9 @@ SCM_PRIMITIVE_GENERIC (scm_inexact_to_exact, "inexact>exact", 1, 0, 0,
mpq_init (frac);
mpq_set_d (frac, val);
 q = scm_i_make_ratio (scm_i_mpz2num (mpq_numref (frac)),
 scm_i_mpz2num (mpq_denref (frac)));
+ q = scm_i_make_ratio_already_reduced
+ (scm_i_mpz2num (mpq_numref (frac)),
+ scm_i_mpz2num (mpq_denref (frac)));
/* When scm_i_make_ratio throws, we leak the memory allocated
for frac...
diff git a/testsuite/tests/numbers.test b/testsuite/tests/numbers.test
index b1f3d8b..7cb4694 100644
 a/testsuite/tests/numbers.test
+++ b/testsuite/tests/numbers.test
@@ 4034,6 +4034,9 @@
(passif (eqv? 0.125 (expt 2 3.0)))
(passif (eqv? 0.125 (expt 2.0 3.0)))
(passif (eqv? 0.25 (expt 2.0 2.0)))
+ (passif (eqv? 32/243 (expt 2/3 5)))
+ (passif (eqv? 243/32 (expt 2/3 5)))
+ (passif (eqv? 32 (expt 1/2 5)))
(passif (testeqv? (* 1.0+0.0i 12398 12398) (expt +12398i 2.0)))
(passif (eqvloosely? +i (expt 1 0.5)))
(passif (eqvloosely? +i (expt 1 1/2)))
@@ 4304,6 +4307,9 @@
(passif (eqv? 1/8 (integerexpt 2 3)))
(passif (eqv? 0.125 (integerexpt 2.0 3)))
(passif (eqv? 0.25 (integerexpt 2.0 2)))
+ (passif (eqv? 32/243 (integerexpt 2/3 5)))
+ (passif (eqv? 243/32 (integerexpt 2/3 5)))
+ (passif (eqv? 32 (integerexpt 1/2 5)))
(passif (testeqv? (* 1.0+0.0i 12398 12398) (integerexpt +12398.0i 2))))

1.7.2.5
===
ContentType: text/xdiff
ContentDisposition: inline;
filename=0003Addroundasharoundingarithmeticshiftoperator.patch
ContentDescription: Add `roundash', a rounding arithmetic shift operator
>From c1e2e76872dad0fb53c4f389b387019b136e36e1 Mon Sep 17 00:00:00 2001
From: Mark H Weaver
Date: Wed, 6 Apr 2011 17:29:06 0400
Subject: [PATCH 3/7] Add `roundash', a rounding arithmetic shift operator
* libguile/numbers.c (left_shift_exact_integer,
floor_right_shift_exact_integer, round_right_shift_exact_integer):
New internal static functions to efficiently compute n * 2^count,
floor(n / 2^count), and round(n / 2^count), respectively, for
exact integer N and positive exact integer COUNT. Used to combine
the implementations of `ash' and `roundash' with minimal code
duplication.
(scm_ash): Reimplement in terms of left_shift_exact_integer and
floor_right_shift_exact_integer. Note that this function efficiently
computes floor(n * 2^count).
(scm_round_ash): New procedure to efficiently compute
round(n * 2^count), for exact integers N and COUNT. Implemented
in terms of left_shift_exact_integer and
round_right_shift_exact_integer.
* libguile/numbers.h: Add prototype for scm_round_ash. Change the
name of scm_ash's second formal parameter from `cnt' to `count'.
* testsuite/tests/numbers.test (roundash, ash): Add new unified
testing framework for `ash' and `roundash'. Previously, the tests
for `ash' were not very comprehensive; for example, they did not
include a single test where the number to be shifted was a bignum.
* doc/ref/apidata.texi (Bitwise Operations): Add documentation for
`roundash'. Improve documentation for `ash'.
* NEWS: Add NEWS entry.

NEWS  8 ++
doc/ref/apidata.texi  44 ++++++
libguile/numbers.c  230 ++++++++++++++++++++++++++++
libguile/numbers.h  3 +
testsuite/tests/numbers.test  114 +++++++++
5 files changed, 247 insertions(+), 152 deletions()
diff git a/NEWS b/NEWS
index f5760cf..68168b0 100644
 a/NEWS
+++ b/NEWS
@@ 4,7 +4,15 @@ See the end for copying conditions.
Please send Guile bug reports to bugguile@gnu.org.
+Changes in 2.0.3 (since 2.0.2):
+* Notable changes
+
+** New procedure: `roundash', a rounding arithmetic shift operator
+
+See "Bitwise Operations" in the manual, for more.
+
+
Changes in 2.0.2 (since 2.0.1):
* Notable changes
diff git a/doc/ref/apidata.texi b/doc/ref/apidata.texi
index 9825bef..3a14d29 100644
 a/doc/ref/apidata.texi
+++ b/doc/ref/apidata.texi
@@ 1671,19 +1671,16 @@ starts from 0 for the least significant bit.
@end lisp
@end deffn
@deffn {Scheme Procedure} ash n cnt
@deffnx {C Function} scm_ash (n, cnt)
Return @var{n} shifted left by @var{cnt} bits, or shifted right if
@var{cnt} is negative. This is an ``arithmetic'' shift.

This is effectively a multiplication by @m{2^{cnt}, 2^@var{cnt}}, and
when @var{cnt} is negative it's a division, rounded towards negative
infinity. (Note that this is not the same rounding as @code{quotient}
does.)
+@deffn {Scheme Procedure} ash n count
+@deffnx {C Function} scm_ash (n, count)
+Return @math{floor(@var{n} * 2^@var{count})}, but computed
+more efficiently. @var{n} and @var{count} must be exact
+integers.
With @var{n} viewed as an infinite precision twos complement,
@code{ash} means a left shift introducing zero bits, or a right shift
dropping bits.
+With @var{n} viewed as an infiniteprecision twoscomplement
+integer, @code{ash} means a left shift introducing zero bits
+when @var{count} is positive, or a right shift dropping bits
+when @var{count} is negative. This is an ``arithmetic'' shift.
@lisp
(number>string (ash #b1 3) 2) @result{} "1000"
@@ 1694,6 +1691,29 @@ dropping bits.
@end lisp
@end deffn
+@deffn {Scheme Procedure} roundash n count
+@deffnx {C Function} scm_round_ash (n, count)
+Return @math{round(@var{n} * 2^@var{count})}, but computed
+more efficiently. @var{n} and @var{count} must be exact
+integers.
+
+With @var{n} viewed as an infiniteprecision twoscomplement
+integer, @code{roundash} means a left shift introducing zero
+bits when @var{count} is positive, or a right shift rounding
+to the nearest integer (with ties going to the nearest even
+integer) when @var{count} is negative. This is a rounded
+``arithmetic'' shift.
+
+@lisp
+(number>string (roundash #b1 3) 2) @result{} \"1000\"
+(number>string (roundash #b1010 1) 2) @result{} \"101\"
+(number>string (roundash #b1010 2) 2) @result{} \"10\"
+(number>string (roundash #b1011 2) 2) @result{} \"11\"
+(number>string (roundash #b1101 2) 2) @result{} \"11\"
+(number>string (roundash #b1110 2) 2) @result{} \"100\"
+@end lisp
+@end deffn
+
@deffn {Scheme Procedure} logcount n
@deffnx {C Function} scm_logcount (n)
Return the number of bits in integer @var{n}. If @var{n} is
diff git a/libguile/numbers.c b/libguile/numbers.c
index 80b46df..e2c74d2 100644
 a/libguile/numbers.c
+++ b/libguile/numbers.c
@@ 4750,19 +4750,122 @@ SCM_DEFINE (scm_integer_expt, "integerexpt", 2, 0, 0,
}
#undef FUNC_NAME
+/* n must be an exact integer, and count > 0.
+ Returns n * 2^count. */
+static SCM
+left_shift_exact_integer (SCM n, long count)
+{
+ if (SCM_I_INUMP (n))
+ {
+ scm_t_inum nn = SCM_I_INUM (n);
+
+ /* Left shift of count >= SCM_I_FIXNUM_BIT1 will always
+ overflow a nonzero fixnum. For smaller shifts we check the
+ bits going into positions above SCM_I_FIXNUM_BIT1. If they're
+ all 0s for nn>=0, or all 1s for nn<0 then there's no overflow.
+ Those bits are "nn >> (SCM_I_FIXNUM_BIT1 
+ count)". */
+
+ if (nn == 0)
+ return n;
+ else if (count < SCM_I_FIXNUM_BIT1 &&
+ ((scm_t_bits) (SCM_SRS (nn, (SCM_I_FIXNUM_BIT1  count)) + 1)
+ <= 1))
+ {
+ return SCM_I_MAKINUM (nn << count);
+ }
+ else
+ {
+ SCM result = scm_i_inum2big (nn);
+ mpz_mul_2exp (SCM_I_BIG_MPZ (result), SCM_I_BIG_MPZ (result),
+ count);
+ return result;
+ }
+ }
+ else if (SCM_BIGP (n))
+ {
+ SCM result = scm_i_mkbig ();
+ mpz_mul_2exp (SCM_I_BIG_MPZ (result), SCM_I_BIG_MPZ (n),
+ count);
+ scm_remember_upto_here_1 (n);
+ return result;
+ }
+ else
+ scm_syserror ("left_shift_exact_integer");
+}
+
+/* n must be an exact integer, and count > 0.
+ Returns floor(n / 2^count). */
+static SCM
+floor_right_shift_exact_integer (SCM n, long count)
+{
+ if (SCM_I_INUMP (n))
+ {
+ scm_t_inum nn = SCM_I_INUM (n);
+
+ if (count >= SCM_I_FIXNUM_BIT)
+ return (nn >= 0 ? SCM_INUM0 : SCM_I_MAKINUM (1));
+ else
+ return SCM_I_MAKINUM (SCM_SRS (nn, count));
+ }
+ else if (SCM_BIGP (n))
+ {
+ SCM result = scm_i_mkbig ();
+ mpz_fdiv_q_2exp (SCM_I_BIG_MPZ (result), SCM_I_BIG_MPZ (n),
+ count);
+ scm_remember_upto_here_1 (n);
+ return scm_i_normbig (result);
+ }
+ else
+ scm_syserror ("floor_right_shift_exact_integer");
+}
+
+/* n must be an exact integer, and count > 0.
+ Returns round(n / 2^count). */
+static SCM
+round_right_shift_exact_integer (SCM n, long count)
+{
+ if (SCM_I_INUMP (n))
+ {
+ scm_t_inum nn = SCM_I_INUM (n);
+ scm_t_inum qq = SCM_SRS (nn, count);
+
+ if (count >= SCM_I_FIXNUM_BIT)
+ return SCM_INUM0;
+ else if (0 == (nn & (1L << (count1))))
+ return SCM_I_MAKINUM (qq); /* round down */
+ else if (nn & ((1L << (count1))  1))
+ return SCM_I_MAKINUM (qq + 1); /* round up */
+ else
+ return SCM_I_MAKINUM ((~1L) & (qq + 1)); /* round to even */
+ }
+ else if (SCM_BIGP (n))
+ {
+ SCM q = scm_i_mkbig ();
+ mpz_fdiv_q_2exp (SCM_I_BIG_MPZ (q), SCM_I_BIG_MPZ (n), count);
+ if (mpz_tstbit (SCM_I_BIG_MPZ (n), count1))
+ {
+ if ((mpz_scan1 (SCM_I_BIG_MPZ (n), 0) < count1) 
+ (mpz_odd_p (SCM_I_BIG_MPZ (q))))
+ mpz_add_ui (SCM_I_BIG_MPZ (q), SCM_I_BIG_MPZ (q), 1);
+ }
+ scm_remember_upto_here_1 (n);
+ return scm_i_normbig (q);
+ }
+ else
+ scm_syserror ("round_right_shift_exact_integer");
+}
+
SCM_DEFINE (scm_ash, "ash", 2, 0, 0,
 (SCM n, SCM cnt),
 "Return @var{n} shifted left by @var{cnt} bits, or shifted right\n"
 "if @var{cnt} is negative. This is an ``arithmetic'' shift.\n"
 "\n"
 "This is effectively a multiplication by 2^@var{cnt}, and when\n"
 "@var{cnt} is negative it's a division, rounded towards negative\n"
 "infinity. (Note that this is not the same rounding as\n"
 "@code{quotient} does.)\n"
+ (SCM n, SCM count),
+ "Return @math{floor(@var{n} * 2^@var{count})}, but computed\n"
+ "more efficiently. @var{n} and @var{count} must be exact\n"
+ "integers.\n"
"\n"
 "With @var{n} viewed as an infinite precision twos complement,\n"
 "@code{ash} means a left shift introducing zero bits, or a right\n"
 "shift dropping bits.\n"
+ "With @var{n} viewed as an infiniteprecision twoscomplement\n"
+ "integer, @code{ash} means a left shift introducing zero bits\n"
+ "when @var{count} is positive, or a right shift dropping bits\n"
+ "when @var{count} is negative. This is an ``arithmetic'' shift.\n"
"\n"
"@lisp\n"
"(number>string (ash #b1 3) 2) @result{} \"1000\"\n"
@@ 4773,79 +4876,58 @@ SCM_DEFINE (scm_ash, "ash", 2, 0, 0,
"@end lisp")
#define FUNC_NAME s_scm_ash
{
 long bits_to_shift;
 bits_to_shift = scm_to_long (cnt);

 if (SCM_I_INUMP (n))
+ if (SCM_I_INUMP (n)  SCM_BIGP (n))
{
 scm_t_inum nn = SCM_I_INUM (n);
+ long bits_to_shift = scm_to_long (count);
if (bits_to_shift > 0)
 {
 /* Left shift of bits_to_shift >= SCM_I_FIXNUM_BIT1 will always
 overflow a nonzero fixnum. For smaller shifts we check the
 bits going into positions above SCM_I_FIXNUM_BIT1. If they're
 all 0s for nn>=0, or all 1s for nn<0 then there's no overflow.
 Those bits are "nn >> (SCM_I_FIXNUM_BIT1 
 bits_to_shift)". */

 if (nn == 0)
 return n;

 if (bits_to_shift < SCM_I_FIXNUM_BIT1
 && ((scm_t_bits)
 (SCM_SRS (nn, (SCM_I_FIXNUM_BIT1  bits_to_shift)) + 1)
 <= 1))
 {
 return SCM_I_MAKINUM (nn << bits_to_shift);
 }
 else
 {
 SCM result = scm_i_inum2big (nn);
 mpz_mul_2exp (SCM_I_BIG_MPZ (result), SCM_I_BIG_MPZ (result),
 bits_to_shift);
 return result;
 }
 }
+ return left_shift_exact_integer (n, bits_to_shift);
+ else if (SCM_LIKELY (bits_to_shift < 0))
+ return floor_right_shift_exact_integer (n, bits_to_shift);
else
 {
 bits_to_shift = bits_to_shift;
 if (bits_to_shift >= SCM_LONG_BIT)
 return (nn >= 0 ? SCM_INUM0 : SCM_I_MAKINUM(1));
 else
 return SCM_I_MAKINUM (SCM_SRS (nn, bits_to_shift));
 }

+ return n;
}
 else if (SCM_BIGP (n))
 {
 SCM result;
+ else
+ SCM_WRONG_TYPE_ARG (SCM_ARG1, n);
+}
+#undef FUNC_NAME
 if (bits_to_shift == 0)
 return n;
+SCM_DEFINE (scm_round_ash, "roundash", 2, 0, 0,
+ (SCM n, SCM count),
+ "Return @math{round(@var{n} * 2^@var{count})}, but computed\n"
+ "more efficiently. @var{n} and @var{count} must be exact\n"
+ "integers.\n"
+ "\n"
+ "With @var{n} viewed as an infiniteprecision twoscomplement\n"
+ "integer, @code{roundash} means a left shift introducing zero\n"
+ "bits when @var{count} is positive, or a right shift rounding\n"
+ "to the nearest integer (with ties going to the nearest even\n"
+ "integer) when @var{count} is negative. This is a rounded\n"
+ "``arithmetic'' shift.\n"
+ "\n"
+ "@lisp\n"
+ "(number>string (roundash #b1 3) 2) @result{} \"1000\"\n"
+ "(number>string (roundash #b1010 1) 2) @result{} \"101\"\n"
+ "(number>string (roundash #b1010 2) 2) @result{} \"10\"\n"
+ "(number>string (roundash #b1011 2) 2) @result{} \"11\"\n"
+ "(number>string (roundash #b1101 2) 2) @result{} \"11\"\n"
+ "(number>string (roundash #b1110 2) 2) @result{} \"100\"\n"
+ "@end lisp")
+#define FUNC_NAME s_scm_round_ash
+{
+ if (SCM_I_INUMP (n)  SCM_BIGP (n))
+ {
+ long bits_to_shift = scm_to_long (count);
 result = scm_i_mkbig ();
 if (bits_to_shift >= 0)
 {
 mpz_mul_2exp (SCM_I_BIG_MPZ (result), SCM_I_BIG_MPZ (n),
 bits_to_shift);
 return result;
 }
+ if (bits_to_shift > 0)
+ return left_shift_exact_integer (n, bits_to_shift);
+ else if (SCM_LIKELY (bits_to_shift < 0))
+ return round_right_shift_exact_integer (n, bits_to_shift);
else
 {
 /* GMP doesn't have an fdiv_q_2exp variant returning just a long, so
 we have to allocate a bignum even if the result is going to be a
 fixnum. */
 mpz_fdiv_q_2exp (SCM_I_BIG_MPZ (result), SCM_I_BIG_MPZ (n),
 bits_to_shift);
 return scm_i_normbig (result);
 }

+ return n;
}
else
 {
 SCM_WRONG_TYPE_ARG (SCM_ARG1, n);
 }
+ SCM_WRONG_TYPE_ARG (SCM_ARG1, n);
}
#undef FUNC_NAME
diff git a/libguile/numbers.h b/libguile/numbers.h
index d985830..a0cc8db 100644
 a/libguile/numbers.h
+++ b/libguile/numbers.h
@@ 204,7 +204,8 @@ SCM_API SCM scm_logbit_p (SCM n1, SCM n2);
SCM_API SCM scm_lognot (SCM n);
SCM_API SCM scm_modulo_expt (SCM n, SCM k, SCM m);
SCM_API SCM scm_integer_expt (SCM z1, SCM z2);
SCM_API SCM scm_ash (SCM n, SCM cnt);
+SCM_API SCM scm_ash (SCM n, SCM count);
+SCM_API SCM scm_round_ash (SCM n, SCM count);
SCM_API SCM scm_bit_extract (SCM n, SCM start, SCM end);
SCM_API SCM scm_logcount (SCM n);
SCM_API SCM scm_integer_length (SCM n);
diff git a/testsuite/tests/numbers.test b/testsuite/tests/numbers.test
index 7cb4694..c4979fd 100644
 a/testsuite/tests/numbers.test
+++ b/testsuite/tests/numbers.test
@@ 201,71 +201,6 @@
(eqv? 2305843009213693953 (1 2305843009213693952))))
;;;
;;; ash
;;;

(withtestprefix "ash"

 (passif "documented?"
 (documented? ash))

 (passif (eqv? 0 (ash 0 0)))
 (passif (eqv? 0 (ash 0 1)))
 (passif (eqv? 0 (ash 0 1000)))
 (passif (eqv? 0 (ash 0 1)))
 (passif (eqv? 0 (ash 0 1000)))

 (passif (eqv? 1 (ash 1 0)))
 (passif (eqv? 2 (ash 1 1)))
 (passif (eqv? 340282366920938463463374607431768211456 (ash 1 128)))
 (passif (eqv? 0 (ash 1 1)))
 (passif (eqv? 0 (ash 1 1000)))

 (passif (eqv? 1 (ash 1 0)))
 (passif (eqv? 2 (ash 1 1)))
 (passif (eqv? 340282366920938463463374607431768211456 (ash 1 128)))
 (passif (eqv? 1 (ash 1 1)))
 (passif (eqv? 1 (ash 1 1000)))

 (passif (eqv? 3 (ash 3 0)))
 (passif (eqv? 6 (ash 3 1)))
 (passif (eqv? 1020847100762815390390123822295304634368 (ash 3 128)))
 (passif (eqv? 2 (ash 3 1)))
 (passif (eqv? 1 (ash 3 1000)))

 (passif (eqv? 6 (ash 23 2)))

 (passif (eqv? mostpositivefixnum (ash mostpositivefixnum 0)))
 (passif (eqv? (* 2 mostpositivefixnum) (ash mostpositivefixnum 1)))
 (passif (eqv? (* 4 mostpositivefixnum) (ash mostpositivefixnum 2)))
 (passif
 (eqv? (* mostpositivefixnum 340282366920938463463374607431768211456)
 (ash mostpositivefixnum 128)))
 (passif (eqv? (quotient mostpositivefixnum 2)
 (ash mostpositivefixnum 1)))
 (passif (eqv? 0 (ash mostpositivefixnum 1000)))

 (let ((mpf4 (quotient mostpositivefixnum 4)))
 (passif (eqv? (* 2 mpf4) (ash mpf4 1)))
 (passif (eqv? (* 4 mpf4) (ash mpf4 2)))
 (passif (eqv? (* 8 mpf4) (ash mpf4 3))))

 (passif (eqv? mostnegativefixnum (ash mostnegativefixnum 0)))
 (passif (eqv? (* 2 mostnegativefixnum) (ash mostnegativefixnum 1)))
 (passif (eqv? (* 4 mostnegativefixnum) (ash mostnegativefixnum 2)))
 (passif
 (eqv? (* mostnegativefixnum 340282366920938463463374607431768211456)
 (ash mostnegativefixnum 128)))
 (passif (eqv? (quotientfloor mostnegativefixnum 2)
 (ash mostnegativefixnum 1)))
 (passif (eqv? 1 (ash mostnegativefixnum 1000)))

 (let ((mnf4 (quotientfloor mostnegativefixnum 4)))
 (passif (eqv? (* 2 mnf4) (ash mnf4 1)))
 (passif (eqv? (* 4 mnf4) (ash mnf4 2)))
 (passif (eqv? (* 8 mnf4) (ash mnf4 3)))))

;;;
;;; exact?
;;;
@@ 4891,3 +4826,52 @@
roundquotient
roundremainder
validroundanswer?)))
+
+;;;
+;;; ash
+;;; roundash
+;;;
+
+(let ()
+ (define (testashvariant name ashvariant roundvariant)
+ (withtestprefix name
+ (define (test n count)
+ (passif (list n count)
+ (eqv? (ashvariant n count)
+ (roundvariant (* n (expt 2 count))))))
+
+ (passif "documented?"
+ (documented? ashvariant))
+
+ (foreach (lambda (n)
+ (foreach (lambda (count) (test n count))
+ '(1000 3 2 1 0 1 2 3 1000)))
+ (list 0 1 3 23 1 3 23
+ fixnummax
+ (1+ fixnummax)
+ (1 fixnummax)
+ (* fixnummax 4)
+ (quotient fixnummax 4)
+ fixnummin
+ (1+ fixnummin)
+ (1 fixnummin)
+ (* fixnummin 4)
+ (quotient fixnummin 4)))
+
+ (do ((count 2 (1 count))
+ (vals '(1 3 5 7 9 11)
+ (map (lambda (n) (* 2 n)) vals)))
+ ((> (car vals) (* 2 fixnummax)) 'done)
+ (foreach (lambda (n)
+ (test n count)
+ (test ( n) count))
+ vals))
+
+ ;; Test rounding
+ (foreach (lambda (base)
+ (foreach (lambda (offset) (test (+ base offset) 3))
+ '(#b11001 #b11100 #b11101 #b10001 #b10100 #b10101)))
+ (list 0 64 64 (* 64 fixnummax) (* 64 fixnummin)))))
+
+ (testashvariant 'ash ash floor)
+ (testashvariant 'roundash roundash round))

1.7.2.5
===
ContentType: text/xdiff
ContentDisposition: inline;
filename=0004Introducedouble_precisionanduseit.patch
ContentDescription: Introduce double_precision and use it
>From 42ecb421749b7b5ab64943c402c92587509e9f04 Mon Sep 17 00:00:00 2001
From: Mark H Weaver
Date: Wed, 23 Feb 2011 00:04:12 0500
Subject: [PATCH 4/7] Introduce double_precision and use it
* libguile/numbers.c (double_precision): New internal static global
which contains the number of bits of precision in the C double type.
(scm_i_dbl2num, scm_num_eq_p): Use double_precision instead of
DBL_MANT_DIG. Previously, the code improperly assumed that
DBL_MANT_DIG is a number of bits, when in fact it is a number of
base`FLT_RADIX' digits.
(log_of_shifted_double): Use double_precision instead of
scm_dblprec[0]. (Note that scm_dblprec[0] is used by the idbl2str,
and is either 60 or the number of bits of precision of doubles,
whichever is less. This limitation cannot be lifted without
increasing the size of the fx_per_radix array, which is already over
16 kilobytes.)

libguile/numbers.c  64 ++++++++++++++++++++++++++++++++++++
1 files changed, 45 insertions(+), 19 deletions()
diff git a/libguile/numbers.c b/libguile/numbers.c
index e2c74d2..1274306 100644
 a/libguile/numbers.c
+++ b/libguile/numbers.c
@@ 168,10 +168,40 @@ scm_from_complex_double (complex double z)
#endif /* GUILE_I */
+/* double_precision is the smallest positive integer k
+ such that 1.0 == 1.0 + 2.0^(k).
static mpz_t z_negative_one;
+ For floatingpoint numbers with significands represented
+ in base 2, it is the number of bits in the significand
+ (including the mostsignificant 1 bit which is sometimes
+ left implicit and not actually stored).
+
+ When the C "double" type corresponds to the IEEE 754
+ binary64 format, double_precision should be 53.
+*/
+static long double_precision;
+
+static void
+init_double_precision (void)
+{
+ double sum;
+ long i;
+
+ for (i = 1; i < 1000000; i++)
+ {
+ sum = 1.0 + ldexp (1.0, i);
+ if (sum == 1.0)
+ {
+ double_precision = i;
+ return;
+ }
+ }
+ scm_syserror ("init_double_precision");
+}
+static mpz_t z_negative_one;
+
/* Clear the `mpz_t' embedded in bignum PTR. */
static void
finalize_bignum (GC_PTR ptr, GC_PTR data)
@@ 304,10 +334,10 @@ scm_i_dbl2num (double u)
/* scm_i_big2dbl() rounds to the closest representable double, in accordance
with R5RS exact>inexact.
 The approach is to use mpz_get_d to pick out the high DBL_MANT_DIG bits
 (ie. truncate towards zero), then adjust to get the closest double by
 examining the next lower bit and adding 1 (to the absolute value) if
 necessary.
+ The approach is to use mpz_get_d to pick out the high
+ double_precision bits (ie. truncate towards zero), then adjust to
+ get the closest double by examining the next lower bit and adding 1
+ (to the absolute value) if necessary.
Bignums exactly half way between representable doubles are rounded to the
next higher absolute value (ie. away from zero). This seems like an
@@ 321,7 +351,7 @@ scm_i_dbl2num (double u)
In GMP before 4.2, mpz_get_d rounding was unspecified. It ended up
following the hardware rounding mode, but applied to the absolute
value of the mpz_t operand. This is not what we want so we put the
 high DBL_MANT_DIG bits into a temporary. Starting with GMP 4.2
+ high double_precision bits into a temporary. Starting with GMP 4.2
(released in March 2006) mpz_get_d now always truncates towards zero.
ENHANCEME: The temporary init+clear to force the rounding in GMP
@@ 339,16 +369,11 @@ scm_i_big2dbl (SCM b)
#if 1
{
/* For GMP earlier than 4.2, force truncation towards zero */

 /* FIXME: DBL_MANT_DIG is the number of base`FLT_RADIX' digits,
 _not_ the number of bits, so this code will break badly on a
 system with nonbinary doubles. */

mpz_t tmp;
 if (bits > DBL_MANT_DIG)
+ if (bits > double_precision)
{
 size_t shift = bits  DBL_MANT_DIG;
 mpz_init2 (tmp, DBL_MANT_DIG);
+ size_t shift = bits  double_precision;
+ mpz_init2 (tmp, double_precision);
mpz_tdiv_q_2exp (tmp, SCM_I_BIG_MPZ (b), shift);
result = ldexp (mpz_get_d (tmp), shift);
mpz_clear (tmp);
@@ 363,9 +388,9 @@ scm_i_big2dbl (SCM b)
result = mpz_get_d (SCM_I_BIG_MPZ (b));
#endif
 if (bits > DBL_MANT_DIG)
+ if (bits > double_precision)
{
 unsigned long pos = bits  DBL_MANT_DIG  1;
+ unsigned long pos = bits  double_precision  1;
/* test bit number "pos" in absolute value */
if (mpz_getlimbn (SCM_I_BIG_MPZ (b), pos / GMP_NUMB_BITS)
& ((mp_limb_t) 1 << (pos % GMP_NUMB_BITS)))
@@ 6332,7 +6357,7 @@ scm_num_eq_p (SCM x, SCM y)
double yy = SCM_REAL_VALUE (y);
return scm_from_bool ((double) xx == yy
 && (DBL_MANT_DIG >= SCM_I_FIXNUM_BIT1
+ && (double_precision >= SCM_I_FIXNUM_BIT1
 xx == (scm_t_signed_bits) yy));
}
else if (SCM_COMPLEXP (y))
@@ 6386,7 +6411,7 @@ scm_num_eq_p (SCM x, SCM y)
/* see comments with inum/real above */
scm_t_signed_bits yy = SCM_I_INUM (y);
return scm_from_bool (xx == (double) yy
 && (DBL_MANT_DIG >= SCM_I_FIXNUM_BIT1
+ && (double_precision >= SCM_I_FIXNUM_BIT1
 (scm_t_signed_bits) xx == yy));
}
else if (SCM_BIGP (y))
@@ 9519,7 +9544,7 @@ log_of_shifted_double (double x, long shift)
static SCM
log_of_exact_integer_with_size (SCM n, long size)
{
 long shift = size  2 * scm_dblprec[0];
+ long shift = size  2 * double_precision;
if (shift > 0)
return log_of_shifted_double
@@ 9806,6 +9831,7 @@ scm_init_numbers ()
flo_log10e = scm_from_double (M_LOG10E);
/* determine floating point precision */
+ init_double_precision ();
for (i=2; i <= SCM_MAX_DBL_RADIX; ++i)
{
init_dblprec(&scm_dblprec[i2],i);

1.7.2.5
===
ContentType: text/xdiff
ContentDisposition: inline;
filename=0005Simplifyandimprovescm_i_big2dblandaddscm_i_big.patch
ContentDescription: Simplify and improve scm_i_big2dbl, and add
scm_i_big2dbl_2exp
>From 54f194f285114ad046fb67fd3027053f9544080f Mon Sep 17 00:00:00 2001
From: Mark H Weaver
Date: Fri, 4 Mar 2011 15:28:51 0500
Subject: [PATCH 5/7] Simplify and improve scm_i_big2dbl, and add scm_i_big2dbl_2exp
* libguile/numbers.c (scm_i_big2dbl_2exp): New internal function which
converts a bignum into a normalized significand and an exponent,
similar to frexp, or mpz_get_d_2exp but with correct rounding. This
can be used on bignums that are too large or small to be represented
by a double.
(scm_i_big2dbl): Simplify and improve scm_i_big2dbl, which is now
implemented in terms of scm_i_big2dbl_2exp. Ties now go to even.
Previously they were rounded away from zero.

libguile/numbers.c  94 ++++++++++++++++
1 files changed, 30 insertions(+), 64 deletions()
diff git a/libguile/numbers.c b/libguile/numbers.c
index 1274306..1773715 100644
 a/libguile/numbers.c
+++ b/libguile/numbers.c
@@ 331,76 +331,42 @@ scm_i_dbl2num (double u)
return scm_i_dbl2big (u);
}
/* scm_i_big2dbl() rounds to the closest representable double, in accordance
 with R5RS exact>inexact.

 The approach is to use mpz_get_d to pick out the high
 double_precision bits (ie. truncate towards zero), then adjust to
 get the closest double by examining the next lower bit and adding 1
 (to the absolute value) if necessary.

 Bignums exactly half way between representable doubles are rounded to the
 next higher absolute value (ie. away from zero). This seems like an
 adequate interpretation of R5RS "numerically closest", and it's easier
 and faster than a full "nearesteven" style.

 The bit test must be done on the absolute value of the mpz_t, which means
 we need to use mpz_getlimbn. mpz_tstbit is not right, it treats
 negatives as twos complement.

 In GMP before 4.2, mpz_get_d rounding was unspecified. It ended up
 following the hardware rounding mode, but applied to the absolute
 value of the mpz_t operand. This is not what we want so we put the
 high double_precision bits into a temporary. Starting with GMP 4.2
 (released in March 2006) mpz_get_d now always truncates towards zero.

 ENHANCEME: The temporary init+clear to force the rounding in GMP
 before 4.2 is a slowdown. It'd be faster to pick out the relevant
 high bits with mpz_getlimbn. */

double
scm_i_big2dbl (SCM b)
{
 double result;
 size_t bits;

 bits = mpz_sizeinbase (SCM_I_BIG_MPZ (b), 2);

#if 1
 {
 /* For GMP earlier than 4.2, force truncation towards zero */
 mpz_t tmp;
 if (bits > double_precision)
 {
 size_t shift = bits  double_precision;
 mpz_init2 (tmp, double_precision);
 mpz_tdiv_q_2exp (tmp, SCM_I_BIG_MPZ (b), shift);
 result = ldexp (mpz_get_d (tmp), shift);
 mpz_clear (tmp);
 }
 else
 {
 result = mpz_get_d (SCM_I_BIG_MPZ (b));
 }
 }
#else
 /* GMP 4.2 or later */
 result = mpz_get_d (SCM_I_BIG_MPZ (b));
#endif
+static SCM round_right_shift_exact_integer (SCM n, long count);
+
+/* scm_i_big2dbl_2exp() is like frexp for bignums: it converts the
+ bignum b into a normalized significand and exponent such that
+ b = significand * 2^exponent and 1/2 <= abs(significand) < 1.
+ The return value is the significand rounded to the closest
+ representable double, and the exponent is placed into *expon_p.
+ If b is zero, then the returned exponent and significand are both
+ zero. */
+static double
+scm_i_big2dbl_2exp (SCM b, long *expon_p)
+{
+ size_t bits = mpz_sizeinbase (SCM_I_BIG_MPZ (b), 2);
+ size_t shift = 0;
+ double signif;
+ long expon;
if (bits > double_precision)
{
 unsigned long pos = bits  double_precision  1;
 /* test bit number "pos" in absolute value */
 if (mpz_getlimbn (SCM_I_BIG_MPZ (b), pos / GMP_NUMB_BITS)
 & ((mp_limb_t) 1 << (pos % GMP_NUMB_BITS)))
 {
 result += ldexp ((double) mpz_sgn (SCM_I_BIG_MPZ (b)), pos + 1);
 }
+ shift = bits  double_precision;
+ b = round_right_shift_exact_integer (b, shift);
}

+ signif = mpz_get_d_2exp (&expon, SCM_I_BIG_MPZ (b));
scm_remember_upto_here_1 (b);
 return result;
+ *expon_p = expon + shift;
+ return signif;
+}
+
+/* scm_i_big2dbl() rounds to the closest representable double,
+ in accordance with R5RS exact>inexact. */
+double
+scm_i_big2dbl (SCM b)
+{
+ long expon;
+ double signif = scm_i_big2dbl_2exp (b, &expon);
+ return ldexp (signif, expon);
}
SCM

1.7.2.5
===
ContentType: text/xdiff
ContentDisposition: inline;
filename=0006Optimizelogarithmsusingscm_i_big2dbl_2exp.patch
ContentDescription: Optimize logarithms using scm_i_big2dbl_2exp
>From b2f2efbfa10dcb00d59cb4567ba5b6a217b1ed81 Mon Sep 17 00:00:00 2001
From: Mark H Weaver
Date: Wed, 23 Feb 2011 02:09:34 0500
Subject: [PATCH 6/7] Optimize logarithms using scm_i_big2dbl_2exp
* libguile/numbers.c (log_of_exact_integer_with_size): Removed.
(log_of_exact_integer): Handle bignums too large to fit in a double
using scm_i_big2dbl_2exp instead of scm_integer_length and scm_ash.
(log_of_fraction): Use log_of_exact_integer instead of
log_of_exact_integer_with_size.

libguile/numbers.c  30 ++++++++++++
1 files changed, 12 insertions(+), 18 deletions()
diff git a/libguile/numbers.c b/libguile/numbers.c
index 1773715..c9be26d 100644
 a/libguile/numbers.c
+++ b/libguile/numbers.c
@@ 9506,26 +9506,20 @@ log_of_shifted_double (double x, long shift)
return scm_c_make_rectangular (ans, M_PI);
}
/* Returns log(n), for exact integer n of integerlength size */
static SCM
log_of_exact_integer_with_size (SCM n, long size)
{
 long shift = size  2 * double_precision;

 if (shift > 0)
 return log_of_shifted_double
 (scm_to_double (scm_ash (n, scm_from_long(shift))),
 shift);
 else
 return log_of_shifted_double (scm_to_double (n), 0);
}

/* Returns log(n), for exact integer n */
static SCM
log_of_exact_integer (SCM n)
{
 return log_of_exact_integer_with_size
 (n, scm_to_long (scm_integer_length (n)));
+ if (SCM_I_INUMP (n))
+ return log_of_shifted_double (SCM_I_INUM (n), 0);
+ else if (SCM_BIGP (n))
+ {
+ long expon;
+ double signif = scm_i_big2dbl_2exp (n, &expon);
+ return log_of_shifted_double (signif, expon);
+ }
+ else
+ scm_wrong_type_arg ("log_of_exact_integer", SCM_ARG1, n);
}
/* Returns log(n/d), for exact nonzero integers n and d */
@@ 9536,8 +9530,8 @@ log_of_fraction (SCM n, SCM d)
long d_size = scm_to_long (scm_integer_length (d));
if (abs (n_size  d_size) > 1)
 return (scm_difference (log_of_exact_integer_with_size (n, n_size),
 log_of_exact_integer_with_size (d, d_size)));
+ return (scm_difference (log_of_exact_integer (n),
+ log_of_exact_integer (d)));
else if (scm_is_false (scm_negative_p (n)))
return scm_from_double
(log1p (scm_to_double (scm_divide2real (scm_difference (n, d), d))));

1.7.2.5
===
ContentType: text/xdiff
ContentDisposition: inline;
filename=0007Improveinexactdivisionofexactintegersetal.patch
ContentDescription: Improve inexact division of exact integers et al
>From d754e3f1de92fa2d33edc610f37ff24b58cddbcd Mon Sep 17 00:00:00 2001
From: Mark H Weaver
Date: Fri, 4 Mar 2011 17:40:56 0500
Subject: [PATCH 7/7] Improve inexact division of exact integers et al
* libguile/numbers.c (scm_to_double_2exp): New internal procedure which
converts an arbitrary real number to a normalized C double significand
and a base2 exponent, similar to frexp. This is the basis for making
several other inexact numerical operations robust when working with
large exact integers and rationals.
(scm_divide2real): Removed; superceded by scm_i_divide2double.
(scm_i_divide2double): Returns the ratio of two arbitrary real number
objects as a C double.
(scm_i_fraction2double, log_of_fraction): Use scm_i_divide2double
instead of scm_divide2real.
(scm_divide, do_divide): The core implementation is now in scm_divide.
do_divide has been removed. Previously, do_divide was the basis for
both scm_divide and scm_divide2real. Remove the `inexact' flag
argument, which (when nonzero) requested an inexact answer. The
inexact implementation was flawed in several respects, and is now
done by scm_i_divide2double.
(scm_i_inum_length): New internal procedure that handles the inum case
of scm_integer_length and returns the result as a C int. Used by the
inum case of scm_to_double_2exp.
(scm_integer_length): Moved inum case to scm_i_inum_length.

libguile/numbers.c  170 ++++++++++++++++++++++++++++
1 files changed, 93 insertions(+), 77 deletions()
diff git a/libguile/numbers.c b/libguile/numbers.c
index c9be26d..b35f66c 100644
 a/libguile/numbers.c
+++ b/libguile/numbers.c
@@ 401,9 +401,6 @@ scm_i_mpz2num (mpz_t b)
}
}
/* this is needed when we want scm_divide to make a float, not a ratio, even if passed two ints */
static SCM scm_divide2real (SCM x, SCM y);

/* scm_i_make_ratio_already_reduced makes a ratio more efficiently,
when the following conditions are known in advance:
@@ 459,11 +456,74 @@ scm_i_make_ratio (SCM numerator, SCM denominator)
}
#undef FUNC_NAME
+static int scm_i_inum_length (scm_t_inum n);
+
+/* scm_to_double_2exp() an inexact frexp for SCM real numbers: it
+ converts x into a normalized significand and exponent such that
+ x = significand * 2^exponent and 1/2 <= abs(significand) < 1.
+ The return value is the significand rounded to the closest
+ representable double, and the exponent is placed into *expon_p.
+ If x is zero, then the returned exponent and significand are both
+ zero. */
+static double
+scm_to_double_2exp (SCM x, long *expon_p)
+{
+ if (SCM_I_INUMP (x))
+ {
+ int expon = scm_i_inum_length (abs (SCM_I_INUM (x)));
+ *expon_p = expon;
+ return ldexp (SCM_I_INUM (x), expon);
+ }
+ else if (SCM_BIGP (x))
+ return scm_i_big2dbl_2exp (x, expon_p);
+ else if (SCM_REALP (x))
+ {
+ int expon;
+ double signif = frexp (SCM_REAL_VALUE (x), &expon);
+ *expon_p = expon;
+ return signif;
+ }
+ else if (SCM_FRACTIONP (x))
+ {
+ long n_expon, d_expon;
+ double n_signif = scm_to_double_2exp (SCM_FRACTION_NUMERATOR (x),
+ &n_expon);
+ double d_signif = scm_to_double_2exp (SCM_FRACTION_DENOMINATOR (x),
+ &d_expon);
+ long expon = n_expon  d_expon;
+ double signif = n_signif / d_signif;
+ if (signif >= 1.0  signif <= 1.0)
+ {
+ signif /= 2.0;
+ expon++;
+ }
+ *expon_p = expon;
+ return signif;
+ }
+ else
+ scm_wrong_type_arg ("scm_to_double_2exp", SCM_ARG1, x);
+}
+
+/* Return n/d as a double, where n and d are exact integers. */
+static double
+scm_i_divide2double (SCM n, SCM d)
+{
+ if (SCM_LIKELY (SCM_I_INUMP (n) && SCM_I_INUMP (d)))
+ return ((double) SCM_I_INUM (n)) / ((double) SCM_I_INUM (d));
+ else
+ {
+ long n_expon, d_expon;
+ double n_signif = scm_to_double_2exp (n, &n_expon);
+ double d_signif = scm_to_double_2exp (d, &d_expon);
+ return ldexp (n_signif / d_signif, n_expon  d_expon);
+ }
+}
+
double
scm_i_fraction2double (SCM z)
{
 return scm_to_double (scm_divide2real (SCM_FRACTION_NUMERATOR (z),
 SCM_FRACTION_DENOMINATOR (z)));
+ return scm_i_divide2double (SCM_FRACTION_NUMERATOR (z),
+ SCM_FRACTION_DENOMINATOR (z));
}
static int
@@ 5049,6 +5109,22 @@ static const char scm_ilentab[] = {
0, 1, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4
};
+/* Return the number of bits necessary to represent n */
+static int scm_i_inum_length (scm_t_inum n)
+{
+ unsigned long c = 0;
+ unsigned int l = 4;
+
+ if (n < 0)
+ n = 1  n;
+ while (n)
+ {
+ c += 4;
+ l = scm_ilentab [15 & n];
+ n >>= 4;
+ }
+ return c  4 + l;
+}
SCM_DEFINE (scm_integer_length, "integerlength", 1, 0, 0,
(SCM n),
@@ 5065,20 +5141,7 @@ SCM_DEFINE (scm_integer_length, "integerlength", 1, 0, 0,
#define FUNC_NAME s_scm_integer_length
{
if (SCM_I_INUMP (n))
 {
 unsigned long c = 0;
 unsigned int l = 4;
 scm_t_inum nn = SCM_I_INUM (n);
 if (nn < 0)
 nn = 1  nn;
 while (nn)
 {
 c += 4;
 l = scm_ilentab [15 & nn];
 nn >>= 4;
 }
 return SCM_I_MAKINUM (c  4 + l);
 }
+ return SCM_I_MAKINUM (scm_i_inum_length (SCM_I_INUM (n)));
else if (SCM_BIGP (n))
{
/* mpz_sizeinbase looks at the absolute value of negatives, whereas we
@@ 7933,8 +7996,8 @@ SCM_PRIMITIVE_GENERIC (scm_i_divide, "/", 0, 2, 1,
#define s_divide s_scm_i_divide
#define g_divide g_scm_i_divide
static SCM
do_divide (SCM x, SCM y, int inexact)
+SCM
+scm_divide (SCM x, SCM y)
#define FUNC_NAME s_divide
{
double a;
@@ 7953,18 +8016,10 @@ do_divide (SCM x, SCM y, int inexact)
scm_num_overflow (s_divide);
#endif
else
 {
 if (inexact)
 return scm_from_double (1.0 / (double) xx);
 else return scm_i_make_ratio_already_reduced (SCM_INUM1, x);
 }
+ return scm_i_make_ratio_already_reduced (SCM_INUM1, x);
}
else if (SCM_BIGP (x))
 {
 if (inexact)
 return scm_from_double (1.0 / scm_i_big2dbl (x));
 else return scm_i_make_ratio_already_reduced (SCM_INUM1, x);
 }
+ return scm_i_make_ratio_already_reduced (SCM_INUM1, x);
else if (SCM_REALP (x))
{
double xx = SCM_REAL_VALUE (x);
@@ 8014,11 +8069,7 @@ do_divide (SCM x, SCM y, int inexact)
#endif
}
else if (xx % yy != 0)
 {
 if (inexact)
 return scm_from_double ((double) xx / (double) yy);
 else return scm_i_make_ratio (x, y);
 }
+ return scm_i_make_ratio (x, y);
else
{
scm_t_inum z = xx / yy;
@@ 8029,11 +8080,7 @@ do_divide (SCM x, SCM y, int inexact)
}
}
else if (SCM_BIGP (y))
 {
 if (inexact)
 return scm_from_double ((double) xx / scm_i_big2dbl (y));
 else return scm_i_make_ratio (x, y);
 }
+ return scm_i_make_ratio (x, y);
else if (SCM_REALP (y))
{
double yy = SCM_REAL_VALUE (y);
@@ 8090,29 +8137,10 @@ do_divide (SCM x, SCM y, int inexact)
else if (yy == 1)
return x;
else
 {
 if (inexact)
 return scm_from_double (scm_i_big2dbl (x) / (double) yy);
 else return scm_i_make_ratio (x, y);
 }
 }
 else if (SCM_BIGP (y))
 {
 /* big_x / big_y */
 if (inexact)
 {
 /* It's easily possible for the ratio x/y to fit a double
 but one or both x and y be too big to fit a double,
 hence the use of mpq_get_d rather than converting and
 dividing. */
 mpq_t q;
 *mpq_numref(q) = *SCM_I_BIG_MPZ (x);
 *mpq_denref(q) = *SCM_I_BIG_MPZ (y);
 return scm_from_double (mpq_get_d (q));
 }
 else
return scm_i_make_ratio (x, y);
}
+ else if (SCM_BIGP (y))
+ return scm_i_make_ratio (x, y);
else if (SCM_REALP (y))
{
double yy = SCM_REAL_VALUE (y);
@@ 8273,17 +8301,6 @@ do_divide (SCM x, SCM y, int inexact)
else
SCM_WTA_DISPATCH_2 (g_divide, x, y, SCM_ARG1, s_divide);
}

SCM
scm_divide (SCM x, SCM y)
{
 return do_divide (x, y, 0);
}

static SCM scm_divide2real (SCM x, SCM y)
{
 return do_divide (x, y, 1);
}
#undef FUNC_NAME
@@ 9534,12 +9551,11 @@ log_of_fraction (SCM n, SCM d)
log_of_exact_integer (d)));
else if (scm_is_false (scm_negative_p (n)))
return scm_from_double
 (log1p (scm_to_double (scm_divide2real (scm_difference (n, d), d))));
+ (log1p (scm_i_divide2double (scm_difference (n, d), d)));
else
return scm_c_make_rectangular
 (log1p (scm_to_double (scm_divide2real
 (scm_difference (scm_abs (n), d),
 d))),
+ (log1p (scm_i_divide2double (scm_difference (scm_abs (n), d),
+ d)),
M_PI);
}

1.7.2.5
===
From MAILERDAEMON Fri Oct 07 06:09:14 2011
Received: from list by lists.gnu.org with archive (Exim 4.71)
id 1RC7Mg0000dONG
for mharcguiledevel@gnu.org; Fri, 07 Oct 2011 06:09:14 0400
Received: from eggs.gnu.org ([140.186.70.92]:48411)
by lists.gnu.org with esmtp (Exim 4.71)
(envelopefrom ) id 1RC7Me0000bk59
for guiledevel@gnu.org; Fri, 07 Oct 2011 06:09:13 0400
Received: from Debianexim by eggs.gnu.org with spamscanned (Exim 4.71)
(envelopefrom ) id 1RC7MZ0002VqQL
for guiledevel@gnu.org; Fri, 07 Oct 2011 06:09:12 0400
Received: from mailvw0f41.google.com ([209.85.212.41]:33936)
by eggs.gnu.org with esmtp (Exim 4.71)
(envelopefrom ) id 1RC7MZ0002VE2g
for guiledevel@gnu.org; Fri, 07 Oct 2011 06:09:07 0400
Received: by vws16 with SMTP id 16so3702855vws.0
for ; Fri, 07 Oct 2011 03:09:06 0700 (PDT)
DKIMSignature: v=1; a=rsasha256; c=relaxed/relaxed; d=gmail.com; s=gamma;
h=mimeversion:sender:date:xgooglesenderauth:messageid:subject
:from:to:cc:contenttype;
bh=QtMqRmJcnZjmJIzuIyUCQS021tEuZuMXBSG+uOyE7oc=;
b=ktSKjojqmyEupd3c5QNgpu103ltsEZeTABblvznG6IejdNtSGtgZxOUE4Zct1K+lgF
cvwBkQfSVH6Gj4X8IO06G04w07IeMAwvXsWfS6JQlvgNIoncyN0rQZ5GrE2SvxT9LKoD
M2JEksGg6ig6XJVvNHEW4Cy8hcyLT3nwl0xQg=
MIMEVersion: 1.0
Received: by 10.52.91.5 with SMTP id ca5mr1863651vdb.9.1317982145889; Fri, 07
Oct 2011 03:09:05 0700 (PDT)
Sender: mdjurfeldt@gmail.com
Received: by 10.52.162.225 with HTTP; Fri, 7 Oct 2011 03:09:05 0700 (PDT)
Date: Fri, 7 Oct 2011 12:09:05 +0200
XGoogleSenderAuth: 3XEvZI5ezQJBDvoMJsZyP34D5ng
MessageID:
Subject: Benchmarks
From: Mikael Djurfeldt
To: guiledevel
ContentType: text/plain; charset=ISO88591
Xdetectedoperatingsystem: by eggs.gnu.org: GNU/Linux 2.6 (newer, 2)
XReceivedFrom: 209.85.212.41
XBeenThere: guiledevel@gnu.org
XMailmanVersion: 2.1.14
Precedence: list
ListId: "Developers list for Guile,
the GNU extensibility library"
ListUnsubscribe: ,
ListArchive:
ListPost:
ListHelp:
ListSubscribe: ,
XListReceivedDate: Fri, 07 Oct 2011 10:09:13 0000
Dear Guilers,
I just pulled the latest version via git and am amazed about how much
you have achieved during the last years.
Then, today, I stumbled on this:
http://www.cs.utah.edu/~mflatt/benchmarks20100126/log3/Benchmarks.html
Probably Guile now compares better to the other implementations.
Happy hacking!
Mikael
From MAILERDAEMON Fri Oct 07 09:00:17 2011
Received: from list by lists.gnu.org with archive (Exim 4.71)
id 1RCA2D0001fm0S
for mharcguiledevel@gnu.org; Fri, 07 Oct 2011 09:00:17 0400
Received: from eggs.gnu.org ([140.186.70.92]:48001)
by lists.gnu.org with esmtp (Exim 4.71)
(envelopefrom ) id 1RCA2A0001fD8m
for guiledevel@gnu.org; Fri, 07 Oct 2011 09:00:15 0400
Received: from Debianexim by eggs.gnu.org with spamscanned (Exim 4.71)
(envelopefrom ) id 1RCA260003Ub7z
for guiledevel@gnu.org; Fri, 07 Oct 2011 09:00:14 0400
Received: from nm17vm0.bullet.mail.sp2.yahoo.com ([98.139.91.212]:24458)
by eggs.gnu.org with smtp (Exim 4.71)
(envelopefrom ) id 1RCA250003U1Vu
for guiledevel@gnu.org; Fri, 07 Oct 2011 09:00:10 0400
Received: from [98.139.91.70] by nm17.bullet.mail.sp2.yahoo.com with NNFMP;
07 Oct 2011 13:00:08 0000
Received: from [98.139.91.13] by tm10.bullet.mail.sp2.yahoo.com with NNFMP;
07 Oct 2011 13:00:08 0000
Received: from [127.0.0.1] by omp1013.mail.sp2.yahoo.com with NNFMP;
07 Oct 2011 13:00:08 0000
XYahooNewmanProperty: ymail3
XYahooNewmanId: 247095.76151.bm@omp1013.mail.sp2.yahoo.com
Received: (qmail 90802 invoked by uid 60001); 7 Oct 2011 13:00:07 0000
DKIMSignature: v=1; a=rsasha256; c=relaxed/relaxed; d=yahoo.com; s=s1024;
t=1317992407; bh=qng/up7PbXHtx9U/Mj7/WmOxAHTaEHQucsmeyjP+Pzw=;
h=XYMailOSG:Received:XMailer:MessageID:Date:From:ReplyTo:Subject:To:MIMEVersion:ContentType:ContentTransferEncoding;
b=NoPC+2ItG771RZtF7B2HLvqHrmWXhKtXzHQrs0Zw5OZaybCJ6l8960rNuHgGlnr70wQVsmLNMDOXdemBU7IfOfTRUrwkwqeGf/33jmP8Xa37m13aaFWZzqxAOQ1FNtyOGjHsilou2++EURJ9IxrAVXWC8HhWjPEdUkxJWONqyeE=
DomainKeySignature: a=rsasha1; q=dns; c=nofws; s=s1024; d=yahoo.com;
h=XYMailOSG:Received:XMailer:MessageID:Date:From:ReplyTo:Subject:To:MIMEVersion:ContentType:ContentTransferEncoding;
b=BK4K+AeupWG0Q7ftBHA8WaV3XOyw2LhNv5gIX/NPT3mwZPPY5KpZoZFI6zaTSeJynKlnKjq6ovg2BlBhcTdw6d/onYVqBRxtT6b7TiIXcSmy7WK3qArTr04hgkAuK8kly+nPwrAxYXwU6h7c0RdhdSUkOVD/XuGOuAaawFmI89U=;
XYMailOSG: RWENB8AVM1k3AuQ1E1XrsMNv4hukE1xOTFKzL7BVRte5K6Y
j6tfAFSpg4E.HJUd.YDSfYNt7v.qqynPgGo978ULG.RoMRXWtbp6MViLfbEM
J0uLWjOEfr6n_e5Et.xxW4mOZ8SvfCGpyYOCOekC6clPdQAzrfFAWNJ0W7yd
UnnwPZGujcWg9ey6CFd.iEWcohF8biiJCe14.oy4Z5s_vW2We8UhWbiwTcIE
zqcowAwxUBO4Mn3ndUNmRIwQjLMZFaptKEaoCOdV9xUbW3Hi1RiIK7ZtZYkb
hh3c8wB8E2BnTN3GlTyirwgJrlySqJbXaK5z_vKBX0WXyOWT1xNkHkGqh.6a
nrVmQSIEhIRf3txbAEQsB0BuePq4Fx.7og3vOmvdluQrvYwma.WtcvnDfF_S
Jj46n3.wLSF0Y7vX4NFTCfI8z1qQzpE9hVc9X8iDHbR8SkUteh4aLkDMf41c 
Received: from [71.130.221.133] by web37903.mail.mud.yahoo.com via HTTP;
Fri, 07 Oct 2011 06:00:07 PDT
XMailer: YahooMailWebService/0.8.114.317681
MessageID: <1317992407.89760.YahooMailNeo@web37903.mail.mud.yahoo.com>
Date: Fri, 7 Oct 2011 06:00:07 0700 (PDT)
From: Mike Gran
Subject: SCM_ASSERT_TYPE
To: guiledevel
MIMEVersion: 1.0
ContentType: text/plain; charset=iso88591
ContentTransferEncoding: quotedprintable
Xdetectedoperatingsystem: by eggs.gnu.org: Genre and OS details not
recognized.
XReceivedFrom: 98.139.91.212
XBeenThere: guiledevel@gnu.org
XMailmanVersion: 2.1.14
Precedence: list
ReplyTo: Mike Gran
ListId: "Developers list for Guile,
the GNU extensibility library"
ListUnsubscribe: ,
ListArchive:
ListPost:
ListHelp:
ListSubscribe: ,
XListReceivedDate: Fri, 07 Oct 2011 13:00:15 0000
Hello all=0A=0AIs the SCM_ASSERT_TYPE macro considered to be a stable publ=
ic API=0Aor internal to Guile?=A0 It has never been mentioned in the manual=
,=0Abut both Lilypond and GNU Serveez have used it.=0A=0AAnd what about the=
seldomused SCM_ASRTGO?=0A=0A=0AThanks,=0A=0AMike=0A
From MAILERDAEMON Sat Oct 08 17:42:34 2011
Received: from list by lists.gnu.org with archive (Exim 4.71)
id 1RCefC0007507s
for mharcguiledevel@gnu.org; Sat, 08 Oct 2011 17:42:34 0400
Received: from eggs.gnu.org ([140.186.70.92]:49558)
by lists.gnu.org with esmtp (Exim 4.71)
(envelopefrom ) id 1RCefA00074t04
for guiledevel@gnu.org; Sat, 08 Oct 2011 17:42:32 0400
Received: from Debianexim by eggs.gnu.org with spamscanned (Exim 4.71)
(envelopefrom ) id 1RCef90000v54A
for guiledevel@gnu.org; Sat, 08 Oct 2011 17:42:31 0400
Received: from world.peace.net ([96.39.62.75]:36112)
by eggs.gnu.org with esmtp (Exim 4.71)
(envelopefrom ) id 1RCef90000u01s
for guiledevel@gnu.org; Sat, 08 Oct 2011 17:42:31 0400
Received: from c24637323.hsd1.ma.comcast.net ([24.63.73.23]
helo=yeeloong.netris.org) by world.peace.net with esmtpa (Exim 4.69)
(envelopefrom )
id 1RCeen0008OoIP; Sat, 08 Oct 2011 17:42:09 0400
Received: from mhw by yeeloong.netris.org with local (Exim 4.72)
(envelopefrom )
id 1RCeem0000c89O; Sat, 08 Oct 2011 17:42:08 0400
From: Mark H Weaver
To: guiledevel@gnu.org
Subject: Re: [PATCH] Improvements to exact rationals et al
References: <8739f5tlu9.fsf@yeeloong.netris.org>
Date: Sat, 08 Oct 2011 17:42:07 0400
InReplyTo: <8739f5tlu9.fsf@yeeloong.netris.org> (Mark H. Weaver's message of
"Fri, 07 Oct 2011 01:25:02 0400")
MessageID: <874nzjrwi8.fsf@yeeloong.netris.org>
UserAgent: Gnus/5.13 (Gnus v5.13) Emacs/23.3 (gnu/linux)
MIMEVersion: 1.0
ContentType: text/plain; charset=usascii
Xdetectedoperatingsystem: by eggs.gnu.org: GNU/Linux 2.6 (newer, 3)
XReceivedFrom: 96.39.62.75
XBeenThere: guiledevel@gnu.org
XMailmanVersion: 2.1.14
Precedence: list
ListId: "Developers list for Guile,
the GNU extensibility library"
ListUnsubscribe: ,
ListArchive:
ListPost:
ListHelp:
ListSubscribe: ,
XListReceivedDate: Sat, 08 Oct 2011 21:42:32 0000
On second thought, I've decided that this patch set needs a bit more
work before it is ready for submission. I hope to post an improved
version soon.
Mark
From MAILERDAEMON Sat Oct 08 18:00:02 2011
Received: from list by lists.gnu.org with archive (Exim 4.71)
id 1RCew60000ZlNF
for mharcguiledevel@gnu.org; Sat, 08 Oct 2011 18:00:02 0400
Received: from eggs.gnu.org ([140.186.70.92]:59228)
by lists.gnu.org with esmtp (Exim 4.71)
(envelopefrom ) id 1RCew40000ZYEr
for guiledevel@gnu.org; Sat, 08 Oct 2011 18:00:01 0400
Received: from Debianexim by eggs.gnu.org with spamscanned (Exim 4.71)
(envelopefrom ) id 1RCew30003XQIK
for guiledevel@gnu.org; Sat, 08 Oct 2011 18:00:00 0400
Received: from lo.gmane.org ([80.91.229.12]:51208)
by eggs.gnu.org with esmtp (Exim 4.71)
(envelopefrom ) id 1RCew30003X7DI
for guiledevel@gnu.org; Sat, 08 Oct 2011 17:59:59 0400
Received: from list by lo.gmane.org with local (Exim 4.69)
(envelopefrom ) id 1RCevz0004pkBN
for guiledevel@gnu.org; Sat, 08 Oct 2011 23:59:55 +0200
Received: from reverse83.fdn.fr ([80.67.176.83])
by main.gmane.org with esmtp (Gmexim 0.1 (Debian))
id 1AlnuQ0007hv00
for ; Sat, 08 Oct 2011 23:59:55 +0200
Received: from ludo by reverse83.fdn.fr with local (Gmexim 0.1 (Debian))
id 1AlnuQ0007hv00
for ; Sat, 08 Oct 2011 23:59:55 +0200
XInjectedViaGmane: http://gmane.org/
To: guiledevel@gnu.org
From: ludo@gnu.org (Ludovic =?iso88591?Q?Court=E8s?=)
Subject: Re: gettext #" reader macro?
Date: Sat, 08 Oct 2011 23:59:42 +0200
Lines: 15
MessageID: <87d3e76t69.fsf@gnu.org>
References:
MimeVersion: 1.0
ContentType: text/plain; charset=utf8
ContentTransferEncoding: 8bit
XComplaintsTo: usenet@dough.gmane.org
XGmaneNNTPPostingHost: reverse83.fdn.fr
XURL: http://www.fdn.fr/~lcourtes/
XRevolutionaryDate: 17 =?iso88591?Q?Vend=E9miaire?= an 220 de la
=?iso88591?Q?R=E9volution?=
XPGPKeyID: 0xEA52ECF4
XPGPKey: http://www.fdn.fr/~lcourtes/ludovic.asc
XPGPFingerprint: 83C4 F8E5 10A3 3B4C 5BEA D15D 77DD 95E2 EA52 ECF4
XOS: x86_64unknownlinuxgnu
UserAgent: Gnus/5.110018 (No Gnus v0.18) Emacs/24.0.90 (gnu/linux)
CancelLock: sha1:EQ8DI46I8YJVz7cEJiFm//NOhjs=
Xdetectedoperatingsystem: by eggs.gnu.org: GNU/Linux 2.6 (newer, 3)
XReceivedFrom: 80.91.229.12
XBeenThere: guiledevel@gnu.org
XMailmanVersion: 2.1.14
Precedence: list
ListId: "Developers list for Guile,
the GNU extensibility library"
ListUnsubscribe: ,
ListArchive:
ListPost:
ListHelp:
ListSubscribe: ,
XListReceivedDate: Sat, 08 Oct 2011 22:00:01 0000
Hi,
Tobias Gerdin skribis:
> For convenient use doing something like (define _ gettext) is
> recommended. The #"text" syntax that the above page proposes is more
> concise and in my opinion quite nice, so I did the below and stuck it
> in boot9.scm:
I find (_ "text") just as concise and more likely to be directly
understood since _ is an alias for the ‘gettext’ function in most
languages, and the one used by default when running ‘gettextize’.
Thanks,
Ludo’.
From MAILERDAEMON Sat Oct 08 18:05:17 2011
Received: from list by lists.gnu.org with archive (Exim 4.71)
id 1RCf1B00014qAB
for mharcguiledevel@gnu.org; Sat, 08 Oct 2011 18:05:17 0400
Received: from eggs.gnu.org ([140.186.70.92]:54016)
by lists.gnu.org with esmtp (Exim 4.71)
(envelopefrom ) id 1RCf1800014iQC
for guiledevel@gnu.org; Sat, 08 Oct 2011 18:05:15 0400
Received: from Debianexim by eggs.gnu.org with spamscanned (Exim 4.71)
(envelopefrom ) id 1RCf170004e5Lp
for guiledevel@gnu.org; Sat, 08 Oct 2011 18:05:14 0400
Received: from lo.gmane.org ([80.91.229.12]:41743)
by eggs.gnu.org with esmtp (Exim 4.71)
(envelopefrom ) id 1RCf170004dvFS
for guiledevel@gnu.org; Sat, 08 Oct 2011 18:05:13 0400
Received: from list by lo.gmane.org with local (Exim 4.69)
(envelopefrom ) id 1RCf160006XDAN
for guiledevel@gnu.org; Sun, 09 Oct 2011 00:05:12 +0200
Received: from reverse83.fdn.fr ([80.67.176.83])
by main.gmane.org with esmtp (Gmexim 0.1 (Debian))
id 1AlnuQ0007hv00
for ; Sun, 09 Oct 2011 00:05:12 +0200
Received: from ludo by reverse83.fdn.fr with local (Gmexim 0.1 (Debian))
id 1AlnuQ0007hv00
for ; Sun, 09 Oct 2011 00:05:12 +0200
XInjectedViaGmane: http://gmane.org/
To: guiledevel@gnu.org
From: ludo@gnu.org (Ludovic =?iso88591?Q?Court=E8s?=)
Subject: Re: SCM_ASSERT_TYPE
Date: Sun, 09 Oct 2011 00:04:03 +0200
Lines: 17
MessageID: <8739f36sz0.fsf@gnu.org>
References: <1317992407.89760.YahooMailNeo@web37903.mail.mud.yahoo.com>
MimeVersion: 1.0
ContentType: text/plain; charset=utf8
ContentTransferEncoding: 8bit
XComplaintsTo: usenet@dough.gmane.org
XGmaneNNTPPostingHost: reverse83.fdn.fr
XURL: http://www.fdn.fr/~lcourtes/
XRevolutionaryDate: 18 =?iso88591?Q?Vend=E9miaire?= an 220 de la
=?iso88591?Q?R=E9volution?=
XPGPKeyID: 0xEA52ECF4
XPGPKey: http://www.fdn.fr/~lcourtes/ludovic.asc
XPGPFingerprint: 83C4 F8E5 10A3 3B4C 5BEA D15D 77DD 95E2 EA52 ECF4
XOS: x86_64unknownlinuxgnu
UserAgent: Gnus/5.110018 (No Gnus v0.18) Emacs/24.0.90 (gnu/linux)
CancelLock: sha1:brgxIFYlvybNY9J9Nn1T8PH9Nw4=
Xdetectedoperatingsystem: by eggs.gnu.org: GNU/Linux 2.6 (newer, 3)
XReceivedFrom: 80.91.229.12
XBeenThere: guiledevel@gnu.org
XMailmanVersion: 2.1.14
Precedence: list
ListId: "Developers list for Guile,
the GNU extensibility library"
ListUnsubscribe: ,
ListArchive:
ListPost:
ListHelp:
ListSubscribe: ,
XListReceivedDate: Sat, 08 Oct 2011 22:05:15 0000
Hi,
Mike Gran skribis:
> Is the SCM_ASSERT_TYPE macro considered to be a stable public API
> or internal to Guile? It has never been mentioned in the manual,
> but both Lilypond and GNU Serveez have used it.
Then I think it’s defacto public and the fix should be to document it.
Would you like to do it? :)
> And what about the seldomused SCM_ASRTGO?
Likewise (Google Codesearch finds a couple of external users.)
Thanks,
Ludo’.
From MAILERDAEMON Sat Oct 08 21:35:54 2011
Received: from list by lists.gnu.org with archive (Exim 4.71)
id 1RCiJ00006SY5z
for mharcguiledevel@gnu.org; Sat, 08 Oct 2011 21:35:54 0400
Received: from eggs.gnu.org ([140.186.70.92]:49968)
by lists.gnu.org with esmtp (Exim 4.71)
(envelopefrom ) id 1RCiIx0006Qv14
for guiledevel@gnu.org; Sat, 08 Oct 2011 21:35:52 0400
Received: from Debianexim by eggs.gnu.org with spamscanned (Exim 4.71)
(envelopefrom ) id 1RCiIv0005AHSc
for guiledevel@gnu.org; Sat, 08 Oct 2011 21:35:51 0400
Received: from mailiy0f169.google.com ([209.85.210.169]:54634)
by eggs.gnu.org with esmtp (Exim 4.71)
(envelopefrom ) id 1RCiIv0005A8Pb
for guiledevel@gnu.org; Sat, 08 Oct 2011 21:35:49 0400
Received: by iaen33 with SMTP id n33so7757227iae.0
for ; Sat, 08 Oct 2011 18:35:48 0700 (PDT)
DKIMSignature: v=1; a=rsasha256; c=relaxed/relaxed; d=gmail.com; s=gamma;
h=mimeversion:sender:date:xgooglesenderauth:messageid:subject
:from:to:contenttype;
bh=2Xg4eS9f+CH6K6ZBNF8B/8cEsTvq5xK6CZwD4IjHxAY=;
b=AeCEWixhmtwOvmX9leYMATIQ09ga7Og/fskn4Ws15egXJYwIm+w/KV7fi6hfr3m0K8
60TkU7I6uzfrkm4iLLN+SMS2KTpek+XT61YsvAVMmDEJ2IFxZqXn4LKMAd76z0lhpWpS
dI7E5KwS0250Nd7k6U7zzdOgt7q2+kI3v9HoQ=
MIMEVersion: 1.0
Received: by 10.42.117.193 with SMTP id u1mr6744539icq.24.1318124148827; Sat,
08 Oct 2011 18:35:48 0700 (PDT)
Sender: noah549@gmail.com
Received: by 10.42.180.1 with HTTP; Sat, 8 Oct 2011 18:35:48 0700 (PDT)
Date: Sat, 8 Oct 2011 21:35:48 0400
XGoogleSenderAuth: O5_tJJqb5wHItiDtS2NwcpUo0zY
MessageID:
Subject: ELisp?
From: Noah Lavine
To: guiledevel
ContentType: text/plain; charset=ISO88591
Xdetectedoperatingsystem: by eggs.gnu.org: GNU/Linux 2.6 (newer, 2)
XReceivedFrom: 209.85.210.169
XBeenThere: guiledevel@gnu.org
XMailmanVersion: 2.1.14
Precedence: list
ListId: "Developers list for Guile,
the GNU extensibility library"
ListUnsubscribe: ,
ListArchive:
ListPost:
ListHelp:
ListSubscribe: ,
XListReceivedDate: Sun, 09 Oct 2011 01:35:52 0000
Hello all,
Could anyone tell me the status of the ELisp implementation since July
21st (the last update)?
I'm especially interested now because of a thread on emacsdevel 
http://lists.gnu.org/archive/html/emacsdevel/201109/msg00753.html.
People were talking about adding multithreading to Emacs. Some people
said that moving Emacs to Guile might be the best solution, but others
were pessimistic about that ever happening. It looks like the Emacs
people would really like to use Guile, and we would certainly like
them to. Also, every time Emacs implements a feature that Guile
already has, it's wasted effort when we eventually integrate them.
It seems like EmacsGuile integration is a project that is on the
verge of happening, and just needs some sort of push to get it over
the hump. I hope that this summer's SoC work can be the impetus.
Noah
From MAILERDAEMON Sun Oct 09 09:38:00 2011
Received: from list by lists.gnu.org with archive (Exim 4.71)
id 1RCtZo0007uqT8
for mharcguiledevel@gnu.org; Sun, 09 Oct 2011 09:38:00 0400
Received: from eggs.gnu.org ([140.186.70.92]:45053)
by lists.gnu.org with esmtp (Exim 4.71)
(envelopefrom ) id 1RCtZm0007ukMJ
for guiledevel@gnu.org; Sun, 09 Oct 2011 09:37:59 0400
Received: from Debianexim by eggs.gnu.org with spamscanned (Exim 4.71)
(envelopefrom ) id 1RCtZl0006iWHf
for guiledevel@gnu.org; Sun, 09 Oct 2011 09:37:58 0400
Received: from lo.gmane.org ([80.91.229.12]:57597)
by eggs.gnu.org with esmtp (Exim 4.71)
(envelopefrom ) id 1RCtZl0006iI6u
for guiledevel@gnu.org; Sun, 09 Oct 2011 09:37:57 0400
Received: from list by lo.gmane.org with local (Exim 4.69)
(envelopefrom ) id 1RCtZi00080RBZ
for guiledevel@gnu.org; Sun, 09 Oct 2011 15:37:54 +0200
Received: from h235102.a149.priv.bahnhof.se ([85.24.235.102])
by main.gmane.org with esmtp (Gmexim 0.1 (Debian))
id 1AlnuQ0007hv00
for ; Sun, 09 Oct 2011 15:37:54 +0200
Received: from joakim by h235102.a149.priv.bahnhof.se with local (Gmexim 0.1
(Debian)) id 1AlnuQ0007hv00
for ; Sun, 09 Oct 2011 15:37:54 +0200
XInjectedViaGmane: http://gmane.org/
To: guiledevel@gnu.org
From: joakim@verona.se
Subject: Re: ELisp?
Date: Sun, 09 Oct 2011 15:37:42 +0200
Lines: 64
MessageID:
References:
MimeVersion: 1.0
ContentType: text/plain
XComplaintsTo: usenet@dough.gmane.org
XGmaneNNTPPostingHost: h235102.a149.priv.bahnhof.se
UserAgent: Gnus/5.13 (Gnus v5.13) Emacs/24.0.90 (gnu/linux)
CancelLock: sha1:rVDQQpEcLlvzcfNXFxjf6id+SCo=
Xdetectedoperatingsystem: by eggs.gnu.org: GNU/Linux 2.6 (newer, 3)
XReceivedFrom: 80.91.229.12
XBeenThere: guiledevel@gnu.org
XMailmanVersion: 2.1.14
Precedence: list
ListId: "Developers list for Guile,
the GNU extensibility library"
ListUnsubscribe: ,
ListArchive:
ListPost:
ListHelp:
ListSubscribe: ,
XListReceivedDate: Sun, 09 Oct 2011 13:37:59 0000
Noah Lavine writes:
> Hello all,
>
> Could anyone tell me the status of the ELisp implementation since July
> 21st (the last update)?
>
> I'm especially interested now because of a thread on emacsdevel 
> http://lists.gnu.org/archive/html/emacsdevel/201109/msg00753.html.People were talking about adding multithreading to Emacs. Some people
> said that moving Emacs to Guile might be the best solution, but others
> were pessimistic about that ever happening. It looks like the Emacs
> people would really like to use Guile, and we would certainly like
> them to. Also, every time Emacs implements a feature that Guile
> already has, it's wasted effort when we eventually integrate them.
>
> It seems like EmacsGuile integration is a project that is on the
> verge of happening, and just needs some sort of push to get it over
> the hump. I hope that this summer's SoC work can be the impetus.
>
> Noah
>
>
I'm an Emacs developer(not the most prolific but I have contributed
ImageMagick core integration and Webkit integration for Emacs 25)
I'm now trying to learn nontrivial Guile usage so as to be useful in
the future merge of Guile and Emacs.
Currently, for me coming from the Emacs side is that I have no idea how
integration would happen. I've studied the various attempts but haven't
come to any conclusion.
My naive approach would be to make an Emacs Guile branch on
Savannah. The branch would unify incrementally the 3 different existing
approaches:
 Nishidas patches to run Guile in Emacs
 Ken Raeburns patches to replace the Emacs Lisp engine
 Templetons implementation of Elisp in Guile
This branch would initially use Nishidas strategy of just linking Guile
and providing some simple interoperability functions. The version linked
would be Templetons Elisp Guile version. So, there would be 2 lisp
engines in Emacs for a while. When things work well the old Emacs lisp
engine would be ripped out.
As I'm coming from the Emacs side of things my interest is in getting
Guile in the Emacs core efficiently. My motivation is somewhat selfish
because I don't want to reimplement all the interesting features Guile
has in Emacs, such as dynamic FFI etc..
Of course there are many details to work out. A random example could
be that we would like a cookie to indicate that evalbuffer should use
guile rather than elisp for a buffer.
The advantage of the above approach is that it is incremental. We gain
exposure in the Emacs developer community. Since Emacs 24 is entering
pretest its a good time to start to think of features for Emacs 25.

Joakim Verona
From MAILERDAEMON Sun Oct 09 12:16:45 2011
Received: from list by lists.gnu.org with archive (Exim 4.71)
id 1RCw3R0006QaA5
for mharcguiledevel@gnu.org; Sun, 09 Oct 2011 12:16:45 0400
Received: from eggs.gnu.org ([140.186.70.92]:57841)
by lists.gnu.org with esmtp (Exim 4.71)
(envelopefrom ) id 1RCw3O0006OVPr
for guiledevel@gnu.org; Sun, 09 Oct 2011 12:16:43 0400
Received: from Debianexim by eggs.gnu.org with spamscanned (Exim 4.71)
(envelopefrom ) id 1RCw3O0002C754
for guiledevel@gnu.org; Sun, 09 Oct 2011 12:16:42 0400
Received: from nm18vm0.bullet.mail.ac4.yahoo.com ([98.139.53.210]:35507)
by eggs.gnu.org with smtp (Exim 4.71)
(envelopefrom ) id 1RCw3N0002BxW3
for guiledevel@gnu.org; Sun, 09 Oct 2011 12:16:42 0400
Received: from [98.139.52.189] by nm18.bullet.mail.ac4.yahoo.com with NNFMP;
09 Oct 2011 16:16:40 0000
Received: from [98.139.52.157] by tm2.bullet.mail.ac4.yahoo.com with NNFMP;
09 Oct 2011 16:16:40 0000
Received: from [127.0.0.1] by omp1040.mail.ac4.yahoo.com with NNFMP;
09 Oct 2011 16:16:40 0000
XYahooNewmanProperty: ymail3
XYahooNewmanId: 931272.71417.bm@omp1040.mail.ac4.yahoo.com
Received: (qmail 66533 invoked by uid 60001); 9 Oct 2011 16:16:40 0000
DKIMSignature: v=1; a=rsasha256; c=relaxed/relaxed; d=yahoo.com; s=s1024;
t=1318177000; bh=PZ1DwfO3nKIVKfQBVWvDwYzruKyP5IwsIPzuufQWu08=;
h=XYMailOSG:Received:XMailer:MessageID:Date:From:ReplyTo:Subject:To:MIMEVersion:ContentType;
b=UL9urMWz3yMSYjzr4c5f9bW+gpgFxZJRRizOffM+idbCl3wC+rdudTdUISKK+R3dQmO5SG3rOSaGc8ph7r64WbK5rMu+EctIqWJLpXsg39uvJYP8N8YoPiIfFixBvSwTafuSvwNEv7EUx02a9lf8oqyIJxx41Sb8e+k7wfqsPA0=
DomainKeySignature: a=rsasha1; q=dns; c=nofws; s=s1024; d=yahoo.com;
h=XYMailOSG:Received:XMailer:MessageID:Date:From:ReplyTo:Subject:To:MIMEVersion:ContentType;
b=vG9Wd5vcI+LAz152ahcl2pv8IXFbYHNEZ5Nkdb2LRnlp0gqN0BDSCfXX3b53mEe8VZlzvdCgCGmhiAcG2beMvRCMq0VVZNkC8rJ3rzPT9h2KALATA1vQixZoSpAdTtH1cGqltNivXnVMy/sdhqNYCRMoq52ix1CUHQP2dYPbZ0M=;
XYMailOSG: s7S.cYsVM1n1cbFGU57r65PsHx8xCkCvyBIipeYfI64PVO5
RRV_85RWrj2i8t2fFnymiD6hMJLEazIcCZKdD050pjiWMVBe91uwd_ot8pmT
YSVaru9fP3DebR3UCeaEjBk8G3Uj5QwJIUcFguX.O_APCv2bu.Jnvo70wpW9
VILKvFsze7wVkz4Vh6Z59tgy_2SXqZ8pSGTGZRsDdGJBdVFvBj9aVjhc30Lv
MsXbs3qATaFcNN1mL2TiVjKB5ko.l4.6CIthlcQR0D2pGHd3Q6zN4IV4MTkP
qJtrsfRMKqn_Wai.4HGAOydku.2uB3ykda8qN.d4t_IhK5ocbVsXOnWWlUxa
xegLhKDXIIhaoH_D6sVohTXMf4VfgDmI7UFN__ig.x_MX8299Z5u7rbk6EEQ
xmHtjJYLsR.G_pPZ4AOL3xuxhKnQe9TWmTAidwgSW1hnbKdITthTo6UutYA 
Received: from [71.130.221.133] by web37903.mail.mud.yahoo.com via HTTP;
Sun, 09 Oct 2011 09:16:40 PDT
XMailer: YahooMailWebService/0.8.114.317681
MessageID: <1318177000.15831.YahooMailNeo@web37903.mail.mud.yahoo.com>
Date: Sun, 9 Oct 2011 09:16:40 0700 (PDT)
From: Mike Gran
Subject: scm_is_exact, scm_is_inexact
To: guiledevel
MIMEVersion: 1.0
ContentType: text/plain; charset=usascii
Xdetectedoperatingsystem: by eggs.gnu.org: Genre and OS details not
recognized.
XReceivedFrom: 98.139.53.210
XBeenThere: guiledevel@gnu.org
XMailmanVersion: 2.1.14
Precedence: list
ReplyTo: Mike Gran
ListId: "Developers list for Guile,
the GNU extensibility library"
ListUnsubscribe: ,
ListArchive:
ListPost:
ListHelp:
ListSubscribe: ,
XListReceivedDate: Sun, 09 Oct 2011 16:16:43 0000
Hi
Would it be okay for me to add scm_is_exact and scm_is_inexact
C functions as companions to the existing scm_exact_p and
scm_inexact_p?
If so, which branch?
Mike
From MAILERDAEMON Sun Oct 09 15:22:41 2011
Received: from list by lists.gnu.org with archive (Exim 4.71)
id 1RCyxN0003euFn
for mharcguiledevel@gnu.org; Sun, 09 Oct 2011 15:22:41 0400
Received: from eggs.gnu.org ([140.186.70.92]:46769)
by lists.gnu.org with esmtp (Exim 4.71)
(envelopefrom ) id 1RCyxK0003eoRh
for guiledevel@gnu.org; Sun, 09 Oct 2011 15:22:40 0400
Received: from Debianexim by eggs.gnu.org with spamscanned (Exim 4.71)
(envelopefrom ) id 1RCyxJ0006VzAv
for guiledevel@gnu.org; Sun, 09 Oct 2011 15:22:38 0400
Received: from mailiy0f169.google.com ([209.85.210.169]:51519)
by eggs.gnu.org with esmtp (Exim 4.71)
(envelopefrom ) id 1RCyxJ0006Vt6Y
for guiledevel@gnu.org; Sun, 09 Oct 2011 15:22:37 0400
Received: by iaen33 with SMTP id n33so8701015iae.0
for ; Sun, 09 Oct 2011 12:22:36 0700 (PDT)
DKIMSignature: v=1; a=rsasha256; c=relaxed/relaxed; d=gmail.com; s=gamma;
h=mimeversion:sender:inreplyto:references:date
:xgooglesenderauth:messageid:subject:from:to:cc:contenttype
:contenttransferencoding;
bh=/Miz2+trouzi3aHfInHKHGECNBIL0jCMt97ll9wnD0k=;
b=Wx8MlXBfAL8XP5xJdmNCoRdCSTHtWZJoLMvRQdKDL0dfDcxhAuHLaKugxtghmHbRAG
K/rfT9pt+hmDfUfoDYggbibASLFUvo8SE9UoRqG0YWP3WU/IALQA6pKsCzrvw1vkn4U9
QSLQuCD3TOyI6J+E/N4s4j+3eYdmYCSBUaZns=
MIMEVersion: 1.0
Received: by 10.42.154.7 with SMTP id o7mr11444978icw.48.1318188156308; Sun,
09 Oct 2011 12:22:36 0700 (PDT)
Sender: noah549@gmail.com
Received: by 10.42.180.1 with HTTP; Sun, 9 Oct 2011 12:22:36 0700 (PDT)
InReplyTo:
References:
Date: Sun, 9 Oct 2011 15:22:36 0400
XGoogleSenderAuth: fEMcsTgZjgwwBwhQCDFb6PR7GBk
MessageID:
Subject: Re: ELisp?
From: Noah Lavine
To: joakim@verona.se
ContentType: text/plain; charset=ISO88591
ContentTransferEncoding: quotedprintable
Xdetectedoperatingsystem: by eggs.gnu.org: GNU/Linux 2.6 (newer, 2)
XReceivedFrom: 209.85.210.169
Cc: guiledevel@gnu.org
XBeenThere: guiledevel@gnu.org
XMailmanVersion: 2.1.14
Precedence: list
ListId: "Developers list for Guile,
the GNU extensibility library"
ListUnsubscribe: ,
ListArchive:
ListPost:
ListHelp:
ListSubscribe: ,
XListReceivedDate: Sun, 09 Oct 2011 19:22:41 0000
That makes sense. I was hoping we could skip the phase where we have
two lisp interpreters around, if Guile's ELisp implementation was good
enough, but maybe that will not be possible. Emacs already does
something similar to this for the programming language modes, where it
has another interpreter as a subprocess, so this doesn't sound so bad
technically.
One question I have is, how much of Emacs' C code can Guile use right
now? I guess Ken Raeburn's patches are the ones that address that, but
I don't know what is left to do.
(I also have the same question about ELisp  what of the language is
left to implement? Is it just adding more builtins?)
I don't know if this would work, but the way I was imagining it
happening is really just starting up Guile and loading Emacs source
files, one by one. If we have a complete ELisp implementation with all
of Emacs' C code, then in theory Emacs would start. I don't know what
would actually happen though.
A branch on Savannah sounds like a really good idea though. Then at
least there would be a central thing for people to look at and hack
on, and more people might get involved. Right now I suspect that most
people don't know what's happening or where to look. If you set up a
branch, I for one would love to check it out and perhaps contribute
some patches. Do you need permission from the Emacs maintainers to do
that, or anything else?
Noah
On Sun, Oct 9, 2011 at 9:37 AM, wrote:
> Noah Lavine writes:
>
>> Hello all,
>>
>> Could anyone tell me the status of the ELisp implementation since July
>> 21st (the last update)?
>>
>> I'm especially interested now because of a thread on emacsdevel 
>> http://lists.gnu.org/archive/html/emacsdevel/201109/msg00753.html.Peop=
le were talking about adding multithreading to Emacs. Some people
>> said that moving Emacs to Guile might be the best solution, but others
>> were pessimistic about that ever happening. It looks like the Emacs
>> people would really like to use Guile, and we would certainly like
>> them to. Also, every time Emacs implements a feature that Guile
>> already has, it's wasted effort when we eventually integrate them.
>>
>> It seems like EmacsGuile integration is a project that is on the
>> verge of happening, and just needs some sort of push to get it over
>> the hump. I hope that this summer's SoC work can be the impetus.
>>
>> Noah
>>
>>
>
> I'm an Emacs developer(not the most prolific but I have contributed
> ImageMagick core integration and Webkit integration for Emacs 25)
>
> I'm now trying to learn nontrivial Guile usage so as to be useful in
> the future merge of Guile and Emacs.
>
> Currently, for me coming from the Emacs side is that I have no idea how
> integration would happen. I've studied the various attempts but haven't
> come to any conclusion.
>
> My naive approach would be to make an Emacs Guile branch on
> Savannah. The branch would unify incrementally the 3 different existing
> approaches:
>
> =A0 Nishidas patches to run Guile in Emacs
> =A0 Ken Raeburns patches to replace the Emacs Lisp engine
> =A0 Templetons implementation of Elisp in Guile
>
> This branch would initially use Nishidas strategy of just linking Guile
> and providing some simple interoperability functions. The version linked
> would be Templetons Elisp Guile version. So, there would be 2 lisp
> engines in Emacs for a while. When things work well the old Emacs lisp
> engine would be ripped out.
>
> As I'm coming from the Emacs side of things my interest is in getting
> Guile in the Emacs core efficiently. My motivation is somewhat selfish
> because I don't want to reimplement all the interesting features Guile
> has in Emacs, such as dynamic FFI etc..
>
> Of course there are many details to work out. A random example could
> be that we would like a cookie to indicate that evalbuffer should use
> guile rather than elisp for a buffer.
>
> The advantage of the above approach is that it is incremental. We gain
> exposure in the Emacs developer community. Since Emacs 24 is entering
> pretest its a good time to start to think of features for Emacs 25.
>
>
>
> 
> Joakim Verona
>
>
>
From MAILERDAEMON Sun Oct 09 16:37:42 2011
Received: from list by lists.gnu.org with archive (Exim 4.71)
id 1RD07y0008677o
for mharcguiledevel@gnu.org; Sun, 09 Oct 2011 16:37:42 0400
Received: from eggs.gnu.org ([140.186.70.92]:42968)
by lists.gnu.org with esmtp (Exim 4.71)
(envelopefrom ) id 1RD07w000861Ji
for guiledevel@gnu.org; Sun, 09 Oct 2011 16:37:41 0400
Received: from Debianexim by eggs.gnu.org with spamscanned (Exim 4.71)
(envelopefrom ) id 1RD07v0005JxOW
for guiledevel@gnu.org; Sun, 09 Oct 2011 16:37:40 0400
Received: from lo.gmane.org ([80.91.229.12]:55331)
by eggs.gnu.org with esmtp (Exim 4.71)
(envelopefrom ) id 1RD07v0005JrFo
for guiledevel@gnu.org; Sun, 09 Oct 2011 16:37:39 0400
Received: from list by lo.gmane.org with local (Exim 4.69)
(envelopefrom ) id 1RD07r00005i93
for guiledevel@gnu.org; Sun, 09 Oct 2011 22:37:35 +0200
Received: from reverse83.fdn.fr ([80.67.176.83])
by main.gmane.org with esmtp (Gmexim 0.1 (Debian))
id 1AlnuQ0007hv00
for ; Sun, 09 Oct 2011 22:37:35 +0200
Received: from ludo by reverse83.fdn.fr with local (Gmexim 0.1 (Debian))
id 1AlnuQ0007hv00
for ; Sun, 09 Oct 2011 22:37:35 +0200
XInjectedViaGmane: http://gmane.org/
To: guiledevel@gnu.org
From: ludo@gnu.org (Ludovic =?iso88591?Q?Court=E8s?=)
Subject: Re: scm_is_exact, scm_is_inexact
Date: Sun, 09 Oct 2011 22:37:21 +0200
Lines: 18
MessageID: <87wrcd6gvy.fsf@gnu.org>
References: <1318177000.15831.YahooMailNeo@web37903.mail.mud.yahoo.com>
MimeVersion: 1.0
ContentType: text/plain; charset=utf8
ContentTransferEncoding: 8bit
XComplaintsTo: usenet@dough.gmane.org
XGmaneNNTPPostingHost: reverse83.fdn.fr
XURL: http://www.fdn.fr/~lcourtes/
XRevolutionaryDate: 18 =?iso88591?Q?Vend=E9miaire?= an 220 de la
=?iso88591?Q?R=E9volution?=
XPGPKeyID: 0xEA52ECF4
XPGPKey: http://www.fdn.fr/~lcourtes/ludovic.asc
XPGPFingerprint: 83C4 F8E5 10A3 3B4C 5BEA D15D 77DD 95E2 EA52 ECF4
XOS: x86_64unknownlinuxgnu
UserAgent: Gnus/5.110018 (No Gnus v0.18) Emacs/24.0.90 (gnu/linux)
CancelLock: sha1:txCjsRP0H7wcE4ALXTuCC5fFONg=
Xdetectedoperatingsystem: by eggs.gnu.org: GNU/Linux 2.6 (newer, 3)
XReceivedFrom: 80.91.229.12
XBeenThere: guiledevel@gnu.org
XMailmanVersion: 2.1.14
Precedence: list
ListId: "Developers list for Guile,
the GNU extensibility library"
ListUnsubscribe: ,
ListArchive:
ListPost:
ListHelp:
ListSubscribe: ,
XListReceivedDate: Sun, 09 Oct 2011 20:37:41 0000
Hi Mike,
Mike Gran skribis:
> Would it be okay for me to add scm_is_exact and scm_is_inexact
> C functions as companions to the existing scm_exact_p and
>
> scm_inexact_p?
Yes.
> If so, which branch?
2.0 is OK.
Thanks, and thanks for the doc patch you committed too!
Ludo’.
From MAILERDAEMON Mon Oct 10 10:49:50 2011
Received: from list by lists.gnu.org with archive (Exim 4.71)
id 1RDHAs0002GwNO
for mharcguiledevel@gnu.org; Mon, 10 Oct 2011 10:49:50 0400
Received: from eggs.gnu.org ([140.186.70.92]:50112)
by lists.gnu.org with esmtp (Exim 4.71)
(envelopefrom ) id 1RDHAp0002EIQV
for guiledevel@gnu.org; Mon, 10 Oct 2011 10:49:48 0400
Received: from Debianexim by eggs.gnu.org with spamscanned (Exim 4.71)
(envelopefrom ) id 1RDHAo0007fXEF
for guiledevel@gnu.org; Mon, 10 Oct 2011 10:49:47 0400
Received: from apbsaslsd.pobox.com ([74.115.168.62]:35512
helo=sasl.smtp.pobox.com) by eggs.gnu.org with esmtp (Exim 4.71)
(envelopefrom ) id 1RDHAo0007QaBd
for guiledevel@gnu.org; Mon, 10 Oct 2011 10:49:46 0400
Received: from sasl.smtp.pobox.com (unknown [127.0.0.1])
by apbsaslsd.pobox.com (Postfix) with ESMTP id 784C2740F
for ; Mon, 10 Oct 2011 10:49:14 0400 (EDT)
DKIMSignature: v=1; a=rsasha1; c=relaxed; d=pobox.com; h=from:to
:subject:date:messageid:mimeversion:contenttype; s=sasl; bh=5
vCDeW9EACD8ffPx/nwt0RDd42k=; b=To4bK2+KqRGjAHeLQ0EAG4BZbIJe7EPfr
f8kAQIi6lxIHSjaZY+aFAoDi+Z23pcRosV4P8+kVlAaWyN2hHZFSx8EEFG5kDjap
HM3vaK371kwwEtyLz4xKor/y3XBpWZf+2io8a5XdmihgM7QYXpNxMs8h3jutoGf8
M5ibo5NPdA=
DomainKeySignature: a=rsasha1; c=nofws; d=pobox.com; h=from:to:subject
:date:messageid:mimeversion:contenttype; q=dns; s=sasl; b=rEL
7iRU+z64KrVoVkmCJT2ioWv8sg059sTN27evSaPUQe2ZsCf1Sv46VWJ0tpcFoofQ
5fNROh16iM7JRtI9NR9Gk5N1LlhphvxZT8CZQq98xPrnvY/r0/gE1PpXHNL/ut39
TPYMYVghUUlSLKQ8iR4MQ7GEAXDvRrwvJGwuMiFM=
Received: from apbsaslsd.pobox.com (unknown [127.0.0.1])
by apbsaslsd.pobox.com (Postfix) with ESMTP id 7059C740E
for ; Mon, 10 Oct 2011 10:49:14 0400 (EDT)
Received: from badger (unknown [90.164.198.39]) (using TLSv1 with cipher
DHERSAAES256SHA (256/256 bits)) (No client certificate requested) by
apbsaslsd.pobox.com (Postfix) with ESMTPSA id E4553740D for
; Mon, 10 Oct 2011 10:49:13 0400 (EDT)
From: Andy Wingo
To: guiledevel
Subject: peval again
Date: Mon, 10 Oct 2011 16:49:11 +0200
MessageID: <8762jwuck8.fsf@pobox.com>
UserAgent: Gnus/5.13 (Gnus v5.13) Emacs/23.3 (gnu/linux)
MIMEVersion: 1.0
ContentType: text/plain; charset=usascii
XPoboxRelayID: 05772A66F34F11E0951265B1DE99592402397024!apbsaslsd.pobox.com
Xdetectedoperatingsystem: by eggs.gnu.org: Solaris 10 (beta)
XReceivedFrom: 74.115.168.62
XBeenThere: guiledevel@gnu.org
XMailmanVersion: 2.1.14
Precedence: list
ListId: "Developers list for Guile,
the GNU extensibility library"
ListUnsubscribe: ,
ListArchive:
ListPost:
ListHelp:
ListSubscribe: ,
XListReceivedDate: Mon, 10 Oct 2011 14:49:48 0000
Hi all,
I have pushed some work to stable2.0 and master that fixes some peval
bugs, while also allowing it to inline mutually recursive bindings. If
you have experienced bugs in the last week or two, give your tree a
pull and rebuild.
Thanks,
Andy

http://wingolog.org/
From MAILERDAEMON Tue Oct 11 06:12:49 2011
Received: from list by lists.gnu.org with archive (Exim 4.71)
id 1RDZKL0002hUCm
for mharcguiledevel@gnu.org; Tue, 11 Oct 2011 06:12:49 0400
Received: from eggs.gnu.org ([140.186.70.92]:53449)
by lists.gnu.org with esmtp (Exim 4.71)
(envelopefrom