[#8815] Segfault in libc strlen, via rb_str_new2 — "Sean E. Russell" <ser@...>

Howdy,

12 messages 2006/09/09
[#8817] Re: Segfault in libc strlen, via rb_str_new2 — Eric Hodel <drbrain@...7.net> 2006/09/09

On Sep 8, 2006, at 10:10 PM, Sean E. Russell wrote:

Re: patch bignums

From: Ondrej Bilka <neleai@...>
Date: 2006-09-22 09:05:33 UTC
List: ruby-core #8910
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);
 }
 
 /*


In This Thread

Prev Next