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/