ext/cumo/narray/index.c in cumo-0.2.4 vs ext/cumo/narray/index.c in cumo-0.2.5

- old
+ new

@@ -10,27 +10,10 @@ #define cIndex cumo_cInt64 #elif SIZEOF_VOIDP == 4 #define cIndex cumo_cInt32 #endif -// from ruby/enumerator.c -struct enumerator { - VALUE obj; - ID meth; - VALUE args; - // use only above in this source - VALUE fib; - VALUE dst; - VALUE lookahead; - VALUE feedvalue; - VALUE stop_exc; - VALUE size; - // incompatible below depending on ruby version - //VALUE procs; // ruby 2.4 - //rb_enumerator_size_func *size_fn; // ruby 2.1-2.4 - //VALUE (*size_fn)(ANYARGS); // ruby 2.0 -}; // note: the memory refed by this pointer is not freed and causes memroy leak. // // @example // a[1..3,1] generates two cumo_na_index_arg_t(s). First is for 1..3, and second is for 1. @@ -202,10 +185,46 @@ int n; VALUE excl_end; ssize_t beg, end, beg_orig, end_orig; const char *dot = "..", *edot = "..."; +#ifdef HAVE_RB_ARITHMETIC_SEQUENCE_EXTRACT + rb_arithmetic_sequence_components_t x; + rb_arithmetic_sequence_extract(range, &x); + step = NUM2SSIZET(x.step); + + beg = beg_orig = NUM2SSIZET(x.begin); + if (beg < 0) { + beg += size; + } + if (T_NIL == TYPE(x.end)) { // endless range + end = size -1; + if (RTEST(x.exclude_end)) { + dot = edot; + } + } else { + end = end_orig = NUM2SSIZET(x.end); + if (end < 0) { + end += size; + } + if (RTEST(x.exclude_end)) { + end--; + dot = edot; + } + } + if (beg < 0 || beg >= size || end < 0 || end >= size) { + if (T_NIL == TYPE(x.end)) { // endless range + rb_raise(rb_eRangeError, + "%"SZF"d%s is out of range for size=%"SZF"d", + beg_orig, dot, size); + } else { + rb_raise(rb_eRangeError, + "%"SZF"d%s%"SZF"d is out of range for size=%"SZF"d", + beg_orig, dot, end_orig, size); + } + } +#else beg = beg_orig = NUM2SSIZET(rb_funcall(range,cumo_id_beg,0)); if (beg < 0) { beg += size; } end = end_orig = NUM2SSIZET(rb_funcall(range,cumo_id_end,0)); @@ -220,50 +239,65 @@ if (beg < 0 || beg >= size || end < 0 || end >= size) { rb_raise(rb_eRangeError, "%"SZF"d%s%"SZF"d is out of range for size=%"SZF"d", beg_orig, dot, end_orig, size); } +#endif n = (end-beg)/step+1; if (n<0) n=0; cumo_na_index_set_step(q,orig_dim,n,beg,step); } -static void -cumo_na_parse_enumerator(VALUE enum_obj, int orig_dim, ssize_t size, cumo_na_index_arg_t *q) +void +cumo_na_parse_enumerator_step(VALUE enum_obj, VALUE *pstep) { int len; - ssize_t step; - struct enumerator *e; + VALUE step; + cumo_enumerator_t *e; if (!RB_TYPE_P(enum_obj, T_DATA)) { rb_raise(rb_eTypeError,"wrong argument type (not T_DATA)"); } - e = (struct enumerator *)DATA_PTR(enum_obj); + e = (cumo_enumerator_t *)DATA_PTR(enum_obj); - if (rb_obj_is_kind_of(e->obj, rb_cRange)) { - if (e->meth == cumo_id_each) { - cumo_na_parse_range(e->obj, 1, orig_dim, size, q); + if (!rb_obj_is_kind_of(e->obj, rb_cRange)) { + rb_raise(rb_eTypeError,"not Range object"); + } + + if (e->meth == cumo_id_each) { + step = INT2NUM(1); + } + else if (e->meth == cumo_id_step) { + if (TYPE(e->args) != T_ARRAY) { + rb_raise(rb_eArgError,"no argument for step"); } - else if (e->meth == cumo_id_step) { - if (TYPE(e->args) != T_ARRAY) { - rb_raise(rb_eArgError,"no argument for step"); - } - len = RARRAY_LEN(e->args); - if (len != 1) { - rb_raise(rb_eArgError,"invalid number of step argument (1 for %d)",len); - } - step = NUM2SSIZET(RARRAY_AREF(e->args,0)); - cumo_na_parse_range(e->obj, step, orig_dim, size, q); - } else { - rb_raise(rb_eTypeError,"unknown Range method: %s",rb_id2name(e->meth)); + len = RARRAY_LEN(e->args); + if (len != 1) { + rb_raise(rb_eArgError,"invalid number of step argument (1 for %d)",len); } + step = RARRAY_AREF(e->args,0); } else { - rb_raise(rb_eTypeError,"not Range object"); + rb_raise(rb_eTypeError,"unknown Range method: %s",rb_id2name(e->meth)); } + if (pstep) *pstep = step; } +static void +cumo_na_parse_enumerator(VALUE enum_obj, int orig_dim, ssize_t size, cumo_na_index_arg_t *q) +{ + VALUE step; + cumo_enumerator_t *e; + + if (!RB_TYPE_P(enum_obj, T_DATA)) { + rb_raise(rb_eTypeError,"wrong argument type (not T_DATA)"); + } + cumo_na_parse_enumerator_step(enum_obj, &step); + e = (cumo_enumerator_t *)DATA_PTR(enum_obj); + cumo_na_parse_range(e->obj, NUM2SSIZET(step), orig_dim, size, q); // e->obj : Range Object +} + // Analyze *a* which is *i*-th index object and store the information to q // // a: a ruby object of i-th index // size: size of i-th dimension of original NArray // i: parse i-th index @@ -314,16 +348,16 @@ default: if (rb_obj_is_kind_of(a, rb_cRange)) { cumo_na_parse_range(a, 1, i, size, q); } +#ifdef HAVE_RB_ARITHMETIC_SEQUENCE_EXTRACT + else if (rb_obj_is_kind_of(a, rb_cArithSeq)) { + cumo_na_parse_range(a, 1, i, size, q); + } +#endif else if (rb_obj_is_kind_of(a, rb_cEnumerator)) { cumo_na_parse_enumerator(a, i, size, q); - } - else if (rb_obj_is_kind_of(a, cumo_na_cStep)) { - ssize_t beg, step, n; - cumo_na_step_array_index(a, size, (size_t*)(&n), &beg, &step); - cumo_na_index_set_step(q,i,n,beg,step); } // NArray index else if (CUMO_NA_CumoIsNArray(a)) { cumo_na_parse_narray_index(a, i, size, q); }