ruby-core@ruby-lang.org archive (unofficial mirror)
 help / color / mirror / Atom feed
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);
 }
 
 /*

      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).