ext/numo/narray/narray.c in numo-narray-0.9.0.6 vs ext/numo/narray/narray.c in numo-narray-0.9.0.7
- old
+ new
@@ -1446,92 +1446,70 @@
1 : 0 ;
}
}
-VALUE
-na_reduce_dimension(int argc, VALUE *argv, int naryc, VALUE *naryv,
- ndfunc_t *ndf, na_iter_func_t iter_nan)
+static VALUE
+na_get_reduce_flag_from_narray(int naryc, VALUE *naryv, int *max_arg)
{
int ndim, ndim0;
- int row_major;
- int i, r;
- long narg;
+ int rowmaj;
+ int i;
size_t j;
- size_t len;
- ssize_t beg, step;
- VALUE v;
narray_t *na;
- size_t m;
VALUE reduce;
- VALUE kw_hash = Qnil;
- ID kw_table[3] = {id_axis,id_nan,id_keepdims};
- VALUE opts[3] = {Qundef,Qundef,Qundef};
- VALUE axes;
- narg = rb_scan_args(argc, argv, "*:", &axes, &kw_hash);
- rb_get_kwargs(kw_hash, kw_table, 0, 3, opts);
-
- // option: axis
- if (opts[0] != Qundef && RTEST(opts[0])) {
- if (narg > 0) {
- rb_raise(rb_eArgError,"both axis-arguments and axis-keyword are given");
- }
- if (TYPE(opts[0]) == T_ARRAY) {
- axes = opts[0];
- } else {
- axes = rb_ary_new3(1,opts[0]);
- }
- }
- if (ndf) {
- // option: nan
- if (iter_nan && opts[1] != Qundef) {
- if (RTEST(opts[1]))
- ndf->func = iter_nan; // replace to nan-aware iterator function
- }
- // option: keepdims
- if (opts[2] != Qundef) {
- if (RTEST(opts[2]))
- ndf->flag |= NDF_KEEP_DIM;
- }
- }
-
if (naryc<1) {
rb_raise(rb_eRuntimeError,"must be positive: naryc=%d", naryc);
}
GetNArray(naryv[0],na);
if (na->size==0) {
rb_raise(nary_eShapeError,"cannot reduce empty NArray");
}
reduce = na->reduce;
- if (argc==0) {
- //printf("pass argc=0 reduce=%d\n",NUM2INT(reduce));
- return reduce;
- }
ndim = ndim0 = na->ndim;
- row_major = TEST_COLUMN_MAJOR(naryv[0]);
- for (i=1; i<naryc; i++) {
+ if (max_arg) *max_arg = 0;
+ rowmaj = TEST_COLUMN_MAJOR(naryv[0]);
+ for (i=0; i<naryc; i++) {
GetNArray(naryv[i],na);
if (na->size==0) {
rb_raise(nary_eShapeError,"cannot reduce empty NArray");
}
- if (TEST_COLUMN_MAJOR(naryv[i]) != row_major) {
+ if (TEST_COLUMN_MAJOR(naryv[i]) != rowmaj) {
rb_raise(nary_eDimensionError,"dimension order is different");
}
- if (na->ndim > ndim) {
+ if (na->ndim > ndim) { // maximum dimension
ndim = na->ndim;
+ if (max_arg) *max_arg = i;
}
}
if (ndim != ndim0) {
- j = FIX2ULONG(reduce) << (ndim-ndim0);
- reduce = ULONG2NUM(j);
- if (!FIXNUM_P(reduce)) {
- rb_raise(nary_eDimensionError,"reduce has too many bits");
- }
+ j = NUM2SIZET(reduce) << (ndim-ndim0);
+ reduce = SIZET2NUM(j);
}
- //printf("argc=%d\n",argc);
+ return reduce;
+}
+
+static VALUE
+na_get_reduce_flag_from_axes(VALUE na_obj, VALUE axes)
+{
+ int i, r;
+ int ndim, rowmaj;
+ long narg;
+ size_t j;
+ size_t len;
+ ssize_t beg, step;
+ VALUE v;
+ size_t m;
+ VALUE reduce;
+ narray_t *na;
+
+ GetNArray(na_obj,na);
+ ndim = na->ndim;
+ rowmaj = TEST_COLUMN_MAJOR(na_obj);
+
m = 0;
reduce = Qnil;
narg = RARRAY_LEN(axes);
for (i=0; i<narg; i++) {
v = RARRAY_AREF(axes,i);
@@ -1552,12 +1530,13 @@
rb_raise(nary_eDimensionError, "invalid dimension argument %s",
rb_obj_classname(v));
}
for (j=0; j<len; j++) {
r = beg + step*j;
- if (row_major)
+ if (rowmaj) {
r = ndim-1-r;
+ }
if (reduce==Qnil) {
if ( r < (ssize_t)sizeof(size_t) ) {
m |= ((size_t)1) << r;
continue;
} else {
@@ -1566,14 +1545,72 @@
}
v = rb_funcall( INT2FIX(1), id_shift_left, 1, INT2FIX(r) );
reduce = rb_funcall( reduce, '|', 1, v );
}
}
- RB_GC_GUARD(axes);
- if (reduce==Qnil) reduce = SIZET2NUM(m);
+ if (NIL_P(reduce)) reduce = SIZET2NUM(m);
return reduce;
}
+
+VALUE
+nary_reduce_options(VALUE axes, VALUE *opts, int naryc, VALUE *naryv,
+ ndfunc_t *ndf)
+{
+ int max_arg;
+ VALUE reduce;
+
+ // option: axis
+ if (opts[0] != Qundef && RTEST(opts[0])) {
+ if (!NIL_P(axes)) {
+ rb_raise(rb_eArgError,
+ "cannot specify axis-arguments and axis-keyword simultaneously");
+ }
+ if (TYPE(opts[0]) == T_ARRAY) {
+ axes = opts[0];
+ } else {
+ axes = rb_ary_new3(1,opts[0]);
+ }
+ }
+ if (ndf) {
+ // option: keepdims
+ if (opts[1] != Qundef) {
+ if (RTEST(opts[1]))
+ ndf->flag |= NDF_KEEP_DIM;
+ }
+ }
+
+ reduce = na_get_reduce_flag_from_narray(naryc, naryv, &max_arg);
+
+ if (NIL_P(axes)) return reduce;
+
+ return na_get_reduce_flag_from_axes(naryv[max_arg], axes);
+}
+
+
+VALUE
+nary_reduce_dimension(int argc, VALUE *argv, int naryc, VALUE *naryv,
+ ndfunc_t *ndf, na_iter_func_t iter_nan)
+{
+ long narg;
+ VALUE axes;
+ VALUE kw_hash = Qnil;
+ ID kw_table[3] = {id_axis,id_keepdims,id_nan};
+ VALUE opts[3] = {Qundef,Qundef,Qundef};
+
+ narg = rb_scan_args(argc, argv, "*:", &axes, &kw_hash);
+ rb_get_kwargs(kw_hash, kw_table, 0, 3, opts);
+
+ if (ndf) {
+ // option: nan
+ if (iter_nan && opts[2] != Qundef) {
+ if (RTEST(opts[2]))
+ ndf->func = iter_nan; // replace to nan-aware iterator function
+ }
+ }
+
+ return na_reduce_options((narg)?axes:Qnil, opts, naryc, naryv, ndf);
+}
/*
Return true if column major.
*/
VALUE na_column_major_p( VALUE self )