From: Kevin Ryde <user42@zip.com.au>
Subject: ash using shifts (was: ratio implementation)
Date: Sat, 18 Oct 2003 10:55:31 +1000 [thread overview]
Message-ID: <87znfz4b5o.fsf_-_@zip.com.au> (raw)
In-Reply-To: <87n0c3zaoh.fsf@zip.com.au> (Kevin Ryde's message of "Wed, 15 Oct 2003 09:01:02 +1000")
[-- Attachment #1: Type: text/plain, Size: 256 bytes --]
Speaking of ash, the bit of code below is what I'm looking at for
shifts instead of mul or div. Untested as yet, but hopefully not too
far wrong. Anyone who wants to take it forward should feel free ...
or kick it into touch and do something different.
[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: ash.c --]
[-- Type: text/x-csrc, Size: 3395 bytes --]
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 @m{2^{cnt},\n"
"2^@var{cnt}}, and when @var{cnt} is negative it's a division,\n"
"rounded towards negative infinity. (Note that this is not the\n"
"same rounding as @code{quotient} does.)\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"
"\n"
"@lisp\n"
"(number->string (ash #b1 3) 2) @result{} \"1000\"\n"
"(number->string (ash #b1010 -1) 2) @result{} \"101\"\n"
"\n"
";; -23 is bits ...11101001, -6 is bits ...111010\n"
"(ash -23 -2) @result{} -6\n"
"@end lisp")
#define FUNC_NAME s_scm_ash
{
long bits_to_shift;
SCM_VALIDATE_INUM (2, cnt);
bits_to_shift = SCM_INUM (cnt);
if (SCM_INUMP (y)) {
long in = SCM_INUM (n);
if (bits_to_shift > 0)
{
/* Left shift of more than SCM_I_FIXNUM_BIT-1 will certainly
overflow a non-zero fixnum. For smaller shifts we check the bits
going into positions above SCM_I_FIXNUM_BIT-1. If they're all 0s
for in>=0, or all 1s for in<0 then there's no overflow. Those
bits are "in >> (SCM_I_FIXNUM_BIT-1 - bits_to_shift". */
if (in == 0)
return n;
/* FIXME: This relies on signed right shifts being arithmetic, which
is not guaranteed by C99. */
if (bits_to_shift < SCM_I_FIXNUM_BIT-1
&& ((unsigned long) ((in >> (SCM_I_FIXNUM_BIT-1 - bits_to_shift))
+ 1 <= 1)))
{
return SCM_MKINUM (in << bits_to_shift);
}
else
{
SCM result = scm_i_long2big (z);
mpz_mul_2exp (SCM_I_BIG_MPZ (result), SCM_I_BIG_MPZ (result),
bits_to_shift);
return result;
}
}
else
{
bits_to_shift = -bits_to_shift;
if (bits_to_shift >= LONG_BIT)
return (in >= ? 0 : -1);
else
{
/* FIXME: This relies on signed right shifts being arithmetic,
which is not guaranteed by C99. */
return SCM_MKINUM (in >> bits_to_shift);
}
}
} else if (SCM_BIGP (n)) {
SCM result;
if (bits_to_shift == 0)
return n;
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;
}
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. We could detect the case of bits_to_shift being so big
as to leave us with only 0 or -1, and avoid allocating a bignum,
but that doesn't seem worth worrying about. */
mpz_fdiv_q_2exp (SCM_I_BIG_MPZ (result), SCM_I_BIG_MPZ (n),
-bits_to_shift);
return scm_i_normbig (result);
}
} else {
SCM_WRONG_TYPE_ARG (SCM_ARG1, n);
}
}
#undef FUNC_NAME
[-- Attachment #3: Type: text/plain, Size: 142 bytes --]
_______________________________________________
Guile-devel mailing list
Guile-devel@gnu.org
http://mail.gnu.org/mailman/listinfo/guile-devel
next prev parent reply other threads:[~2003-10-18 0:55 UTC|newest]
Thread overview: 32+ messages / expand[flat|nested] mbox.gz Atom feed top
2003-07-28 11:24 ratio implementation Bill Schottstaedt
2003-07-28 12:08 ` Han-Wen Nienhuys
2003-07-29 0:41 ` Kevin Ryde
2003-07-29 11:57 ` Bill Schottstaedt
2003-07-30 22:42 ` Kevin Ryde
2003-09-15 10:35 ` Marius Vollmer
2003-09-15 16:19 ` Rob Browning
2003-09-15 22:06 ` Dirk Herrmann
2003-09-15 22:59 ` Kevin Ryde
2003-09-16 11:39 ` Bill Schottstaedt
2003-09-16 21:36 ` Rob Browning
2003-09-18 21:09 ` Dirk Herrmann
2003-10-07 15:26 ` Marius Vollmer
2003-10-13 10:58 ` Bill Schottstaedt
2003-10-14 8:57 ` Marius Vollmer
2004-02-18 14:25 ` fractions.test Bill Schottstaedt
2003-10-14 12:39 ` ratio implementation Marius Vollmer
2003-10-14 22:56 ` Kevin Ryde
2003-10-14 13:03 ` Marius Vollmer
2003-10-14 23:37 ` Kevin Ryde
2003-10-16 11:49 ` Bill Schottstaedt
2003-10-17 10:09 ` Marius Vollmer
2003-10-17 11:47 ` Bill Schottstaedt
2003-10-17 15:04 ` Rob Browning
2003-10-18 0:45 ` Kevin Ryde
2003-10-15 12:57 ` Bill Schottstaedt
2003-10-17 10:20 ` Marius Vollmer
2003-10-17 15:14 ` Rob Browning
2003-10-17 15:42 ` Marius Vollmer
2003-10-14 23:01 ` Kevin Ryde
2003-10-18 0:55 ` Kevin Ryde [this message]
2003-10-07 15:24 ` Marius Vollmer
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
List information: https://www.gnu.org/software/guile/
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=87znfz4b5o.fsf_-_@zip.com.au \
--to=user42@zip.com.au \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).