ruby-changes:42223
From: nobu <ko1@a...>
Date: Sat, 26 Mar 2016 10:54:54 +0900 (JST)
Subject: [ruby-changes:42223] nobu:r54297 (trunk): numeric.c: rb_int_round
nobu 2016-03-26 10:54:50 +0900 (Sat, 26 Mar 2016) New Revision: 54297 https://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=revision&revision=54297 Log: numeric.c: rb_int_round * numeric.c (rb_int_round): rounding function for generic Integers. Modified files: trunk/ChangeLog trunk/internal.h trunk/numeric.c Index: numeric.c =================================================================== --- numeric.c (revision 54296) +++ numeric.c (revision 54297) @@ -106,6 +106,7 @@ round(double x) https://github.com/ruby/ruby/blob/trunk/numeric.c#L106 static VALUE fix_uminus(VALUE num); static VALUE fix_mul(VALUE x, VALUE y); static VALUE int_pow(long x, unsigned long y); +static VALUE int_cmp(VALUE x, VALUE y); static ID id_coerce, id_div, id_divmod; #define id_to_i idTo_i @@ -177,6 +178,32 @@ compare_with_zero(VALUE num, ID mid) https://github.com/ruby/ruby/blob/trunk/numeric.c#L178 #define FIXNUM_NEGATIVE_P(num) ((SIGNED_VALUE)(num) < 0) #define FIXNUM_ZERO_P(num) ((num) == INT2FIX(0)) +#if 0 +static inline int +int_pos_p(VALUE num) +{ + if (FIXNUM_P(num)) { + return FIXNUM_NEGATIVE_P(num); + } + else if (RB_TYPE_P(num, T_BIGNUM)) { + return BIGNUM_NEGATIVE_P(num); + } + return Qnil; +} +#endif + +static inline int +int_neg_p(VALUE num) +{ + if (FIXNUM_P(num)) { + return FIXNUM_NEGATIVE_P(num); + } + else if (RB_TYPE_P(num, T_BIGNUM)) { + return BIGNUM_NEGATIVE_P(num); + } + return Qnil; +} + static inline int positive_int_p(VALUE num) { @@ -1743,12 +1770,11 @@ flo_ceil(VALUE num) https://github.com/ruby/ruby/blob/trunk/numeric.c#L1770 /* * Assumes num is an Integer, ndigits <= 0 */ -static VALUE -int_round_0(VALUE num, int ndigits) +VALUE +rb_int_round(VALUE num, int ndigits) { VALUE n, f, h, r; long bytes; - ID op; /* If 10**N / 2 > num, then return 0 */ /* We have log_256(10) > 0.415241 and log_256(1/2) = -0.125, so */ bytes = FIXNUM_P(num) ? sizeof(long) : rb_funcall(num, idSize, 0); @@ -1769,12 +1795,12 @@ int_round_0(VALUE num, int ndigits) https://github.com/ruby/ruby/blob/trunk/numeric.c#L1795 /* then int_pow overflow */ return INT2FIX(0); } - h = rb_funcall(f, '/', 1, INT2FIX(2)); - r = rb_funcall(num, '%', 1, f); - n = rb_funcall(num, '-', 1, r); - op = negative_int_p(num) ? idLE : '<'; - if (!RTEST(rb_funcall(r, op, 1, h))) { - n = rb_funcall(n, '+', 1, f); + h = rb_int_idiv(f, INT2FIX(2)); + r = rb_int_modulo(num, f); + n = rb_int_minus(num, r); + r = int_cmp(r, h); + if (FIXNUM_POSITIVE_P(r) || (FIXNUM_ZERO_P(r) && !int_neg_p(num))) { + n = rb_int_plus(n, f); } return n; } @@ -1826,7 +1852,7 @@ flo_round(int argc, VALUE *argv, VALUE n https://github.com/ruby/ruby/blob/trunk/numeric.c#L1852 ndigits = NUM2INT(nd); } if (ndigits < 0) { - return int_round_0(flo_truncate(num), ndigits); + return rb_int_round(flo_truncate(num), ndigits); } number = RFLOAT_VALUE(num); if (ndigits == 0) { @@ -4123,7 +4149,7 @@ int_round(int argc, VALUE* argv, VALUE n https://github.com/ruby/ruby/blob/trunk/numeric.c#L4149 if (ndigits == 0) { return num; } - return int_round_0(num, ndigits); + return rb_int_round(num, ndigits); } /* Index: internal.h =================================================================== --- internal.h (revision 54296) +++ internal.h (revision 54297) @@ -1013,6 +1013,7 @@ VALUE rb_int_minus(VALUE x, VALUE y); https://github.com/ruby/ruby/blob/trunk/internal.h#L1013 VALUE rb_int_mul(VALUE x, VALUE y); VALUE rb_int_idiv(VALUE x, VALUE y); VALUE rb_int_modulo(VALUE x, VALUE y); +VALUE rb_int_round(VALUE num, int ndigits); VALUE rb_dbl_hash(double d); VALUE rb_fix_plus(VALUE x, VALUE y); Index: ChangeLog =================================================================== --- ChangeLog (revision 54296) +++ ChangeLog (revision 54297) @@ -1,4 +1,7 @@ https://github.com/ruby/ruby/blob/trunk/ChangeLog#L1 -Sat Mar 26 10:54:14 2016 Nobuyoshi Nakada <nobu@r...> +Sat Mar 26 10:54:49 2016 Nobuyoshi Nakada <nobu@r...> + + * numeric.c (rb_int_round): rounding function for generic + Integers. * numeric.c (rb_int_{uminus,plus,minus,mul,idiv,modulo}): basic arithmetic functions for generic Integers. -- ML: ruby-changes@q... Info: http://www.atdot.net/~ko1/quickml/