internal.h: round macros
* internal.h (ROUND_FUNC, ROUND_CALL): macros wrapping round functions. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@56824 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
parent
d9035a8fd4
commit
81ec47ea18
10
internal.h
10
internal.h
@ -1151,8 +1151,14 @@ enum ruby_num_rounding_mode {
|
|||||||
RUBY_NUM_ROUND_HALF_EVEN,
|
RUBY_NUM_ROUND_HALF_EVEN,
|
||||||
RUBY_NUM_ROUND_DEFAULT = ROUND_DEFAULT
|
RUBY_NUM_ROUND_DEFAULT = ROUND_DEFAULT
|
||||||
};
|
};
|
||||||
#define ROUND_TO(mode, up, even) \
|
#define ROUND_TO(mode, even, up) \
|
||||||
((mode) == RUBY_NUM_ROUND_HALF_EVEN ? even : up)
|
((mode) == RUBY_NUM_ROUND_HALF_EVEN ? even : \
|
||||||
|
up)
|
||||||
|
#define ROUND_FUNC(mode, name) \
|
||||||
|
ROUND_TO(mode, name##_half_even, name##_half_up)
|
||||||
|
#define ROUND_CALL(mode, name, args) \
|
||||||
|
ROUND_TO(mode, name##_half_even args, \
|
||||||
|
name##_half_up args)
|
||||||
|
|
||||||
int rb_num_to_uint(VALUE val, unsigned int *ret);
|
int rb_num_to_uint(VALUE val, unsigned int *ret);
|
||||||
VALUE ruby_num_interval_step_size(VALUE from, VALUE to, VALUE step, int excl);
|
VALUE ruby_num_interval_step_size(VALUE from, VALUE to, VALUE step, int excl);
|
||||||
|
28
numeric.c
28
numeric.c
@ -99,6 +99,7 @@ round_half_up(double x, double s)
|
|||||||
|
|
||||||
#ifdef HAVE_ROUND
|
#ifdef HAVE_ROUND
|
||||||
f = round(xs);
|
f = round(xs);
|
||||||
|
if (s == 1.0) return f;
|
||||||
#endif
|
#endif
|
||||||
if (x > 0) {
|
if (x > 0) {
|
||||||
#ifndef HAVE_ROUND
|
#ifndef HAVE_ROUND
|
||||||
@ -2033,6 +2034,18 @@ int_round_half_up(SIGNED_VALUE x, SIGNED_VALUE y)
|
|||||||
return (x + y / 2) / y * y;
|
return (x + y / 2) / y * y;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
int_half_p_half_even(VALUE num, VALUE n, VALUE f)
|
||||||
|
{
|
||||||
|
return (int)int_odd_p(rb_int_idiv(n, f));
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
int_half_p_half_up(VALUE num, VALUE n, VALUE f)
|
||||||
|
{
|
||||||
|
return int_pos_p(num);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Assumes num is an Integer, ndigits <= 0
|
* Assumes num is an Integer, ndigits <= 0
|
||||||
*/
|
*/
|
||||||
@ -2050,9 +2063,7 @@ rb_int_round(VALUE num, int ndigits, enum ruby_num_rounding_mode mode)
|
|||||||
SIGNED_VALUE x = FIX2LONG(num), y = FIX2LONG(f);
|
SIGNED_VALUE x = FIX2LONG(num), y = FIX2LONG(f);
|
||||||
int neg = x < 0;
|
int neg = x < 0;
|
||||||
if (neg) x = -x;
|
if (neg) x = -x;
|
||||||
x = ROUND_TO(mode,
|
x = ROUND_CALL(mode, int_round, (x, y));
|
||||||
int_round_half_up(x, y),
|
|
||||||
int_round_half_even(x, y));
|
|
||||||
if (neg) x = -x;
|
if (neg) x = -x;
|
||||||
return LONG2NUM(x);
|
return LONG2NUM(x);
|
||||||
}
|
}
|
||||||
@ -2065,10 +2076,7 @@ rb_int_round(VALUE num, int ndigits, enum ruby_num_rounding_mode mode)
|
|||||||
n = rb_int_minus(num, r);
|
n = rb_int_minus(num, r);
|
||||||
r = rb_int_cmp(r, h);
|
r = rb_int_cmp(r, h);
|
||||||
if (FIXNUM_POSITIVE_P(r) ||
|
if (FIXNUM_POSITIVE_P(r) ||
|
||||||
(FIXNUM_ZERO_P(r) &&
|
(FIXNUM_ZERO_P(r) && ROUND_CALL(mode, int_half_p, (num, n, f)))) {
|
||||||
ROUND_TO(mode,
|
|
||||||
int_pos_p(num),
|
|
||||||
(SIGNED_VALUE) int_odd_p(rb_int_idiv(n, f))))) {
|
|
||||||
n = rb_int_plus(n, f);
|
n = rb_int_plus(n, f);
|
||||||
}
|
}
|
||||||
return n;
|
return n;
|
||||||
@ -2199,14 +2207,12 @@ flo_round(int argc, VALUE *argv, VALUE num)
|
|||||||
}
|
}
|
||||||
number = RFLOAT_VALUE(num);
|
number = RFLOAT_VALUE(num);
|
||||||
if (ndigits == 0) {
|
if (ndigits == 0) {
|
||||||
x = ROUND_TO(mode,
|
x = ROUND_CALL(mode, round, (number, 1.0));
|
||||||
round(number), round_half_even(number, 1.0));
|
|
||||||
return dbl2ival(x);
|
return dbl2ival(x);
|
||||||
}
|
}
|
||||||
if (float_invariant_round(number, ndigits, &num)) return num;
|
if (float_invariant_round(number, ndigits, &num)) return num;
|
||||||
f = pow(10, ndigits);
|
f = pow(10, ndigits);
|
||||||
x = ROUND_TO(mode,
|
x = ROUND_CALL(mode, round, (number, f));
|
||||||
round_half_up(number, f), round_half_even(number, f));
|
|
||||||
return DBL2NUM(x / f);
|
return DBL2NUM(x / f);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1481,9 +1481,7 @@ nurat_round_n(int argc, VALUE *argv, VALUE self)
|
|||||||
enum ruby_num_rounding_mode mode = (
|
enum ruby_num_rounding_mode mode = (
|
||||||
argc = rb_scan_args(argc, argv, "*:", NULL, &opt),
|
argc = rb_scan_args(argc, argv, "*:", NULL, &opt),
|
||||||
rb_num_get_rounding_option(opt));
|
rb_num_get_rounding_option(opt));
|
||||||
VALUE (*round_func)(VALUE) =
|
VALUE (*round_func)(VALUE) = ROUND_FUNC(mode, nurat_round);
|
||||||
ROUND_TO(mode,
|
|
||||||
nurat_round_half_up, nurat_round_half_even);
|
|
||||||
return f_round_common(argc, argv, self, round_func);
|
return f_round_common(argc, argv, self, round_func);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user