[前][次][番号順一覧][スレッド一覧]

ruby-changes:41955

From: naruse <ko1@a...>
Date: Tue, 8 Mar 2016 18:15:23 +0900 (JST)
Subject: [ruby-changes:41955] naruse:r54029 (trunk): * intern.h (rb_divmod): assume compilers `/` and `%` comply C99

naruse	2016-03-08 18:15:18 +0900 (Tue, 08 Mar 2016)

  New Revision: 54029

  https://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=revision&revision=54029

  Log:
    * intern.h (rb_divmod): assume compilers `/` and `%` comply C99
      and reduce branching. If a compiler doesn't comply, add #ifdefs.
    
    * intern.h (rb_div): added for Ruby's behavior.
    
    * intern.h (rb_mod): added for Ruby's behavior.
    
    * insns.def (opt_div): use rb_div.
    
    * insns.def (opt_mod): use rb_mod.
    
    * numeric.c (fixdivmod): removed.
    
    * numeric.c (fix_divide): use rb_div.
    
    * numeric.c (fix_mod): use rb_mod.
    
    * numeric.c (fix_divmod): use rb_divmod.

  Modified files:
    trunk/ChangeLog
    trunk/insns.def
    trunk/internal.h
    trunk/numeric.c
Index: numeric.c
===================================================================
--- numeric.c	(revision 54028)
+++ numeric.c	(revision 54029)
@@ -3079,33 +3079,6 @@ fix_mul(VALUE x, VALUE y) https://github.com/ruby/ruby/blob/trunk/numeric.c#L3079
     }
 }
 
-static void
-fixdivmod(long x, long y, long *divp, long *modp)
-{
-    long div, mod;
-
-    if (y == 0) rb_num_zerodiv();
-    if (y < 0) {
-	if (x < 0)
-	    div = -x / -y;
-	else
-	    div = - (x / -y);
-    }
-    else {
-	if (x < 0)
-	    div = - (-x / y);
-	else
-	    div = x / y;
-    }
-    mod = x - div*y;
-    if ((mod < 0 && y > 0) || (mod > 0 && y < 0)) {
-	mod += y;
-	div -= 1;
-    }
-    if (divp) *divp = div;
-    if (modp) *modp = mod;
-}
-
 /*
  *  call-seq:
  *     fix.fdiv(numeric)  ->  float
@@ -3138,10 +3111,8 @@ static VALUE https://github.com/ruby/ruby/blob/trunk/numeric.c#L3111
 fix_divide(VALUE x, VALUE y, ID op)
 {
     if (FIXNUM_P(y)) {
-	long div;
-
-	fixdivmod(FIX2LONG(x), FIX2LONG(y), &div, 0);
-	return LONG2NUM(div);
+	if (FIX2LONG(y) == 0) rb_num_zerodiv();
+	return LONG2NUM(rb_div(FIX2LONG(x), FIX2LONG(y)));
     }
     else if (RB_TYPE_P(y, T_BIGNUM)) {
 	x = rb_int2big(FIX2LONG(x));
@@ -3212,10 +3183,8 @@ static VALUE https://github.com/ruby/ruby/blob/trunk/numeric.c#L3183
 fix_mod(VALUE x, VALUE y)
 {
     if (FIXNUM_P(y)) {
-	long mod;
-
-	fixdivmod(FIX2LONG(x), FIX2LONG(y), 0, &mod);
-	return LONG2NUM(mod);
+	if (FIX2LONG(y) == 0) rb_num_zerodiv();
+	return LONG2FIX(rb_mod(FIX2LONG(x), FIX2LONG(y)));
     }
     else if (RB_TYPE_P(y, T_BIGNUM)) {
 	x = rb_int2big(FIX2LONG(x));
@@ -3240,10 +3209,9 @@ fix_divmod(VALUE x, VALUE y) https://github.com/ruby/ruby/blob/trunk/numeric.c#L3209
 {
     if (FIXNUM_P(y)) {
 	long div, mod;
-
-	fixdivmod(FIX2LONG(x), FIX2LONG(y), &div, &mod);
-
-	return rb_assoc_new(LONG2NUM(div), LONG2NUM(mod));
+	if (FIX2LONG(y) == 0) rb_num_zerodiv();
+	rb_divmod(FIX2LONG(x), FIX2LONG(y), &div, &mod);
+	return rb_assoc_new(LONG2NUM(div), LONG2FIX(mod));
     }
     else if (RB_TYPE_P(y, T_BIGNUM)) {
 	x = rb_int2big(FIX2LONG(x));
Index: internal.h
===================================================================
--- internal.h	(revision 54028)
+++ internal.h	(revision 54029)
@@ -266,6 +266,47 @@ nlz_int128(uint128_t x) https://github.com/ruby/ruby/blob/trunk/internal.h#L266
 }
 #endif
 
+/*
+ * This behaves different from C99 for negative arguments.
+ * Note that div may overflow fixnum.
+ */
+static inline void
+rb_divmod(long x, long y, long *divp, long *modp) {
+    /* assume / and % comply C99.
+     * ldiv(3) won't be inlined by GCC and clang.
+     * I expect / and % are compiled as single idiv.
+     */
+    long div = x / y;
+    long mod = x % y;
+    if (y > 0 ? mod < 0 : mod > 0) {
+	mod += y;
+	div -= 1;
+    }
+    if (divp) *divp = div;
+    if (modp) *modp = mod;
+}
+
+/* div() for Ruby
+ * This behaves different from C99 for negative arguments.
+ * Note that div may overflow fixnum
+ */
+static inline long
+rb_div(long x, long y) {
+    long div;
+    rb_divmod(x, y, &div, NULL);
+    return div;
+}
+
+/* mod() for Ruby
+ * This behaves different from C99 for negative arguments.
+ */
+static inline long
+rb_mod(long x, long y) {
+    long mod;
+    rb_divmod(x, y, NULL, &mod);
+    return mod;
+}
+
 #if defined(HAVE_UINT128_T)
 #   define bit_length(x) \
     (sizeof(x) <= SIZEOF_INT ? SIZEOF_INT * CHAR_BIT - nlz_int((unsigned int)(x)) : \
Index: ChangeLog
===================================================================
--- ChangeLog	(revision 54028)
+++ ChangeLog	(revision 54029)
@@ -1,3 +1,24 @@ https://github.com/ruby/ruby/blob/trunk/ChangeLog#L1
+Tue Mar  8 17:20:21 2016  NARUSE, Yui  <naruse@r...>
+
+	* intern.h (rb_divmod): assume compilers `/` and `%` comply C99
+	  and reduce branching. If a compiler doesn't comply, add #ifdefs.
+
+	* intern.h (rb_div): added for Ruby's behavior.
+
+	* intern.h (rb_mod): added for Ruby's behavior.
+
+	* insns.def (opt_div): use rb_div.
+
+	* insns.def (opt_mod): use rb_mod.
+
+	* numeric.c (fixdivmod): removed.
+
+	* numeric.c (fix_divide): use rb_div.
+
+	* numeric.c (fix_mod): use rb_mod.
+
+	* numeric.c (fix_divmod): use rb_divmod.
+
 Tue Mar  8 17:53:09 2016  NARUSE, Yui  <naruse@r...>
 
 	* insns.def (opt_mod): show its method name on ZeroDivisionError.
Index: insns.def
===================================================================
--- insns.def	(revision 54028)
+++ insns.def	(revision 54029)
@@ -1473,34 +1473,9 @@ opt_div https://github.com/ruby/ruby/blob/trunk/insns.def#L1473
 {
     if (FIXNUM_2_P(recv, obj) &&
 	BASIC_OP_UNREDEFINED_P(BOP_DIV, FIXNUM_REDEFINED_OP_FLAG)) {
-	long x, y, div;
-
-	x = FIX2LONG(recv);
-	y = FIX2LONG(obj);
-	{
-	    /* copied from numeric.c#fixdivmod */
-	    long mod;
-	    if (y == 0)
-		goto INSN_LABEL(normal_dispatch);
-	    if (y < 0) {
-		if (x < 0)
-		    div = -x / -y;
-		else
-		    div = -(x / -y);
-	    }
-	    else {
-		if (x < 0)
-		    div = -(-x / y);
-		else
-		    div = x / y;
-	    }
-	    mod = x - div * y;
-	    if ((mod < 0 && y > 0) || (mod > 0 && y < 0)) {
-		mod += y;
-		div -= 1;
-	    }
-	}
-	val = LONG2NUM(div);
+	long y = FIX2LONG(obj);
+	if (y == 0) goto INSN_LABEL(normal_dispatch);
+	val = LONG2NUM(rb_div(FIX2LONG(recv), y));
     }
     else if (FLONUM_2_P(recv, obj) &&
 	     BASIC_OP_UNREDEFINED_P(BOP_DIV, FLOAT_REDEFINED_OP_FLAG)) {
@@ -1536,38 +1511,9 @@ opt_mod https://github.com/ruby/ruby/blob/trunk/insns.def#L1511
 {
     if (FIXNUM_2_P(recv, obj) &&
 	BASIC_OP_UNREDEFINED_P(BOP_MOD, FIXNUM_REDEFINED_OP_FLAG )) {
-	long x, y;
-
-	x = FIX2LONG(recv);
-	y = FIX2LONG(obj);
-	if (x > 0 && y > 0) {
-	    val = LONG2FIX(x % y);
-	}
-	else {
-	    /* copied from numeric.c#fixdivmod */
-	    long div, mod;
-
-	    if (y == 0)
-		goto INSN_LABEL(normal_dispatch);
-	    if (y < 0) {
-		if (x < 0)
-		    div = -x / -y;
-		else
-		    div = -(x / -y);
-	    }
-	    else {
-		if (x < 0)
-		    div = -(-x / y);
-		else
-		    div = x / y;
-	    }
-	    mod = x - div * y;
-	    if ((mod < 0 && y > 0) || (mod > 0 && y < 0)) {
-		mod += y;
-		div -= 1;
-	    }
-	    val = LONG2FIX(mod);
-	}
+	long y = FIX2LONG(obj);
+	if (y == 0) goto INSN_LABEL(normal_dispatch);
+	val = LONG2FIX(rb_mod(FIX2LONG(recv), y));
     }
     else if (FLONUM_2_P(recv, obj) &&
 	     BASIC_OP_UNREDEFINED_P(BOP_MOD, FLOAT_REDEFINED_OP_FLAG)) {

--
ML: ruby-changes@q...
Info: http://www.atdot.net/~ko1/quickml/

[前][次][番号順一覧][スレッド一覧]