Class: Enumerator::ArithmeticSequence
- Inherits:
-
Enumerator
- Object
- Enumerator
- Enumerator::ArithmeticSequence
- Defined in:
- enumerator.c,
enumerator.c
Overview
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.
The class can be used for slicing Array (see Array#slice) or custom collections.
Instance Method Summary collapse
-
#==(obj) ⇒ Boolean
Returns
true
only ifobj
is an Enumerator::ArithmeticSequence, has equivalent begin, end, step, and exclude_end? settings. -
#==(obj) ⇒ Boolean
Returns
true
only ifobj
is an Enumerator::ArithmeticSequence, has equivalent begin, end, step, and exclude_end? settings. - #begin ⇒ Object
- #each ⇒ Object
- #end ⇒ Object
-
#==(obj) ⇒ Boolean
Returns
true
only ifobj
is an Enumerator::ArithmeticSequence, has equivalent begin, end, step, and exclude_end? settings. - #exclude_end? ⇒ Boolean
-
#first(*args) ⇒ Object
Returns the first number in this arithmetic sequence, or an array of the first
n
elements. -
#hash ⇒ Integer
Compute a hash-value for this arithmetic sequence.
-
#inspect ⇒ String
Convert this arithmetic sequence to a printable form.
-
#last(*args) ⇒ Object
Returns the last number in this arithmetic sequence, or an array of the last
n
elements. -
#size ⇒ Numeric?
Returns the number of elements in this arithmetic sequence if it is a finite sequence.
- #step ⇒ Object
Methods inherited from Enumerator
#+, #each_with_index, #each_with_object, #feed, #initialize, #initialize_copy, #next, #next_values, #peek, #peek_values, produce, product, #rewind, #with_index, #with_object
Methods included from Enumerable
#all?, #any?, #chain, #chunk, #chunk_while, #collect, #collect_concat, #compact, #count, #cycle, #detect, #drop, #drop_while, #each_cons, #each_entry, #each_slice, #each_with_index, #each_with_object, #entries, #filter, #filter_map, #find, #find_all, #find_index, #flat_map, #grep, #grep_v, #group_by, #include?, #inject, #lazy, #map, #max, #max_by, #member?, #min, #min_by, #minmax, #minmax_by, #none?, #one?, #partition, #reduce, #reject, #reverse_each, #select, #slice_after, #slice_before, #slice_when, #sort, #sort_by, #sum, #take, #take_while, #tally, #to_a, #to_h, #uniq, #zip
Constructor Details
This class inherits a constructor from Enumerator
Instance Method Details
#==(obj) ⇒ Boolean
Returns true
only if obj
is an Enumerator::ArithmeticSequence, has equivalent begin, end, step, and exclude_end? settings.
4260 4261 4262 4263 4264 4265 4266 4267 4268 4269 4270 4271 4272 4273 4274 4275 4276 4277 4278 4279 4280 4281 4282 4283 4284 |
# File 'enumerator.c', line 4260
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;
}
|
#==(obj) ⇒ Boolean
Returns true
only if obj
is an Enumerator::ArithmeticSequence, has equivalent begin, end, step, and exclude_end? settings.
4260 4261 4262 4263 4264 4265 4266 4267 4268 4269 4270 4271 4272 4273 4274 4275 4276 4277 4278 4279 4280 4281 4282 4283 4284 |
# File 'enumerator.c', line 4260
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;
}
|
#begin ⇒ Object
#each {|i| ... } ⇒ Object #each ⇒ Object
4328 4329 4330 4331 4332 4333 4334 4335 4336 4337 4338 4339 4340 4341 4342 4343 4344 4345 4346 4347 4348 4349 4350 4351 4352 4353 4354 4355 4356 4357 4358 4359 4360 4361 4362 4363 4364 4365 4366 4367 4368 4369 4370 4371 4372 4373 4374 4375 4376 4377 4378 4379 4380 4381 4382 |
# File 'enumerator.c', line 4328
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 = num_idiv(num_minus(e, c), s);
last = num_plus(c, num_mul(s, len_1));
if (x && rb_equal(last, e)) {
last = num_minus(last, s);
}
if (rb_num_negative_int_p(s)) {
while (NUM_GE(c, last)) {
rb_yield(c);
c = num_plus(c, s);
}
}
else {
while (NUM_GE(last, c)) {
rb_yield(c);
c = num_plus(c, s);
}
}
return self;
}
|
#end ⇒ Object
#==(obj) ⇒ Boolean
Returns true
only if obj
is an Enumerator::ArithmeticSequence, has equivalent begin, end, step, and exclude_end? settings.
4260 4261 4262 4263 4264 4265 4266 4267 4268 4269 4270 4271 4272 4273 4274 4275 4276 4277 4278 4279 4280 4281 4282 4283 4284 |
# File 'enumerator.c', line 4260
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;
}
|
#exclude_end? ⇒ Boolean
#first ⇒ Numeric? #first(n) ⇒ Array
Returns the first number in this arithmetic sequence, or an array of the first n
elements.
3901 3902 3903 3904 3905 3906 3907 3908 3909 3910 3911 3912 3913 3914 3915 3916 3917 3918 3919 3920 3921 3922 3923 3924 3925 3926 3927 3928 3929 3930 3931 3932 3933 3934 3935 3936 3937 3938 3939 3940 3941 3942 3943 3944 3945 3946 3947 3948 3949 3950 3951 3952 3953 3954 3955 3956 3957 3958 3959 3960 3961 3962 3963 3964 3965 3966 3967 3968 3969 3970 3971 3972 3973 3974 3975 3976 3977 3978 3979 3980 3981 3982 3983 3984 3985 3986 3987 3988 3989 3990 3991 3992 3993 3994 3995 3996 3997 3998 3999 4000 4001 4002 4003 4004 4005 4006 4007 4008 4009 4010 4011 4012 4013 4014 4015 4016 4017 4018 4019 4020 4021 4022 4023 4024 4025 4026 4027 4028 4029 4030 4031 4032 4033 4034 4035 |
# File 'enumerator.c', line 3901
static VALUE
arith_seq_first(int argc, VALUE *argv, VALUE self)
{
VALUE b, e, s, ary;
long n;
int x;
rb_check_arity(argc, 0, 1);
b = arith_seq_begin(self);
e = arith_seq_end(self);
s = arith_seq_step(self);
if (argc == 0) {
if (NIL_P(b)) {
return Qnil;
}
if (!NIL_P(e)) {
VALUE zero = INT2FIX(0);
int r = rb_cmpint(rb_num_coerce_cmp(s, zero, idCmp), s, zero);
if (r > 0 && RTEST(rb_funcall(b, '>', 1, e))) {
return Qnil;
}
if (r < 0 && RTEST(rb_funcall(b, '<', 1, e))) {
return Qnil;
}
}
return b;
}
// TODO: the following code should be extracted as arith_seq_take
n = NUM2LONG(argv[0]);
if (n < 0) {
rb_raise(rb_eArgError, "attempt to take negative size");
}
if (n == 0) {
return rb_ary_new_capa(0);
}
x = arith_seq_exclude_end_p(self);
if (FIXNUM_P(b) && NIL_P(e) && FIXNUM_P(s)) {
long i = FIX2LONG(b), unit = FIX2LONG(s);
ary = rb_ary_new_capa(n);
while (n > 0 && FIXABLE(i)) {
rb_ary_push(ary, LONG2FIX(i));
i += unit; // FIXABLE + FIXABLE never overflow;
--n;
}
if (n > 0) {
b = LONG2NUM(i);
while (n > 0) {
rb_ary_push(ary, b);
b = rb_big_plus(b, s);
--n;
}
}
return ary;
}
else if (FIXNUM_P(b) && FIXNUM_P(e) && FIXNUM_P(s)) {
long i = FIX2LONG(b);
long end = FIX2LONG(e);
long unit = FIX2LONG(s);
long len;
if (unit >= 0) {
if (!x) end += 1;
len = end - i;
if (len < 0) len = 0;
ary = rb_ary_new_capa((n < len) ? n : len);
while (n > 0 && i < end) {
rb_ary_push(ary, LONG2FIX(i));
if (i + unit < i) break;
i += unit;
--n;
}
}
else {
if (!x) end -= 1;
len = i - end;
if (len < 0) len = 0;
ary = rb_ary_new_capa((n < len) ? n : len);
while (n > 0 && i > end) {
rb_ary_push(ary, LONG2FIX(i));
if (i + unit > i) break;
i += unit;
--n;
}
}
return ary;
}
else if (RB_FLOAT_TYPE_P(b) || RB_FLOAT_TYPE_P(e) || RB_FLOAT_TYPE_P(s)) {
/* generate values like ruby_float_step */
double unit = NUM2DBL(s);
double beg = NUM2DBL(b);
double end = NIL_P(e) ? (unit < 0 ? -1 : 1)*HUGE_VAL : NUM2DBL(e);
double len = ruby_float_step_size(beg, end, unit, x);
long i;
if (n > len)
n = (long)len;
if (isinf(unit)) {
if (len > 0) {
ary = rb_ary_new_capa(1);
rb_ary_push(ary, DBL2NUM(beg));
}
else {
ary = rb_ary_new_capa(0);
}
}
else if (unit == 0) {
VALUE val = DBL2NUM(beg);
ary = rb_ary_new_capa(n);
for (i = 0; i < len; ++i) {
rb_ary_push(ary, val);
}
}
else {
ary = rb_ary_new_capa(n);
for (i = 0; i < n; ++i) {
double d = i*unit+beg;
if (unit >= 0 ? end < d : d < end) d = end;
rb_ary_push(ary, DBL2NUM(d));
}
}
return ary;
}
return rb_call_super(argc, argv);
}
|
#hash ⇒ Integer
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.
4296 4297 4298 4299 4300 4301 4302 4303 4304 4305 4306 4307 4308 4309 4310 4311 4312 |
# File 'enumerator.c', line 4296
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 ST2FIX(hash);
}
|
#inspect ⇒ String
Convert this arithmetic sequence to a printable form.
4196 4197 4198 4199 4200 4201 4202 4203 4204 4205 4206 4207 4208 4209 4210 4211 4212 4213 4214 4215 4216 4217 4218 4219 4220 4221 4222 4223 4224 4225 4226 4227 4228 4229 4230 4231 4232 4233 4234 4235 4236 4237 4238 4239 4240 4241 4242 4243 4244 4245 4246 4247 4248 4249 4250 4251 |
# File 'enumerator.c', line 4196
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, ", ");
}
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;
}
|
#last ⇒ Numeric? #last(n) ⇒ Array
Returns the last number in this arithmetic sequence, or an array of the last n
elements.
4127 4128 4129 4130 4131 4132 4133 4134 4135 4136 4137 4138 4139 4140 4141 4142 4143 4144 4145 4146 4147 4148 4149 4150 4151 4152 4153 4154 4155 4156 4157 4158 4159 4160 4161 4162 4163 4164 4165 4166 4167 4168 4169 4170 4171 4172 4173 4174 4175 4176 4177 4178 4179 4180 4181 4182 4183 4184 4185 4186 4187 4188 |
# File 'enumerator.c', line 4127
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 = num_idiv(num_minus(e, b), s);
if (rb_num_negative_int_p(len_1)) {
if (argc == 0) {
return Qnil;
}
return rb_ary_new_capa(0);
}
last = num_plus(b, num_mul(s, len_1));
if ((last_is_adjusted = arith_seq_exclude_end_p(self) && rb_equal(last, e))) {
last = num_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;
}
|
#size ⇒ Numeric?
Returns the number of elements in this arithmetic sequence if it is a finite sequence. Otherwise, returns nil
.
4391 4392 4393 4394 4395 4396 4397 4398 4399 4400 4401 4402 4403 4404 4405 4406 4407 4408 4409 4410 4411 4412 4413 4414 4415 4416 4417 4418 4419 4420 4421 4422 4423 4424 4425 4426 4427 4428 4429 4430 4431 4432 4433 4434 4435 4436 4437 4438 4439 4440 4441 4442 4443 4444 4445 4446 4447 4448 4449 |
# File 'enumerator.c', line 4391
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 = ruby_float_step_size(NUM2DBL(b), ee, NUM2DBL(s), x);
if (isinf(n)) return DBL2NUM(n);
if (POSFIXABLE(n)) return LONG2FIX((long)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;
}
|