From: Ondrej Bilka <neleai@seznam.cz>
To: ruby-core@ruby-lang.org
Subject: Re: patch bignums
Date: Fri, 22 Sep 2006 18:05:33 +0900 [thread overview]
Message-ID: <20060922120743.GA3517@localhost@localdomain> (raw)
In-Reply-To: <200609211630.k8LGUkRT012129@sharui.kanuma.tochigi.jp>
On Thu, Sep 21, 2006 at 06:30:49PM +0200, Nobuyoshi Nakada wrote:
> Hi,
>
> At Thu, 21 Sep 2006 23:52:56 +0900,
> Ondrej Bilka wrote in [ruby-core:08904]:
> Still I don't have time to review the patch, just a nitpicking.
>
> > --- bignum.c 4 Sep 2006 20:10:45 -0000 1.135
> > +++ bignum.c 21 Sep 2006 14:46:25 -0000
> > @@ -38,6 +38,13 @@
> >
> > #define BIGZEROP(x) (RBIGNUM(x)->len == 0 || (RBIGNUM(x)->len == 1 && BDIGITS(x)[0] == 0))
> >
> > +VALUE rb_num_plus(VALUE x,VALUE y);
> > +VALUE rb_num_minus(VALUE x,VALUE y);
> > +VALUE rb_num_mul(VALUE x,VALUE y);
> > +VALUE rb_num_sqr(VALUE x);
> > +VALUE rb_num_pow(VALUE x,VALUE y);
>
> Why are these in bignum.c? It feels they are OK in numeric.c.
> Also, I suspect this change makes Fixnum operations slower.
Why? This is used when you are not sure if its fixnum or bignum.
Originaly I did fixnum conversion at big_foo methods. Then I tried
refactor it. And named it bad. int_foo is better.
Here is plain refactoring.
Index: numeric.c
===================================================================
RCS file: /src/ruby/numeric.c,v
retrieving revision 1.150
diff -u -r1.150 numeric.c
--- numeric.c 21 Sep 2006 22:52:38 -0000 1.150
+++ numeric.c 22 Sep 2006 08:53:08 -0000
@@ -2233,31 +2235,11 @@
* 2 ** -1 #=> 0.5
* 2 ** 0.5 #=> 1.4142135623731
*/
-
+VALUE rb_int_pow(VALUE x,VALUE y);
static VALUE
fix_pow(VALUE x, VALUE y)
{
- if (FIXNUM_P(y)) {
- long a, b;
-
- b = FIX2LONG(y);
- if (b == 0) return INT2FIX(1);
- if (b == 1) return x;
- a = FIX2LONG(x);
- if (b > 0) {
- return rb_big_pow(rb_int2big(a), y);
- }
- return rb_float_new(pow((double)a, (double)b));
- }
- switch (TYPE(y)) {
- case T_BIGNUM:
- x = rb_int2big(FIX2LONG(x));
- return rb_big_pow(x, y);
- case T_FLOAT:
- return rb_float_new(pow((double)FIX2LONG(x), RFLOAT(y)->value));
- default:
- return rb_num_coerce_bin(x, y);
- }
+ return rb_int_pow(x,y);
}
/*
@@ -2861,6 +2843,127 @@
return Qtrue;
}
+/*
+ * These fuctions are used when if integer is fixnum or bignum doesn't matter.
+ * They don't do type check for other than fix/bignum.
+ */
+VALUE
+rb_int_plus(VALUE x,VALUE y)
+{
+ if FIXNUM_P(x)
+ return fix_plus(x,y);
+ else
+ return rb_big_plus(x,y);
+}
+
+VALUE
+rb_int_minus(VALUE x,VALUE y)
+{
+ if FIXNUM_P(x)
+ return fix_minus(x,y);
+ else
+ return rb_big_minus(x,y);
+}
+
+VALUE
+rb_int_mul(VALUE x,VALUE y)
+{
+ if FIXNUM_P(x)
+ return fix_mul(x,y);
+ else
+ return rb_big_mul(x,y);
+}
+
+VALUE rb_big_sqr(VALUE x){
+ return rb_big_mul(x,x);
+}
+
+VALUE
+rb_int_sqr(VALUE x)
+{
+ if FIXNUM_P(x)
+ return fix_mul(x,x);
+ else
+ return rb_big_sqr(x);
+}
+
+void intdivmod(VALUE x,VALUE y,VALUE *div,VALUE *mod){/*for extension
is this better than returning array.*/
+ if FIXNUM_P(x)
+ {
+ if FIXNUM_P(y){
+ long d,m;
+ fixdivmod(FIX2LONG(x),FIX2LONG(y),&d,&m);
+ *div=LONG2FIX(d);*mod=LONG2FIX(m);
+ return ;
+ }else{
+ x=rb_int2big(FIX2LONG(x));
+ }
+ }
+ bigdivmod(x,y,div,mod);
+}
+
+VALUE rb_int_div(VALUE x,VALUE y){
+ VALUE d;
+ intdivmod(x,y,&d,NULL);
+ return d;
+}
+
+VALUE rb_int_mod(VALUE x,VALUE y){
+ VALUE mod;
+ intdivmod(x,y,NULL,&mod);
+ return mod;
+}
+
+
+VALUE
+rb_int_pow(VALUE x,VALUE y)
+{
+ double d;
+ long yy;
+
+ if (y == INT2FIX(0)) return INT2FIX(1);
+ switch (TYPE(y)) {
+ case T_FLOAT:
+ d = RFLOAT(y)->value;
+ break;
+
+ case T_BIGNUM:
+ rb_warn("in a**b, b may be too big");
+ d = rb_big2dbl(y);
+ break;
+
+ case T_FIXNUM:
+ yy = FIX2LONG(y);
+ if (yy > 0) {
+ VALUE z = x;
+ if (!FIXNUM_P(x)&&RBIGNUM(x)->len * SIZEOF_BDIGITS * yy > 1024*1024) {
+ rb_warn("in a**b, b may be too big");
+ d = (double)yy;
+ break;
+ }
+ for (;;) {
+ yy -= 1;
+ if (yy == 0) break;
+ while (yy % 2 == 0) {
+ yy /= 2;
+ x = rb_int_sqr(x);
+ }
+ z = rb_int_mul(z, x);
+ }
+ return z;
+ }
+ d = (double)yy;
+ break;
+
+ default:
+ return rb_num_coerce_bin(x, y);
+ }
+ return rb_float_new(pow(rb_big2dbl(x), d));
+}
+
+
+
+
void
Init_Numeric(void)
{
Index: bignum.c
===================================================================
RCS file: /src/ruby/bignum.c,v
retrieving revision 1.136
diff -u -r1.136 bignum.c
--- bignum.c 21 Sep 2006 22:52:38 -0000 1.136
+++ bignum.c 22 Sep 2006 08:53:13 -0000
@@ -1334,7 +1334,7 @@
}
}
-static void
+void
bigdivmod(VALUE x, VALUE y, VALUE *divp, VALUE *modp)
{
VALUE mod;
@@ -1523,50 +1523,7 @@
VALUE
rb_big_pow(VALUE x, VALUE y)
{
- double d;
- long yy;
-
- if (y == INT2FIX(0)) return INT2FIX(1);
- switch (TYPE(y)) {
- case T_FLOAT:
- d = RFLOAT(y)->value;
- break;
-
- case T_BIGNUM:
- rb_warn("in a**b, b may be too big");
- d = rb_big2dbl(y);
- break;
-
- case T_FIXNUM:
- yy = FIX2LONG(y);
- if (yy > 0) {
- VALUE z = x;
-
- if (RBIGNUM(x)->len * SIZEOF_BDIGITS * yy > 1024*1024) {
- rb_warn("in a**b, b may be too big");
- d = (double)yy;
- break;
- }
- for (;;) {
- yy -= 1;
- if (yy == 0) break;
- while (yy % 2 == 0) {
- yy /= 2;
- x = rb_big_mul0(x, x);
- if (!BDIGITS(x)[RBIGNUM(x)->len-1]) RBIGNUM(x)->len--;
- }
- z = rb_big_mul0(z, x);
- if (!BDIGITS(z)[RBIGNUM(z)->len-1]) RBIGNUM(z)->len--;
- }
- return bignorm(z);
- }
- d = (double)yy;
- break;
-
- default:
- return rb_num_coerce_bin(x, y);
- }
- return rb_float_new(pow(rb_big2dbl(x), d));
+ return rb_int_pow(x,y);
}
/*
prev parent reply other threads:[~2006-09-22 9:18 UTC|newest]
Thread overview: 7+ messages / expand[flat|nested] mbox.gz Atom feed top
2006-09-21 14:52 patch bignums Ondrej Bilka
2006-09-21 16:30 ` Nobuyoshi Nakada
2006-09-21 17:12 ` Berger, Daniel
2006-09-22 1:01 ` Yukihiro Matsumoto
2006-09-21 18:33 ` Sam Roberts
2006-09-22 0:22 ` Nobuyoshi Nakada
2006-09-22 9:05 ` Ondrej Bilka [this message]
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-list from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
List information: https://www.ruby-lang.org/en/community/mailing-lists/
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20060922120743.GA3517@localhost@localdomain \
--to=ruby-core@ruby-lang.org \
/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).