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, #rewind, #with_index, #with_object
Methods included from Enumerable
#all?, #any?, #chain, #chunk, #chunk_while, #collect, #collect_concat, #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.
3816 3817 3818 3819 3820 3821 3822 3823 3824 3825 3826 3827 3828 3829 3830 3831 3832 3833 3834 3835 3836 3837 3838 3839 3840 |
# File 'enumerator.c', line 3816
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.
3816 3817 3818 3819 3820 3821 3822 3823 3824 3825 3826 3827 3828 3829 3830 3831 3832 3833 3834 3835 3836 3837 3838 3839 3840 |
# File 'enumerator.c', line 3816
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
3884 3885 3886 3887 3888 3889 3890 3891 3892 3893 3894 3895 3896 3897 3898 3899 3900 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 |
# File 'enumerator.c', line 3884
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.
3816 3817 3818 3819 3820 3821 3822 3823 3824 3825 3826 3827 3828 3829 3830 3831 3832 3833 3834 3835 3836 3837 3838 3839 3840 |
# File 'enumerator.c', line 3816
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.
3457 3458 3459 3460 3461 3462 3463 3464 3465 3466 3467 3468 3469 3470 3471 3472 3473 3474 3475 3476 3477 3478 3479 3480 3481 3482 3483 3484 3485 3486 3487 3488 3489 3490 3491 3492 3493 3494 3495 3496 3497 3498 3499 3500 3501 3502 3503 3504 3505 3506 3507 3508 3509 3510 3511 3512 3513 3514 3515 3516 3517 3518 3519 3520 3521 3522 3523 3524 3525 3526 3527 3528 3529 3530 3531 3532 3533 3534 3535 3536 3537 3538 3539 3540 3541 3542 3543 3544 3545 3546 3547 3548 3549 3550 3551 3552 3553 3554 3555 3556 3557 3558 3559 3560 3561 3562 3563 3564 3565 3566 3567 3568 3569 3570 3571 3572 3573 3574 3575 3576 3577 3578 3579 3580 3581 3582 3583 3584 3585 3586 3587 3588 3589 3590 3591 |
# File 'enumerator.c', line 3457
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.
3852 3853 3854 3855 3856 3857 3858 3859 3860 3861 3862 3863 3864 3865 3866 3867 3868 |
# File 'enumerator.c', line 3852
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.
3752 3753 3754 3755 3756 3757 3758 3759 3760 3761 3762 3763 3764 3765 3766 3767 3768 3769 3770 3771 3772 3773 3774 3775 3776 3777 3778 3779 3780 3781 3782 3783 3784 3785 3786 3787 3788 3789 3790 3791 3792 3793 3794 3795 3796 3797 3798 3799 3800 3801 3802 3803 3804 3805 3806 3807 |
# File 'enumerator.c', line 3752
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.
3683 3684 3685 3686 3687 3688 3689 3690 3691 3692 3693 3694 3695 3696 3697 3698 3699 3700 3701 3702 3703 3704 3705 3706 3707 3708 3709 3710 3711 3712 3713 3714 3715 3716 3717 3718 3719 3720 3721 3722 3723 3724 3725 3726 3727 3728 3729 3730 3731 3732 3733 3734 3735 3736 3737 3738 3739 3740 3741 3742 3743 3744 |
# File 'enumerator.c', line 3683
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
.
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 |
# File 'enumerator.c', line 3947
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;
}
|