VALUE na_reduce_dimension(int argc, VALUE *argv, int naryc, VALUE *naryv) { int ndim, ndim0; int row_major; int i, r; size_t j; size_t len; ssize_t beg, step; VALUE v; narray_t *na; size_t m; VALUE reduce; if (naryc<1) { rb_raise(rb_eRuntimeError,"must be positive: naryc=%d", naryc); } GetNArray(naryv[0],na); 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++) { GetNArray(naryv[i],na); if (TEST_COLUMN_MAJOR(naryv[i]) != row_major) { rb_raise(nary_eDimensionError,"dimension order is different"); } if (na->ndim > ndim) { ndim = na->ndim; } } if (ndim != ndim0) { j = FIX2ULONG(reduce) << (ndim-ndim0); reduce = ULONG2NUM(j); if (!FIXNUM_P(reduce)) { rb_raise(nary_eDimensionError,"reduce has too many bits"); } } //printf("argc=%d\n",argc); m = 0; reduce = Qnil; for (i=0; i<argc; i++) { v = argv[i]; //printf("argv[%d]=",i);rb_p(v); if (TYPE(v)==T_FIXNUM) { beg = FIX2INT(v); if (beg<0) beg+=ndim; if (beg>=ndim || beg<0) { rb_raise(nary_eDimensionError,"dimension is out of range"); } len = 1; step = 0; //printf("beg=%d step=%d len=%d\n",beg,step,len); } else if (rb_obj_is_kind_of(v,rb_cRange) || rb_obj_is_kind_of(v,na_cStep)) { nary_step_array_index( v, ndim, &len, &beg, &step ); } else { 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) r = ndim-1-r; if (reduce==Qnil) { if ( r < (ssize_t)sizeof(size_t) ) { m |= ((size_t)1) << r; continue; } else { reduce = SIZE2NUM(m); } } v = rb_funcall( INT2FIX(1), rb_intern("<<"), 1, INT2FIX(r) ); reduce = rb_funcall( reduce, rb_intern("|"), 1, v ); } } if (reduce==Qnil) reduce = SIZE2NUM(m); return reduce; }
// 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 // q: parsed information is stored to *q static void na_index_parse_each(volatile VALUE a, ssize_t size, int i, na_index_arg_t *q) { switch(TYPE(a)) { case T_FIXNUM: na_index_set_scalar(q,i,size,FIX2LONG(a)); break; case T_BIGNUM: na_index_set_scalar(q,i,size,NUM2SSIZET(a)); break; case T_FLOAT: na_index_set_scalar(q,i,size,NUM2SSIZET(a)); break; case T_NIL: case T_TRUE: na_index_set_step(q,i,size,0,1); break; case T_SYMBOL: if (a==sym_all || a==sym_ast) { na_index_set_step(q,i,size,0,1); } else if (a==sym_reverse) { na_index_set_step(q,i,size,size-1,-1); } else if (a==sym_new) { na_index_set_step(q,i,1,0,1); } else if (a==sym_reduce || a==sym_sum || a==sym_plus) { na_index_set_step(q,i,size,0,1); q->reduce = 1; } else { rb_raise(rb_eIndexError, "invalid symbol for index"); } break; case T_ARRAY: na_parse_array(a, i, size, q); break; default: if (rb_obj_is_kind_of(a, rb_cRange)) { na_parse_range(a, 1, i, size, q); } else if (rb_obj_is_kind_of(a, rb_cEnumerator)) { na_parse_enumerator(a, i, size, q); } else if (rb_obj_is_kind_of(a, na_cStep)) { ssize_t beg, step, n; nary_step_array_index(a, size, (size_t*)(&n), &beg, &step); na_index_set_step(q,i,n,beg,step); } // NArray index else if (NA_IsNArray(a)) { na_parse_narray_index(a, i, size, q); } else { rb_raise(rb_eIndexError, "not allowed type"); } } }