Enumerator::ArithmeticSequence is a subclass of Enumerator, that is a representation of sequences of numbers with common difference. Instances of this class can be generated by the Range#step and Numeric#step methods.
Returns true
only if obj
is an Enumerator::ArithmeticSequence, has
equivalent begin, end, step, and exclude_end? settings.
static VALUE arith_seq_eq(VALUE self, VALUE other) { if (!RTEST(rb_obj_is_kind_of(other, rb_cArithSeq))) { return Qfalse; } if (!rb_equal(arith_seq_begin(self), arith_seq_begin(other))) { return Qfalse; } if (!rb_equal(arith_seq_end(self), arith_seq_end(other))) { return Qfalse; } if (!rb_equal(arith_seq_step(self), arith_seq_step(other))) { return Qfalse; } if (arith_seq_exclude_end_p(self) != arith_seq_exclude_end_p(other)) { return Qfalse; } return Qtrue; }
Returns true
only if obj
is an Enumerator::ArithmeticSequence, has
equivalent begin, end, step, and exclude_end? settings.
static VALUE arith_seq_eq(VALUE self, VALUE other) { if (!RTEST(rb_obj_is_kind_of(other, rb_cArithSeq))) { return Qfalse; } if (!rb_equal(arith_seq_begin(self), arith_seq_begin(other))) { return Qfalse; } if (!rb_equal(arith_seq_end(self), arith_seq_end(other))) { return Qfalse; } if (!rb_equal(arith_seq_step(self), arith_seq_step(other))) { return Qfalse; } if (arith_seq_exclude_end_p(self) != arith_seq_exclude_end_p(other)) { return Qfalse; } return Qtrue; }
inline VALUE arith_seq_begin(VALUE self) { return rb_ivar_get(self, id_begin); }
static VALUE arith_seq_each(VALUE self) { VALUE c, e, s, len_1, last; int x; if (!rb_block_given_p()) return self; c = arith_seq_begin(self); e = arith_seq_end(self); s = arith_seq_step(self); x = arith_seq_exclude_end_p(self); if (!RB_TYPE_P(s, T_COMPLEX) && ruby_float_step(c, e, s, x, TRUE)) { return self; } if (NIL_P(e)) { while (1) { rb_yield(c); c = rb_int_plus(c, s); } return self; } if (rb_equal(s, INT2FIX(0))) { while (1) { rb_yield(c); } return self; } len_1 = rb_int_idiv(rb_int_minus(e, c), s); last = rb_int_plus(c, rb_int_mul(s, len_1)); if (x && rb_equal(last, e)) { last = rb_int_minus(last, s); } if (rb_num_negative_int_p(s)) { while (RTEST(rb_int_ge(c, last))) { rb_yield(c); c = rb_int_plus(c, s); } } else { while (RTEST(rb_int_ge(last, c))) { rb_yield(c); c = rb_int_plus(c, s); } } return self; }
inline VALUE arith_seq_end(VALUE self) { return rb_ivar_get(self, id_end); }
Returns true
only if obj
is an Enumerator::ArithmeticSequence, has
equivalent begin, end, step, and exclude_end? settings.
static VALUE arith_seq_eq(VALUE self, VALUE other) { if (!RTEST(rb_obj_is_kind_of(other, rb_cArithSeq))) { return Qfalse; } if (!rb_equal(arith_seq_begin(self), arith_seq_begin(other))) { return Qfalse; } if (!rb_equal(arith_seq_end(self), arith_seq_end(other))) { return Qfalse; } if (!rb_equal(arith_seq_step(self), arith_seq_step(other))) { return Qfalse; } if (arith_seq_exclude_end_p(self) != arith_seq_exclude_end_p(other)) { return Qfalse; } return Qtrue; }
inline VALUE arith_seq_exclude_end(VALUE self) { return rb_ivar_get(self, id_exclude_end); }
Returns the first number in this arithmetic sequence, or an array of the
first n
elements.
static VALUE arith_seq_first(int argc, VALUE *argv, VALUE self) { VALUE b, e, s, len_1; b = arith_seq_begin(self); e = arith_seq_end(self); s = arith_seq_step(self); if (!NIL_P(e)) { len_1 = rb_int_idiv(rb_int_minus(e, b), s); if (rb_num_negative_int_p(len_1)) { if (argc == 0) { return Qnil; } return rb_ary_new_capa(0); } } if (argc == 0) { return b; } /* TODO: optimization */ return rb_call_super(argc, argv); }
Compute a hash-value for this arithmetic sequence. Two arithmetic sequences with same begin, end, step, and exclude_end? values will generate the same hash-value.
See also Object#hash.
static VALUE arith_seq_hash(VALUE self) { st_index_t hash; VALUE v; hash = rb_hash_start(arith_seq_exclude_end_p(self)); v = rb_hash(arith_seq_begin(self)); hash = rb_hash_uint(hash, NUM2LONG(v)); v = rb_hash(arith_seq_end(self)); hash = rb_hash_uint(hash, NUM2LONG(v)); v = rb_hash(arith_seq_step(self)); hash = rb_hash_uint(hash, NUM2LONG(v)); hash = rb_hash_end(hash); return LONG2FIX(hash); }
Convert this arithmetic sequence to a printable form.
static VALUE arith_seq_inspect(VALUE self) { struct enumerator *e; VALUE eobj, str, eargs; int range_p; TypedData_Get_Struct(self, struct enumerator, &enumerator_data_type, e); eobj = rb_attr_get(self, id_receiver); if (NIL_P(eobj)) { eobj = e->obj; } range_p = RTEST(rb_obj_is_kind_of(eobj, rb_cRange)); str = rb_sprintf("(%s%"PRIsVALUE"%s.", range_p ? "(" : "", eobj, range_p ? ")" : ""); rb_str_buf_append(str, rb_id2str(e->meth)); eargs = rb_attr_get(eobj, id_arguments); if (NIL_P(eargs)) { eargs = e->args; } if (eargs != Qfalse) { long argc = RARRAY_LEN(eargs); const VALUE *argv = RARRAY_CONST_PTR(eargs); /* WB: no new reference */ if (argc > 0) { VALUE kwds = Qnil; rb_str_buf_cat2(str, "("); if (RB_TYPE_P(argv[argc-1], T_HASH)) { int all_key = TRUE; rb_hash_foreach(argv[argc-1], key_symbol_p, (VALUE)&all_key); if (all_key) kwds = argv[--argc]; } while (argc--) { VALUE arg = *argv++; rb_str_append(str, rb_inspect(arg)); rb_str_buf_cat2(str, ", "); OBJ_INFECT(str, arg); } if (!NIL_P(kwds)) { rb_hash_foreach(kwds, kwd_append, str); } rb_str_set_len(str, RSTRING_LEN(str)-2); /* drop the last ", " */ rb_str_buf_cat2(str, ")"); } } rb_str_buf_cat2(str, ")"); return str; }
Returns the last number in this arithmetic sequence, or an array of the
last n
elements.
static VALUE arith_seq_last(int argc, VALUE *argv, VALUE self) { VALUE b, e, s, len_1, len, last, nv, ary; int last_is_adjusted; long n; e = arith_seq_end(self); if (NIL_P(e)) { rb_raise(rb_eRangeError, "cannot get the last element of endless arithmetic sequence"); } b = arith_seq_begin(self); s = arith_seq_step(self); len_1 = rb_int_idiv(rb_int_minus(e, b), s); if (rb_num_negative_int_p(len_1)) { if (argc == 0) { return Qnil; } return rb_ary_new_capa(0); } last = rb_int_plus(b, rb_int_mul(s, len_1)); if ((last_is_adjusted = arith_seq_exclude_end_p(self) && rb_equal(last, e))) { last = rb_int_minus(last, s); } if (argc == 0) { return last; } if (last_is_adjusted) { len = len_1; } else { len = rb_int_plus(len_1, INT2FIX(1)); } rb_scan_args(argc, argv, "1", &nv); if (!RB_INTEGER_TYPE_P(nv)) { nv = rb_to_int(nv); } if (RTEST(rb_int_gt(nv, len))) { nv = len; } n = NUM2LONG(nv); if (n < 0) { rb_raise(rb_eArgError, "negative array size"); } ary = rb_ary_new_capa(n); b = rb_int_minus(last, rb_int_mul(s, nv)); while (n) { b = rb_int_plus(b, s); rb_ary_push(ary, b); --n; } return ary; }
Returns the number of elements in this arithmetic sequence if it is a
finite sequence. Otherwise, returns nil
.
static VALUE arith_seq_size(VALUE self) { VALUE b, e, s, len_1, len, last; int x; b = arith_seq_begin(self); e = arith_seq_end(self); s = arith_seq_step(self); x = arith_seq_exclude_end_p(self); if (RB_FLOAT_TYPE_P(b) || RB_FLOAT_TYPE_P(e) || RB_FLOAT_TYPE_P(s)) { double ee, n; if (NIL_P(e)) { if (rb_num_negative_int_p(s)) { ee = -HUGE_VAL; } else { ee = HUGE_VAL; } } else { ee = NUM2DBL(e); } n = arith_seq_float_step_size(NUM2DBL(b), ee, NUM2DBL(s), x); if (isinf(n)) return DBL2NUM(n); if (POSFIXABLE(n)) return LONG2FIX(n); return rb_dbl2big(n); } if (NIL_P(e)) { return DBL2NUM(HUGE_VAL); } if (!rb_obj_is_kind_of(s, rb_cNumeric)) { s = rb_to_int(s); } if (rb_equal(s, INT2FIX(0))) { return DBL2NUM(HUGE_VAL); } len_1 = rb_int_idiv(rb_int_minus(e, b), s); if (rb_num_negative_int_p(len_1)) { return INT2FIX(0); } last = rb_int_plus(b, rb_int_mul(s, len_1)); if (x && rb_equal(last, e)) { len = len_1; } else { len = rb_int_plus(len_1, INT2FIX(1)); } return len; }