diff options
| author | Yukihiro "Matz" Matsumoto <[email protected]> | 2017-11-22 15:43:48 +0900 |
|---|---|---|
| committer | Yukihiro "Matz" Matsumoto <[email protected]> | 2017-11-22 15:43:48 +0900 |
| commit | 284a1d12ee6b0fdd77b042771f5db833112fc14e (patch) | |
| tree | ad07b4b6754425fffbfdba1650725047dd97ba88 /src | |
| parent | 0ab21a9a5e487a0d50988adb5d6c4114364acd3d (diff) | |
| download | mruby-284a1d12ee6b0fdd77b042771f5db833112fc14e.tar.gz mruby-284a1d12ee6b0fdd77b042771f5db833112fc14e.zip | |
Provide shortcut comparison methods for numbers for performance.
Diffstat (limited to 'src')
| -rw-r--r-- | src/numeric.c | 126 |
1 files changed, 100 insertions, 26 deletions
diff --git a/src/numeric.c b/src/numeric.c index 44e3d9836..b898fd0b5 100644 --- a/src/numeric.c +++ b/src/numeric.c @@ -1318,59 +1318,129 @@ fix_to_s(mrb_state *mrb, mrb_value self) return mrb_fixnum_to_str(mrb, self, base); } -/* 15.2.9.3.6 */ -/* - * call-seq: - * self.f <=> other.f => -1, 0, +1 - * < => -1 - * = => 0 - * > => +1 - * Comparison---Returns -1, 0, or +1 depending on whether <i>fix</i> is - * less than, equal to, or greater than <i>numeric</i>. This is the - * basis for the tests in <code>Comparable</code>. - */ -static mrb_value -num_cmp(mrb_state *mrb, mrb_value self) +/* compare two numbers: (1:0:-1; -2 for error) */ +static mrb_int +cmpnum(mrb_state *mrb, mrb_value v1, mrb_value v2) { - mrb_value other; #ifdef MRB_WITHOUT_FLOAT mrb_int x, y; #else mrb_float x, y; #endif - mrb_get_args(mrb, "o", &other); - #ifdef MRB_WITHOUT_FLOAT - x = mrb_fixnum(self); + x = mrb_fixnum(v1); #else - x = mrb_to_flo(mrb, self); + x = mrb_to_flo(mrb, v1); #endif - switch (mrb_type(other)) { + switch (mrb_type(v2)) { case MRB_TT_FIXNUM: #ifdef MRB_WITHOUT_FLOAT - y = mrb_fixnum(other); + y = mrb_fixnum(v2); #else - y = (mrb_float)mrb_fixnum(other); + y = (mrb_float)mrb_fixnum(v2); #endif break; #ifndef MRB_WITHOUT_FLOAT case MRB_TT_FLOAT: - y = mrb_float(other); + y = mrb_float(v2); break; #endif default: - return mrb_nil_value(); + return -2; } if (x > y) - return mrb_fixnum_value(1); + return 1; else { if (x < y) - return mrb_fixnum_value(-1); - return mrb_fixnum_value(0); + return -1; + return 0; } } +/* 15.2.9.3.6 */ +/* + * call-seq: + * self.f <=> other.f => -1, 0, +1 + * < => -1 + * = => 0 + * > => +1 + * Comparison---Returns -1, 0, or +1 depending on whether <i>fix</i> is + * less than, equal to, or greater than <i>numeric</i>. This is the + * basis for the tests in <code>Comparable</code>. + */ +static mrb_value +num_cmp(mrb_state *mrb, mrb_value self) +{ + mrb_value other; + mrb_int n; + + mrb_get_args(mrb, "o", &other); + n = cmpnum(mrb, self, other); + if (n == -2) return mrb_nil_value(); + return mrb_fixnum_value(n); +} + +static void +cmperr(mrb_state *mrb, mrb_value v1, mrb_value v2) +{ + mrb_raisef(mrb, E_ARGUMENT_ERROR, "comparison of %S with %S failed", + mrb_obj_value(mrb_class(mrb, v1)), + mrb_obj_value(mrb_class(mrb, v2))); +} + +static mrb_value +num_lt(mrb_state *mrb, mrb_value self) +{ + mrb_value other; + mrb_int n; + + mrb_get_args(mrb, "o", &other); + n = cmpnum(mrb, self, other); + if (n == -2) cmperr(mrb, self, other); + if (n < 0) return mrb_true_value(); + return mrb_false_value(); +} + +static mrb_value +num_le(mrb_state *mrb, mrb_value self) +{ + mrb_value other; + mrb_int n; + + mrb_get_args(mrb, "o", &other); + n = cmpnum(mrb, self, other); + if (n == -2) cmperr(mrb, self, other); + if (n <= 0) return mrb_true_value(); + return mrb_false_value(); +} + +static mrb_value +num_gt(mrb_state *mrb, mrb_value self) +{ + mrb_value other; + mrb_int n; + + mrb_get_args(mrb, "o", &other); + n = cmpnum(mrb, self, other); + if (n == -2) cmperr(mrb, self, other); + if (n > 0) return mrb_true_value(); + return mrb_false_value(); +} + +static mrb_value +num_ge(mrb_state *mrb, mrb_value self) +{ + mrb_value other; + mrb_int n; + + mrb_get_args(mrb, "o", &other); + n = cmpnum(mrb, self, other); + if (n == -2) cmperr(mrb, self, other); + if (n >= 0) return mrb_true_value(); + return mrb_false_value(); +} + static mrb_value num_finite_p(mrb_state *mrb, mrb_value self) { @@ -1420,6 +1490,10 @@ mrb_init_numeric(mrb_state *mrb) mrb_define_method(mrb, numeric, "/", num_div, MRB_ARGS_REQ(1)); /* 15.2.8.3.4 */ mrb_define_method(mrb, numeric, "quo", num_div, MRB_ARGS_REQ(1)); /* 15.2.7.4.5 (x) */ mrb_define_method(mrb, numeric, "<=>", num_cmp, MRB_ARGS_REQ(1)); /* 15.2.9.3.6 */ + mrb_define_method(mrb, numeric, "<", num_lt, MRB_ARGS_REQ(1)); + mrb_define_method(mrb, numeric, "<=", num_le, MRB_ARGS_REQ(1)); + mrb_define_method(mrb, numeric, ">", num_gt, MRB_ARGS_REQ(1)); + mrb_define_method(mrb, numeric, ">=", num_ge, MRB_ARGS_REQ(1)); mrb_define_method(mrb, numeric, "finite?", num_finite_p, MRB_ARGS_NONE()); mrb_define_method(mrb, numeric, "infinite?",num_infinite_p, MRB_ARGS_NONE()); |
