static inline dtype yield_map_with_index(dtype x, size_t *c, VALUE *a, int nd, int md) { int j; VALUE y; a[0] = m_data_to_num(x); for (j=0; j<=nd; j++) { a[j+1] = SIZET2NUM(c[j]); } y = rb_yield(rb_ary_new4(md,a)); return m_num_to_data(y); } static void <%=c_iter%>(cumo_na_loop_t *const lp) { size_t i; char *p1, *p2; ssize_t s1, s2; size_t *idx1, *idx2; dtype x; VALUE *a; size_t *c; int nd, md; c = (size_t*)(lp->opt_ptr); nd = lp->ndim; if (nd > 0) {nd--;} md = nd + 2; a = ALLOCA_N(VALUE,md); CUMO_INIT_COUNTER(lp, i); CUMO_INIT_PTR_IDX(lp, 0, p1, s1, idx1); CUMO_INIT_PTR_IDX(lp, 1, p2, s2, idx2); CUMO_SHOW_SYNCHRONIZE_WARNING_ONCE("<%=name%>", "<%=type_name%>"); cumo_cuda_runtime_check_status(cudaDeviceSynchronize()); c[nd] = 0; if (idx1) { if (idx2) { for (; i--;) { CUMO_GET_DATA_INDEX(p1,idx1,dtype,x); x = yield_map_with_index(x,c,a,nd,md); CUMO_SET_DATA_INDEX(p2,idx2,dtype,x); c[nd]++; } } else { for (; i--;) { CUMO_GET_DATA_INDEX(p1,idx1,dtype,x); x = yield_map_with_index(x,c,a,nd,md); CUMO_SET_DATA_STRIDE(p2,s2,dtype,x); c[nd]++; } } } else { if (idx2) { for (; i--;) { CUMO_GET_DATA_STRIDE(p1,s1,dtype,x); x = yield_map_with_index(x,c,a,nd,md); CUMO_SET_DATA_INDEX(p2,idx2,dtype,x); c[nd]++; } } else { for (; i--;) { CUMO_GET_DATA_STRIDE(p1,s1,dtype,x); x = yield_map_with_index(x,c,a,nd,md); CUMO_SET_DATA_STRIDE(p2,s2,dtype,x); c[nd]++; } } } } /* Invokes the given block once for each element of self, passing that element and indices along each axis as parameters. Creates a new NArray containing the values returned by the block. Inplace option is allowed, i.e., `nary.inplace.map` overwrites `nary`. @overload <%=name%> For a block {|x,i,j,...| ... } @yield [x,i,j,...] x is an element, i,j,... are multidimensional indices. @return [Cumo::NArray] mapped array */ static VALUE <%=c_func(0)%>(VALUE self) { cumo_ndfunc_arg_in_t ain[1] = {{Qnil,0}}; cumo_ndfunc_arg_out_t aout[1] = {{cT,0}}; cumo_ndfunc_t ndf = {<%=c_iter%>, CUMO_FULL_LOOP, 1,1, ain,aout}; return cumo_na_ndloop_with_index(&ndf, 1, self); }