/* * 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; }
static void na_index_aref_nadata(narray_data_t *na1, narray_view_t *na2, na_index_arg_t *q, ssize_t elmsz, int ndim, int keep_dim) { int i, j; ssize_t size, k, total=1; ssize_t stride1; ssize_t *strides_na1; size_t *index; ssize_t beg, step; VALUE m; strides_na1 = ALLOCA_N(ssize_t, na1->base.ndim); na_get_strides_nadata(na1, strides_na1, elmsz); for (i=j=0; i<ndim; i++) { stride1 = strides_na1[q[i].orig_dim]; // numeric index -- trim dimension if (!keep_dim && q[i].n==1 && q[i].step==0) { beg = q[i].beg; na2->offset += stride1 * beg; continue; } na2->base.shape[j] = size = q[i].n; if (q[i].reduce != 0) { m = rb_funcall(INT2FIX(1),id_shift_left,1,INT2FIX(j)); na2->base.reduce = rb_funcall(m,'|',1,na2->base.reduce); } // array index if (q[i].idx != NULL) { index = q[i].idx; SDX_SET_INDEX(na2->stridx[j],index); q[i].idx = NULL; for (k=0; k<size; k++) { index[k] = index[k] * stride1; } } else { beg = q[i].beg; step = q[i].step; na2->offset += stride1*beg; SDX_SET_STRIDE(na2->stridx[j], stride1*step); } j++; total *= size; } na2->base.size = total; }
/* * call-seq: * narray.expand_dims(dim) => narray view * * Expand the shape of an array. Insert a new axis with size=1 * at a given dimension. * @param [Integer] dim dimension at which new axis is inserted. * @return [Numo::NArray] result narray view. */ VALUE na_expand_dims(VALUE self, VALUE vdim) { int i, j, nd, dim; size_t *shape, *na_shape; stridx_t *stridx, *na_stridx; narray_t *na; narray_view_t *na2; VALUE view; GetNArray(self,na); nd = na->ndim; dim = NUM2INT(vdim); if (dim < -nd-1 || dim > nd) { rb_raise(nary_eDimensionError,"invalid axis (%d for %dD NArray)", dim,nd); } if (dim < 0) { dim += nd+1; } view = na_make_view(self); GetNArrayView(view, na2); shape = ALLOC_N(size_t,nd+1); stridx = ALLOC_N(stridx_t,nd+1); na_shape = na2->base.shape; na_stridx = na2->stridx; for (i=j=0; i<=nd; i++) { if (i==dim) { shape[i] = 1; SDX_SET_STRIDE(stridx[i],0); } else { shape[i] = na_shape[j]; stridx[i] = na_stridx[j]; j++; } } na2->stridx = stridx; xfree(na_stridx); na2->base.shape = shape; xfree(na_shape); na2->base.ndim++; return view; }
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; }
static VALUE nstruct_add_type(VALUE type, int argc, VALUE *argv, VALUE nst) { VALUE ofs, size; ID id; int i; VALUE name=Qnil; size_t *shape=NULL; int ndim=0; ssize_t stride; narray_view_t *nt; int j; for (i=0; i<argc; i++) { switch(TYPE(argv[i])) { case T_STRING: case T_SYMBOL: if (NIL_P(name)) { name = argv[i]; break; } rb_raise(rb_eArgError,"multiple name in struct definition"); case T_ARRAY: if (shape) { rb_raise(rb_eArgError,"multiple shape in struct definition"); } ndim = RARRAY_LEN(argv[i]); if (ndim > NA_MAX_DIMENSION) { rb_raise(rb_eArgError,"too large number of dimensions"); } if (ndim == 0) { rb_raise(rb_eArgError,"array is empty"); } shape = ALLOCA_N(size_t, ndim); na_array_to_internal_shape(Qnil, argv[i], shape); break; } } id = rb_to_id(name); name = ID2SYM(id); if (rb_obj_is_kind_of(type,cNArray)) { narray_t *na; GetNArray(type,na); type = CLASS_OF(type); ndim = na->ndim; shape = na->shape; } type = rb_narray_view_new(type,ndim,shape); GetNArrayView(type,nt); nt->stridx = ALLOC_N(stridx_t,ndim); stride = na_dtype_elmsz(CLASS_OF(type)); for (j=ndim; j--; ) { SDX_SET_STRIDE(nt->stridx[j], stride); stride *= shape[j]; } ofs = rb_iv_get(nst, "__offset__"); nt->offset = NUM2SIZET(ofs); size = rb_funcall(type, rb_intern("byte_size"), 0); rb_iv_set(nst, "__offset__", rb_funcall(ofs,'+',1,size)); rb_ary_push(rb_iv_get(nst,"__members__"), rb_ary_new3(4,name,type,ofs,size)); // <- field definition return Qnil; }
/* * 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; }
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; }