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;
}