static VALUE range_max(int argc, VALUE *argv, VALUE range) { VALUE e = RANGE_END(range); int nm = FIXNUM_P(e) || rb_obj_is_kind_of(e, rb_cNumeric); if (rb_block_given_p() || (EXCL(range) && !nm) || argc) { return rb_call_super(argc, argv); } else { VALUE b = RANGE_BEG(range); int c = rb_cmpint(rb_funcall(b, id_cmp, 1, e), b, e); if (c > 0) return Qnil; if (EXCL(range)) { if (!FIXNUM_P(e) && !rb_obj_is_kind_of(e, rb_cInteger)) { rb_raise(rb_eTypeError, "cannot exclude non Integer end value"); } if (c == 0) return Qnil; if (!FIXNUM_P(b) && !rb_obj_is_kind_of(b,rb_cInteger)) { rb_raise(rb_eTypeError, "cannot exclude end value with non Integer begin value"); } if (FIXNUM_P(e)) { return LONG2NUM(FIX2LONG(e) - 1); } return rb_funcall(e, '-', 1, INT2FIX(1)); } return e; } }
static VALUE range_max(VALUE range) { VALUE e = RANGE_END(range); int ip = FIXNUM_P(e) || rb_obj_is_kind_of(e, rb_cInteger); if (rb_block_given_p() || (EXCL(range) && !ip)) { return rb_call_super(0, 0); } else { VALUE b = RANGE_BEG(range); int c = rb_cmpint(rb_funcall(b, id_cmp, 1, e), b, e); if (c > 0) return Qnil; if (EXCL(range)) { if (c == 0) return Qnil; if (FIXNUM_P(e)) { return LONG2NUM(FIX2LONG(e) - 1); } return rb_funcall(e, '-', 1, INT2FIX(1)); } return e; } }
static VALUE range_max(VALUE range, SEL sel) { VALUE e = RANGE_END(range); int nm = FIXNUM_P(e) || rb_obj_is_kind_of(e, rb_cNumeric); if (rb_block_given_p() || (EXCL(range) && !nm)) { if (sel == NULL) { sel = sel_registerName("max"); } return rb_vm_call_super(range, sel, 0, NULL); } else { VALUE b = RANGE_BEG(range); int c = rb_cmpint(rb_objs_cmp(b, e), b, e); if (c > 0) return Qnil; if (EXCL(range)) { if (!FIXNUM_P(e) && !rb_obj_is_kind_of(e, rb_cInteger)) { rb_raise(rb_eTypeError, "cannot exclude non Integer end value"); } if (c == 0) { return Qnil; } if (FIXNUM_P(e)) { return LONG2NUM(FIX2LONG(e) - 1); } VALUE one = INT2FIX(1); return rb_vm_call(e, selMINUS, 1, &one); } return e; } }
static VALUE cmp_gt(VALUE x, VALUE y) { VALUE c = rb_funcall(x, cmp, 1, y); if (rb_cmpint(c, x, y) > 0) return Qtrue; return Qfalse; }
static VALUE cmp_eq(VALUE *a) { VALUE c = rb_exec_recursive_paired_outer(cmp_eq_recursive, a[0], a[1], a[1]); if (NIL_P(c)) return Qfalse; if (rb_cmpint(c, a[0], a[1]) == 0) return Qtrue; return Qfalse; }
static int cmp_1(const void *ap, const void *bp, void *dummy) { struct sort_data *d = dummy; VALUE a = rb_enc_str_new(ap, d->elsize, d->enc); VALUE b = rb_enc_str_new(bp, d->elsize, d->enc); VALUE retval = rb_yield_values(2, a, b); return rb_cmpint(retval, a, b); }
static VALUE cmp_eq(VALUE *a) { VALUE c = rb_funcall(a[0], cmp, 1, a[1]); if (NIL_P(c)) return Qfalse; if (rb_cmpint(c, a[0], a[1]) == 0) return Qtrue; return Qfalse; }
static VALUE cmp_gt(VALUE x, SEL sel, VALUE y) { VALUE c = rb_vm_call(x, cmp, 1, &y); if (rb_cmpint(c, x, y) > 0) { return Qtrue; } return Qfalse; }
static int r_lt(VALUE a, VALUE b) { VALUE r = rb_funcall(a, id_cmp, 1, b); if (NIL_P(r)) return (int)Qfalse; if (rb_cmpint(r, a, b) < 0) return (int)Qtrue; return (int)Qfalse; }
static int r_lt(VALUE a, VALUE b) { VALUE r = rb_objs_cmp(a, b); if (NIL_P(r)) return Qfalse; if (rb_cmpint(r, a, b) < 0) return Qtrue; return Qfalse; }
VALUE rb_invcmp(VALUE x, VALUE y) { VALUE invcmp = rb_exec_recursive(invcmp_recursive, x, y); if (invcmp == Qundef || NIL_P(invcmp)) { return Qnil; } else { int result = -rb_cmpint(invcmp, x, y); return INT2FIX(result); } }
static VALUE cmp_eq(VALUE *a) { VALUE c = rb_vm_call(a[0], cmp, 1, &a[1]); if (NIL_P(c)) { return Qfalse; } if (rb_cmpint(c, a[0], a[1]) == 0) { return Qtrue; } return Qfalse; }
static VALUE cmp_equal(VALUE x, VALUE y) { VALUE c; if (x == y) return Qtrue; c = rb_exec_recursive_paired_outer(cmp_eq_recursive, x, y, y); if (NIL_P(c)) return Qfalse; if (rb_cmpint(c, x, y) == 0) return Qtrue; return Qfalse; }
static int r_le(VALUE a, VALUE b) { int c; VALUE r = rb_objs_cmp(a, b); if (NIL_P(r)) return Qfalse; c = rb_cmpint(r, a, b); if (c == 0) return INT2FIX(0); if (c < 0) return Qtrue; return Qfalse; }
static int r_le(VALUE a, VALUE b) { int c; VALUE r = rb_funcall(a, id_cmp, 1, b); if (NIL_P(r)) return (int)Qfalse; c = rb_cmpint(r, a, b); if (c == 0) return (int)INT2FIX(0); if (c < 0) return (int)Qtrue; return (int)Qfalse; }
static VALUE range_min(VALUE range) { if (rb_block_given_p()) { return rb_call_super(0, 0); } else { VALUE b = RANGE_BEG(range); VALUE e = RANGE_END(range); int c = rb_cmpint(rb_funcall(b, id_cmp, 1, e), b, e); if (c > 0 || (c == 0 && EXCL(range))) return Qnil; return b; } }
static VALUE range_min(VALUE range, SEL sel) { if (rb_block_given_p()) { if (sel == NULL) { sel = sel_registerName("min"); } return rb_vm_call_super(range, sel, 0, NULL); } else { VALUE b = RANGE_BEG(range); VALUE e = RANGE_END(range); int c = rb_cmpint(rb_objs_cmp(b, e), b, e); if (c > 0 || (c == 0 && EXCL(range))) return Qnil; return b; } }
static VALUE range_min(int argc, VALUE *argv, VALUE range) { if (rb_block_given_p()) { return rb_call_super(argc, argv); } else if (argc != 0) { return range_first(argc, argv, range); } else { VALUE b = RANGE_BEG(range); VALUE e = RANGE_END(range); int c = rb_cmpint(rb_funcall(b, id_cmp, 1, e), b, e); if (c > 0 || (c == 0 && EXCL(range))) return Qnil; return b; } }
static int cmpint(VALUE x, VALUE y) { return rb_cmpint(rb_cmp(x, y), x, y); }
static VALUE range_step(int argc, VALUE *argv, VALUE range) { VALUE b, e, step; long unit; RETURN_ENUMERATOR(range, argc, argv); b = RANGE_BEG(range); e = RANGE_END(range); if (rb_scan_args(argc, argv, "01", &step) == 0) { step = INT2FIX(1); unit = 1; } else if (FIXNUM_P(step)) { unit = NUM2LONG(step); } else { VALUE tmp = rb_to_int(step); unit = rb_cmpint(tmp, step, INT2FIX(0)); step = tmp; } if (unit < 0) { rb_raise(rb_eArgError, "step can't be negative"); } if (unit == 0) rb_raise(rb_eArgError, "step can't be 0"); if (FIXNUM_P(b) && FIXNUM_P(e) && FIXNUM_P(step)) { /* fixnums are special */ long end = FIX2LONG(e); long i; if (!EXCL(range)) end += 1; i = FIX2LONG(b); while (i < end) { rb_yield(LONG2NUM(i)); if (i + unit < i) break; i += unit; } } else { VALUE tmp = rb_check_string_type(b); if (!NIL_P(tmp)) { VALUE args[2], iter[2]; b = tmp; args[0] = e; args[1] = EXCL(range) ? Qtrue : Qfalse; iter[0] = INT2FIX(1); iter[1] = step; rb_block_call(b, rb_intern("upto"), 2, args, step_i, (VALUE)iter); } else if (rb_obj_is_kind_of(b, rb_cNumeric)) { ID c = rb_intern(EXCL(range) ? "<" : "<="); if (rb_equal(step, INT2FIX(0))) rb_raise(rb_eArgError, "step can't be 0"); while (RTEST(rb_funcall(b, c, 1, e))) { rb_yield(b); b = rb_funcall(b, '+', 1, step); } } else { VALUE args[2]; if (!rb_respond_to(b, id_succ)) { rb_raise(rb_eTypeError, "can't iterate from %s", rb_obj_classname(b)); } args[0] = INT2FIX(1); args[1] = step; range_each_func(range, step_i, b, e, args); } } return range; }
static VALUE range_bsearch(VALUE range) { VALUE beg, end; int smaller, satisfied = 0; /* Implementation notes: * Floats are handled by mapping them to 64 bits integers. * Apart from sign issues, floats and their 64 bits integer have the * same order, assuming they are represented as exponent followed * by the mantissa. This is true with or without implicit bit. * * Finding the average of two ints needs to be careful about * potential overflow (since float to long can use 64 bits) * as well as the fact that -1/2 can be 0 or -1 in C89. * * Note that -0.0 is mapped to the same int as 0.0 as we don't want * (-1...0.0).bsearch to yield -0.0. */ #define BSEARCH_CHECK(val) \ do { \ VALUE v = rb_yield(val); \ if (FIXNUM_P(v)) { \ if (FIX2INT(v) == 0) return val; \ smaller = FIX2INT(v) < 0; \ } \ else if (v == Qtrue) { \ satisfied = 1; \ smaller = 1; \ } \ else if (v == Qfalse || v == Qnil) { \ smaller = 0; \ } \ else if (rb_obj_is_kind_of(v, rb_cNumeric)) { \ int cmp = rb_cmpint(rb_funcall(v, id_cmp, 1, INT2FIX(0)), v, INT2FIX(0)); \ if (!cmp) return val; \ smaller = cmp < 0; \ } \ else { \ rb_raise(rb_eTypeError, "wrong argument type %s" \ " (must be numeric, true, false or nil)", \ rb_obj_classname(v)); \ } \ } while (0) #define BSEARCH(conv) \ do { \ RETURN_ENUMERATOR(range, 0, 0); \ if (EXCL(range)) high--; \ org_high = high; \ while (low < high) { \ mid = ((high < 0) == (low < 0)) ? low + ((high - low) / 2) \ : (low < -high) ? -((-1 - low - high)/2 + 1) : (low + high) / 2; \ BSEARCH_CHECK(conv(mid)); \ if (smaller) { \ high = mid; \ } \ else { \ low = mid + 1; \ } \ } \ if (low == org_high) { \ BSEARCH_CHECK(conv(low)); \ if (!smaller) return Qnil; \ } \ if (!satisfied) return Qnil; \ return conv(low); \ } while (0) beg = RANGE_BEG(range); end = RANGE_END(range); if (FIXNUM_P(beg) && FIXNUM_P(end)) { long low = FIX2LONG(beg); long high = FIX2LONG(end); long mid, org_high; BSEARCH(INT2FIX); } #if SIZEOF_DOUBLE == 8 && defined(HAVE_INT64_T) else if (RB_TYPE_P(beg, T_FLOAT) || RB_TYPE_P(end, T_FLOAT)) { int64_t low = double_as_int64(RFLOAT_VALUE(rb_Float(beg))); int64_t high = double_as_int64(RFLOAT_VALUE(rb_Float(end))); int64_t mid, org_high; BSEARCH(int64_as_double_to_num); } #endif else if (is_integer_p(beg) && is_integer_p(end)) { VALUE low = rb_to_int(beg); VALUE high = rb_to_int(end); VALUE mid, org_high; RETURN_ENUMERATOR(range, 0, 0); if (EXCL(range)) high = rb_funcall(high, '-', 1, INT2FIX(1)); org_high = high; while (rb_cmpint(rb_funcall(low, id_cmp, 1, high), low, high) < 0) { mid = rb_funcall(rb_funcall(high, '+', 1, low), id_div, 1, INT2FIX(2)); BSEARCH_CHECK(mid); if (smaller) { high = mid; } else { low = rb_funcall(mid, '+', 1, INT2FIX(1)); } } if (rb_equal(low, org_high)) { BSEARCH_CHECK(low); if (!smaller) return Qnil; } if (!satisfied) return Qnil; return low; } else { rb_raise(rb_eTypeError, "can't do binary search for %s", rb_obj_classname(beg)); } return range; }
static VALUE numeric_spec_rb_cmpint(VALUE self, VALUE val, VALUE b) { return INT2FIX(rb_cmpint(val, val, b)); }