ext/numo/narray/step.c in numo-narray-0.9.1.4 vs ext/numo/narray/step.c in numo-narray-0.9.1.5
- old
+ new
@@ -1,9 +1,9 @@
/*
step.c
- Numerical Array Extension for Ruby
- (C) Copyright 2007,2013 by Masahiro TANAKA
+ Ruby/Numo::NArray - Numerical Array class for Ruby
+ Copyright (C) 2007-2019 Masahiro TANAKA
*/
#include <ruby.h>
#include <math.h>
#include "numo/narray.h"
@@ -22,195 +22,55 @@
#ifndef DBL_EPSILON
#define DBL_EPSILON 2.2204460492503131e-16
#endif
-static ID id_beg, id_end, id_len, id_step, id_excl;
+static ID id_beg, id_end, id_len, id_step;
-//#define EXCL(r) RTEST(rb_ivar_get((r), id_excl))
+
#define EXCL(r) RTEST(rb_funcall((r), rb_intern("exclude_end?"), 0))
-#define SET_EXCL(r,v) rb_ivar_set((r), id_excl, (v) ? Qtrue : Qfalse)
-
-static void
-step_init(
- VALUE self,
- VALUE beg,
- VALUE end,
- VALUE step,
- VALUE len,
- VALUE excl
-)
-{
- if (RTEST(len)) {
- if (!(FIXNUM_P(len) || TYPE(len)==T_BIGNUM)) {
- rb_raise(rb_eArgError, "length must be Integer");
- }
- if (RTEST(rb_funcall(len,rb_intern("<"),1,INT2FIX(0)))) {
- rb_raise(rb_eRangeError,"length must be non negative");
- }
- }
- rb_ivar_set(self, id_beg, beg);
- rb_ivar_set(self, id_end, end);
- rb_ivar_set(self, id_len, len);
- rb_ivar_set(self, id_step, step);
- SET_EXCL(self, excl);
-}
-
-static VALUE
-nary_step_new2(
- VALUE range,
- VALUE step,
- VALUE len
-)
-{
- VALUE beg, end, excl;
- VALUE self = rb_obj_alloc(na_cStep);
-
- //beg = rb_ivar_get(range, id_beg);
- beg = rb_funcall(range, id_beg, 0);
- //end = rb_ivar_get(range, id_end);
- end = rb_funcall(range, id_end, 0);
- excl = rb_funcall(range, rb_intern("exclude_end?"), 0);
-
- step_init(self, beg, end, step, len, excl);
- return self;
-}
-
-
/*
* call-seq:
- * Step.new(start, end, step=nil, length=nil) => step
- * Step.new(range, step=nil, length=nil) => step
- *
- * Constructs a step using three parameters among <i>start</i>,
- * <i>end</i>, <i>step</i> and <i>length</i>. <i>start</i>,
- * <i>end</i> parameters can be replaced with <i>range</i>. If the
- * <i>step</i> is omitted (or supplied with nil), then calculated
- * from <i>length</i> or definded as 1.
- */
-
-static VALUE
-step_initialize( int argc, VALUE *argv, VALUE self )
-{
- VALUE a, b=Qnil, c=Qnil, d=Qnil, e=Qnil;
-
- rb_scan_args(argc, argv, "13", &a, &b, &c, &d);
- /* Selfs are immutable, so that they should be initialized only once. */
- if (rb_ivar_defined(self, id_beg)) {
- rb_name_error(rb_intern("initialize"), "`initialize' called twice");
- }
- if (rb_obj_is_kind_of(a,rb_cRange)) {
- if (argc>3) {
- rb_raise(rb_eArgError, "extra argument");
- }
- d = c;
- c = b;
- e = rb_funcall(a, rb_intern("exclude_end?"), 0);
- //b = rb_ivar_get(a, id_end);
- b = rb_funcall(a, id_end, 0);
- //a = rb_ivar_get(a, id_beg);
- a = rb_funcall(a, id_beg, 0);
- }
- step_init(self, a, b, c, d, e);
- return Qnil;
-}
-
-/*
- * call-seq:
- * step.begin => obj
- * step.first => obj
- *
- * Returns the start of <i>step</i>.
- */
-
-static VALUE
-step_first( VALUE self )
-{
- return rb_ivar_get(self, id_beg);
-}
-
-/*
- * call-seq:
- * step.end => obj
- * step.last => obj
- *
- * Returns the object that defines the end of <i>step</i>.
- */
-
-static VALUE
-step_last( VALUE self )
-{
- return rb_ivar_get(self, id_end);
-}
-
-/*
- * call-seq:
- * step.length => obj
- * step.size => obj
- *
- * Returns the length of <i>step</i>.
- */
-
-static VALUE
-step_length( VALUE self )
-{
- return rb_ivar_get(self, id_len);
-}
-
-/*
- * call-seq:
- * step.step => obj
- *
- * Returns the step of <i>step</i>.
- */
-
-static VALUE
-step_step( VALUE self )
-{
- return rb_ivar_get(self, id_step);
-}
-
-/*
- * call-seq:
- * step.exclude_end? => true or false
- *
- * Returns <code>true</code> if <i>step</i> excludes its end value.
- */
-static VALUE
-step_exclude_end_p(VALUE self)
-{
- return RTEST(rb_ivar_get(self, id_excl)) ? Qtrue : Qfalse;
-}
-
-
-/*
- * call-seq:
* step.parameters([array_size]) => [start,step,length]
*
* Returns the iteration parameters of <i>step</i>. If
* <i>array_sizse</i> is given, negative array index is considered.
*/
void
-nary_step_array_index(VALUE self, size_t ary_size,
+nary_step_array_index(VALUE obj, size_t ary_size,
size_t *plen, ssize_t *pbeg, ssize_t *pstep)
{
size_t len;
ssize_t beg=0, step=1;
VALUE vbeg, vend, vstep, vlen;
ssize_t end=ary_size;
- //vbeg = rb_ivar_get(self, id_beg);
- //vend = rb_ivar_get(self, id_end);
- vlen = rb_ivar_get(self, id_len);
- vstep = rb_ivar_get(self, id_step);
- vbeg = rb_funcall(self, id_beg, 0);
- vend = rb_funcall(self, id_end, 0);
- //vlen = rb_funcall(self, id_len, 0);
- //vstep = rb_funcall(self, id_step, 0);
+#ifdef HAVE_RB_ARITHMETIC_SEQUENCE_EXTRACT
+ rb_arithmetic_sequence_components_t x;
+ rb_arithmetic_sequence_extract(obj, &x);
+ vstep = x.step;
+ vbeg = x.begin;
+ vend = x.end;
+#else
+ struct enumerator *e;
+
+ if (rb_obj_is_kind_of(obj, rb_cRange)) {
+ vstep = rb_ivar_get(obj, id_step);
+ } else { // Enumerator
+ na_parse_enumerator_step(obj, &vstep);
+ e = (struct enumerator *)DATA_PTR(obj);
+ obj = e->obj; // Range
+ }
+
+ vbeg = rb_funcall(obj, id_beg, 0);
+ vend = rb_funcall(obj, id_end, 0);
+#endif
+ vlen = rb_ivar_get(obj, id_len);
+
if (RTEST(vbeg)) {
beg = NUM2SSIZET(vbeg);
if (beg<0) {
beg += ary_size;
}
@@ -235,11 +95,11 @@
} else {
end = beg + step*(len-1);
}
} else {
if (RTEST(vend)) {
- if (EXCL(self)) {
+ if (EXCL(obj)) {
if (step>0) end--;
if (step<0) end++;
}
beg = end - step*(len-1);
} else {
@@ -249,22 +109,22 @@
}
} else { // no step
step = 1;
if (RTEST(vbeg)) {
if (RTEST(vend)) {
- if (EXCL(self)) {
+ if (EXCL(obj)) {
if (beg<end) end--;
if (beg>end) end++;
}
if (len>1)
step = (end-beg)/(len-1);
} else {
end = beg + (len-1);
}
} else {
if (RTEST(vend)) {
- if (EXCL(self)) {
+ if (EXCL(obj)) {
end--;
}
beg = end - (len-1);
} else {
beg = 0;
@@ -284,11 +144,11 @@
beg = 0;
}
if (!RTEST(vend)) {
end = ary_size-1;
}
- else if (EXCL(self)) {
+ else if (EXCL(obj)) {
end--;
}
if (beg<=end) {
len = (end-beg)/step+1;
} else {
@@ -299,11 +159,11 @@
beg = ary_size-1;
}
if (!RTEST(vend)) {
end = 0;
}
- else if (EXCL(self)) {
+ else if (EXCL(obj)) {
end++;
}
if (beg>=end) {
len = (beg-end)/(-step)+1;
} else {
@@ -325,37 +185,47 @@
if (plen) *plen = len;
if (pbeg) *pbeg = beg;
if (pstep) *pstep = step;
}
-
void
-nary_step_sequence( VALUE self, size_t *plen, double *pbeg, double *pstep )
+nary_step_sequence( VALUE obj, size_t *plen, double *pbeg, double *pstep )
{
- VALUE vbeg, vend, vstep, vlen;
+ VALUE vend, vstep, vlen;
double dbeg, dend, dstep=1, dsize, err;
size_t size, n;
- //vbeg = rb_ivar_get(self, id_beg);
- vbeg = rb_funcall(self, id_beg, 0);
- dbeg = NUM2DBL(vbeg);
+#ifdef HAVE_RB_ARITHMETIC_SEQUENCE_EXTRACT
+ rb_arithmetic_sequence_components_t x;
+ rb_arithmetic_sequence_extract(obj, &x);
- //vend = rb_ivar_get(self, id_end);
- vend = rb_funcall(self, id_end, 0);
+ vstep = x.step;
+ dbeg = NUM2DBL(x.begin);
+ vend = x.end;
+#else
+ struct enumerator *e;
- vlen = rb_ivar_get(self, id_len);
- vstep = rb_ivar_get(self, id_step);
- //vlen = rb_funcall(self, id_len ,0);
- //vstep = rb_funcall(self, id_step,0);
+ if (rb_obj_is_kind_of(obj, rb_cRange)) {
+ vstep = rb_ivar_get(obj, id_step);
+ } else { // Enumerator
+ na_parse_enumerator_step(obj, &vstep);
+ e = (struct enumerator *)DATA_PTR(obj);
+ obj = e->obj; // Range
+ }
+ dbeg = NUM2DBL(rb_funcall(obj, id_beg, 0));
+ vend = rb_funcall(obj, id_end, 0);
+#endif
+ vlen = rb_ivar_get(obj, id_len);
+
if (RTEST(vlen)) {
size = NUM2SIZET(vlen);
if (!RTEST(vstep)) {
if (RTEST(vend)) {
dend = NUM2DBL(vend);
- if (EXCL(self)) {
+ if (EXCL(obj)) {
n = size;
} else {
n = size-1;
}
if (n>0) {
@@ -376,11 +246,11 @@
if (RTEST(vend)) {
dend = NUM2DBL(vend);
err = (fabs(dbeg)+fabs(dend)+fabs(dend-dbeg))/fabs(dstep)*DBL_EPSILON;
if (err>0.5) err=0.5;
dsize = (dend-dbeg)/dstep;
- if (EXCL(self))
+ if (EXCL(obj))
dsize -= err;
else
dsize += err;
dsize = floor(dsize) + 1;
if (dsize<0) dsize=0;
@@ -396,79 +266,15 @@
if (plen) *plen = size;
if (pbeg) *pbeg = dbeg;
if (pstep) *pstep = dstep;
}
-/*
-static VALUE
-step_each( VALUE self )
-{
- VALUE a;
- double beg, step;
- size_t i, size;
-
- a = nary_step_parameters( self, Qnil );
- beg = NUM2DBL(RARRAY_PTR(a)[0]);
- step = NUM2DBL(RARRAY_PTR(a)[1]);
- size = NUM2SIZET(RARRAY_PTR(a)[2]);
-
- for (i=0; i<size; i++) {
- rb_yield(rb_float_new(beg+i*step));
- }
- return self;
-}
-*/
-
-static VALUE
-range_with_step( VALUE range, VALUE step )
-{
- return nary_step_new2( range, step, Qnil );
-}
-
-static VALUE
-range_with_length( VALUE range, VALUE len )
-{
- return nary_step_new2( range, Qnil, len );
-}
-
-
-static VALUE
-nary_s_step( int argc, VALUE *argv, VALUE mod )
-{
- VALUE self = rb_obj_alloc(na_cStep);
- step_initialize(argc, argv, self);
- return self;
-}
-
-
void
Init_nary_step()
{
- na_cStep = rb_define_class_under(cNArray, "Step", rb_cObject);
- rb_include_module(na_cStep, rb_mEnumerable);
- rb_define_method(na_cStep, "initialize", step_initialize, -1);
+ rb_define_alias(rb_cRange, "%", "step");
- //rb_define_method(na_cStep, "each", step_each, 0);
-
- rb_define_method(na_cStep, "first", step_first, 0);
- rb_define_method(na_cStep, "last", step_last, 0);
- rb_define_method(na_cStep, "begin", step_first, 0);
- rb_define_method(na_cStep, "end", step_last, 0);
- rb_define_method(na_cStep, "step", step_step, 0);
- rb_define_method(na_cStep, "length", step_length, 0);
- rb_define_method(na_cStep, "size", step_length, 0);
- rb_define_method(na_cStep, "exclude_end?", step_exclude_end_p, 0);
- //rb_define_method(na_cStep, "to_s", step_to_s, 0);
- //rb_define_method(na_cStep, "inspect", step_inspect, 0);
- //rb_define_method(na_cStep, "parameters", nary_step_parameters, 1);
-
- rb_define_method(rb_cRange, "%", range_with_step, 1);
- rb_define_method(rb_cRange, "*", range_with_length, 1);
-
- rb_define_singleton_method(cNArray, "step", nary_s_step, -1);
-
id_beg = rb_intern("begin");
id_end = rb_intern("end");
id_len = rb_intern("length");
id_step = rb_intern("step");
- id_excl = rb_intern("excl");
}