static VALUE rb_narray_debug_info_naview(VALUE self) { int i; narray_view_t *na; size_t *idx; size_t j; GetNArrayView(self,na); printf(" data = 0x%"SZF"x\n", (size_t)na->data); printf(" offset = %"SZF"d\n", (size_t)na->offset); printf(" stridx = 0x%"SZF"x\n", (size_t)na->stridx); if (na->stridx) { printf(" stridx = ["); for (i=0; i<na->base.ndim; i++) { if (SDX_IS_INDEX(na->stridx[i])) { idx = SDX_GET_INDEX(na->stridx[i]); printf(" index[%d]=[", i); for (j=0; j<na->base.shape[i]; j++) { printf(" %"SZF"d", idx[j]); } printf(" ] "); } else { printf(" %"SZF"d", SDX_GET_STRIDE(na->stridx[i])); } } printf(" ]\n"); } return Qnil; }
/* * call-seq: * narray.view => narray * * Return view of NArray */ VALUE na_make_view(VALUE self) { int i, nd; size_t j; size_t *idx1, *idx2; ssize_t stride; narray_t *na; narray_view_t *na1, *na2; volatile VALUE view; GetNArray(self,na); nd = na->ndim; view = na_s_allocate_view(CLASS_OF(self)); na_copy_flags(self, view); GetNArrayView(view, na2); na_setup_shape((narray_t*)na2, nd, na->shape); na2->stridx = ALLOC_N(stridx_t,nd); switch(na->type) { case NARRAY_DATA_T: case NARRAY_FILEMAP_T: stride = na_get_elmsz(self); for (i=nd; i--;) { SDX_SET_STRIDE(na2->stridx[i],stride); stride *= na->shape[i]; } na2->offset = 0; na2->data = self; break; case NARRAY_VIEW_T: GetNArrayView(self, na1); for (i=0; i<nd; i++) { if (SDX_IS_INDEX(na1->stridx[i])) { idx1 = SDX_GET_INDEX(na1->stridx[i]); idx2 = ALLOC_N(size_t,na1->base.shape[i]); for (j=0; j<na1->base.shape[i]; j++) { idx2[j] = idx1[j]; } SDX_SET_INDEX(na2->stridx[i],idx2); } else { na2->stridx[i] = na1->stridx[i]; } } na2->offset = na1->offset; na2->data = na1->data; break; } return view; }
// fix name, ex, allow_stride_for_flatten_view VALUE na_check_ladder(VALUE self, int start_dim) { int i; ssize_t st0, st1; narray_t *na1; narray_view_t *na; GetNArray(self,na1); //puts("pass ladder"); if (start_dim < -na1->ndim || start_dim >= na1->ndim) { rb_bug("start_dim (%d) out of range",start_dim); } switch(na1->type) { case NARRAY_DATA_T: case NARRAY_FILEMAP_T: return Qtrue; case NARRAY_VIEW_T: GetNArrayView(self,na); // negative dim -> position from last dim if (start_dim < 0) { start_dim += na->base.ndim; } // not ladder if it has index for (i=start_dim; i<na->base.ndim; i++) { if (SDX_IS_INDEX(na->stridx[i])) return Qfalse; } // check stride i = start_dim; st0 = SDX_GET_STRIDE(na->stridx[i]); for (i++; i<na->base.ndim; i++) { st1 = SDX_GET_STRIDE(na->stridx[i]); if (st0 != (ssize_t)(st1*na->base.shape[i])) { return Qfalse; } st0 = st1; } return Qtrue; } return Qtrue; }
VALUE na_make_view_struct(VALUE self, VALUE dtype, VALUE offset) { size_t i, n; int j, k, ndim; size_t *shape; size_t *idx1, *idx2; ssize_t stride; stridx_t *stridx; narray_t *na, *nt; narray_view_t *na1, *na2; VALUE klass; volatile VALUE view; GetNArray(self,na); // build from Numo::Struct if (rb_obj_is_kind_of(dtype,cNArray)) { GetNArray(dtype,nt); ndim = na->ndim + nt->ndim; shape = ALLOCA_N(size_t,ndim); // struct dimensions for (j=0; j<na->ndim; j++) { shape[j] = na->shape[j]; } // member dimension for (j=na->ndim,k=0; j<ndim; j++,k++) { shape[j] = nt->shape[k]; } klass = CLASS_OF(dtype); stridx = ALLOC_N(stridx_t, ndim); stride = na_dtype_elmsz(klass); for (j=ndim,k=nt->ndim; k; ) { SDX_SET_STRIDE(stridx[--j],stride); stride *= nt->shape[--k]; } } else { ndim = na->ndim; shape = ALLOCA_N(size_t,ndim); for (j=0; j<ndim; j++) { shape[j] = na->shape[j]; } klass = CLASS_OF(self); if (TYPE(dtype)==T_CLASS) { if (RTEST(rb_class_inherited_p(dtype,cNArray))) { klass = dtype; } } stridx = ALLOC_N(stridx_t, ndim); } view = na_s_allocate_view(klass); na_copy_flags(self, view); GetNArrayView(view, na2); na_setup_shape((narray_t*)na2, ndim, shape); na2->stridx = stridx; switch(na->type) { case NARRAY_DATA_T: case NARRAY_FILEMAP_T: stride = na_get_elmsz(self); for (j=na->ndim; j--;) { SDX_SET_STRIDE(na2->stridx[j], stride); stride *= na->shape[j]; } na2->offset = 0; na2->data = self; break; case NARRAY_VIEW_T: GetNArrayView(self, na1); for (j=na1->base.ndim; j--; ) { if (SDX_IS_INDEX(na1->stridx[j])) { n = na1->base.shape[j]; idx1 = SDX_GET_INDEX(na1->stridx[j]); idx2 = ALLOC_N(size_t, na1->base.shape[j]); for (i=0; i<n; i++) { idx2[i] = idx1[i]; } SDX_SET_INDEX(na2->stridx[j],idx2); } else { na2->stridx[j] = na1->stridx[j]; } } na2->offset = na1->offset; na2->data = na1->data; break; } if (RTEST(offset)) { na2->offset += NUM2SIZET(offset); } return view; }
/* * call-seq: * narray.reverse([dim0,dim1,..]) => narray * * Return reversed view along specified dimeinsion */ VALUE nary_reverse(int argc, VALUE *argv, VALUE self) { int i, nd; size_t j, n; size_t offset; size_t *idx1, *idx2; ssize_t stride; ssize_t sign; narray_t *na; narray_view_t *na1, *na2; VALUE view; VALUE reduce; reduce = na_reduce_dimension(argc, argv, 1, &self); GetNArray(self,na); nd = na->ndim; view = na_s_allocate_view(CLASS_OF(self)); na_copy_flags(self, view); GetNArrayView(view, na2); na_setup_shape((narray_t*)na2, nd, na->shape); na2->stridx = ALLOC_N(stridx_t,nd); switch(na->type) { case NARRAY_DATA_T: case NARRAY_FILEMAP_T: stride = na_get_elmsz(self); offset = 0; for (i=nd; i--;) { if (na_test_reduce(reduce,i)) { offset += (na->shape[i]-1)*stride; sign = -1; } else { sign = 1; } SDX_SET_STRIDE(na2->stridx[i],stride*sign); stride *= na->shape[i]; } na2->offset = offset; na2->data = self; break; case NARRAY_VIEW_T: GetNArrayView(self, na1); offset = na1->offset; for (i=0; i<nd; i++) { n = na1->base.shape[i]; if (SDX_IS_INDEX(na1->stridx[i])) { idx1 = SDX_GET_INDEX(na1->stridx[i]); idx2 = ALLOC_N(size_t,n); if (na_test_reduce(reduce,i)) { for (j=0; j<n; j++) { idx2[n-1-j] = idx1[j]; } } else { for (j=0; j<n; j++) { idx2[j] = idx1[j]; } } SDX_SET_INDEX(na2->stridx[i],idx2); } else { stride = SDX_GET_STRIDE(na1->stridx[i]); if (na_test_reduce(reduce,i)) { offset += (n-1)*stride; SDX_SET_STRIDE(na2->stridx[i],-stride); } else { na2->stridx[i] = na1->stridx[i]; } } } na2->offset = offset; na2->data = na1->data; break; } return view; }
int na_get_result_dimension(VALUE self, int argc, VALUE *argv, ssize_t stride, size_t *pos_idx) { int i, j; int count_new=0; int count_rest=0; ssize_t x, s, m, pos, *idx; narray_t *na; narray_view_t *nv; stridx_t sdx; VALUE a; GetNArray(self,na); if (na->size == 0) { rb_raise(nary_eShapeError, "cannot get element of empty array"); } idx = ALLOCA_N(ssize_t, argc); for (i=j=0; i<argc; i++) { a = argv[i]; switch(TYPE(a)) { case T_FIXNUM: idx[j++] = FIX2LONG(a); break; case T_BIGNUM: case T_FLOAT: idx[j++] = NUM2SSIZET(a); break; case T_FALSE: case T_SYMBOL: if (a==sym_rest || a==sym_tilde || a==Qfalse) { argv[i] = Qfalse; count_rest++; break; } else if (a==sym_new || a==sym_minus) { argv[i] = sym_new; count_new++; } } } if (j != argc) { return check_index_count(argc, na->ndim, count_new, count_rest); } switch(na->type) { case NARRAY_VIEW_T: GetNArrayView(self,nv); pos = nv->offset; if (j == na->ndim) { for (i=j-1; i>=0; i--) { x = na_range_check(idx[i], na->shape[i], i); sdx = nv->stridx[i]; if (SDX_IS_INDEX(sdx)) { pos += SDX_GET_INDEX(sdx)[x]; } else { pos += SDX_GET_STRIDE(sdx)*x; } } *pos_idx = pos; return 0; } if (j == 1) { x = na_range_check(idx[0], na->size, 0); for (i=na->ndim-1; i>=0; i--) { s = na->shape[i]; m = x % s; x = x / s; sdx = nv->stridx[i]; if (SDX_IS_INDEX(sdx)) { pos += SDX_GET_INDEX(sdx)[m]; } else { pos += SDX_GET_STRIDE(sdx)*m; } } *pos_idx = pos; return 0; } break; default: if (!stride) { stride = nary_element_stride(self); } if (j == 1) { x = na_range_check(idx[0], na->size, 0); *pos_idx = stride * x; return 0; } if (j == na->ndim) { pos = 0; for (i=j-1; i>=0; i--) { x = na_range_check(idx[i], na->shape[i], i); pos += stride * x; stride *= na->shape[i]; } *pos_idx = pos; return 0; } } rb_raise(rb_eIndexError,"# of index(=%i) should be " "equal to ndim(=%i) or 1", argc,na->ndim); return -1; }
static void na_index_aref_naview(narray_view_t *na1, narray_view_t *na2, na_index_arg_t *q, ssize_t elmsz, int ndim, int keep_dim) { int i, j; ssize_t total=1; for (i=j=0; i<ndim; i++) { stridx_t sdx1 = na1->stridx[q[i].orig_dim]; ssize_t size; // numeric index -- trim dimension if (!keep_dim && q[i].n==1 && q[i].step==0) { if (SDX_IS_INDEX(sdx1)) { na2->offset += SDX_GET_INDEX(sdx1)[q[i].beg]; } else { na2->offset += SDX_GET_STRIDE(sdx1)*q[i].beg; } continue; } na2->base.shape[j] = size = q[i].n; if (q[i].reduce != 0) { VALUE m = rb_funcall(INT2FIX(1),id_shift_left,1,INT2FIX(j)); na2->base.reduce = rb_funcall(m,'|',1,na2->base.reduce); } if (q[i].orig_dim >= na1->base.ndim) { // new dimension SDX_SET_STRIDE(na2->stridx[j], elmsz); } else if (q[i].idx != NULL && SDX_IS_INDEX(sdx1)) { // index <- index int k; size_t *index = q[i].idx; SDX_SET_INDEX(na2->stridx[j], index); q[i].idx = NULL; for (k=0; k<size; k++) { index[k] = SDX_GET_INDEX(sdx1)[index[k]]; } } else if (q[i].idx != NULL && SDX_IS_STRIDE(sdx1)) { // index <- step ssize_t stride1 = SDX_GET_STRIDE(sdx1); size_t *index = q[i].idx; SDX_SET_INDEX(na2->stridx[j],index); q[i].idx = NULL; if (stride1<0) { size_t last; int k; stride1 = -stride1; last = na1->base.shape[q[i].orig_dim] - 1; if (na2->offset < last * stride1) { rb_raise(rb_eStandardError,"bug: negative offset"); } na2->offset -= last * stride1; for (k=0; k<size; k++) { index[k] = (last - index[k]) * stride1; } } else { int k; for (k=0; k<size; k++) { index[k] = index[k] * stride1; } } } else if (q[i].idx == NULL && SDX_IS_INDEX(sdx1)) { // step <- index int k; size_t beg = q[i].beg; ssize_t step = q[i].step; size_t *index = ALLOC_N(size_t, size); SDX_SET_INDEX(na2->stridx[j],index); for (k=0; k<size; k++) { index[k] = SDX_GET_INDEX(sdx1)[beg+step*k]; } } else if (q[i].idx == NULL && SDX_IS_STRIDE(sdx1)) { // step <- step size_t beg = q[i].beg; ssize_t step = q[i].step; ssize_t stride1 = SDX_GET_STRIDE(sdx1); na2->offset += stride1*beg; SDX_SET_STRIDE(na2->stridx[j], stride1*step); } j++; total *= size; } na2->base.size = total; }