/* :call-seq: vector.convolve(kernel, middle) convolve applies a simple convolution to the vector using kernel centered at the point middle. (0 is the leftmost point of the kernel). */ static VALUE dvector_convolve(VALUE self, VALUE kernel, VALUE middle) { long len; const double * values = Dvector_Data_for_Read(self, &len); VALUE retval = dvector_new2(len,len); double * ret = Dvector_Data_for_Write(retval,NULL); long kernel_len; const double * ker = Dvector_Data_for_Read(kernel, &kernel_len); /* I guess */ long mid = NUM2LONG(middle); if(mid > kernel_len) rb_raise(rb_eArgError, "middle should be within kernel's range"); else { long i,j,k; for(i = 0; i < len; i++) { double sum = 0, k_sum = 0; for(j = 0; j < kernel_len; j++) { /* check that we are within the vector */ k = i - mid + j; /* The current index inside the vector */ /* This code is equivalent to saying that the vector is prolongated until infinity with values at the boundaries -> no, obnoxious, I think. Simply don't take care of these points -> yes, finally ? */ if( k < 0) /* continue; */ k = 0; if( k >= len) /* continue; */ k = len - 1; sum += ker[j] * values[k]; k_sum += ker[j]; } sum/= k_sum; ret[i] = sum; } } return retval; }