| 20 | // accumulate through explicit loops over input, output, and filters. |
| 21 | template <typename Dtype> |
| 22 | void caffe_conv(const Blob<Dtype>* in, ConvolutionParameter* conv_param, |
| 23 | const vector<shared_ptr<Blob<Dtype> > >& weights, |
| 24 | Blob<Dtype>* out) { |
| 25 | const bool has_depth = (out->num_axes() == 5); |
| 26 | if (!has_depth) { CHECK_EQ(4, out->num_axes()); } |
| 27 | // Kernel size, stride, and pad |
| 28 | int kernel_h, kernel_w; |
| 29 | if (conv_param->has_kernel_h() || conv_param->has_kernel_w()) { |
| 30 | kernel_h = conv_param->kernel_h(); |
| 31 | kernel_w = conv_param->kernel_w(); |
| 32 | } else { |
| 33 | kernel_h = kernel_w = conv_param->kernel_size(0); |
| 34 | } |
| 35 | int pad_h, pad_w; |
| 36 | if (conv_param->has_pad_h() || conv_param->has_pad_w()) { |
| 37 | pad_h = conv_param->pad_h(); |
| 38 | pad_w = conv_param->pad_w(); |
| 39 | } else { |
| 40 | pad_h = pad_w = conv_param->pad_size() ? conv_param->pad(0) : 0; |
| 41 | } |
| 42 | int stride_h, stride_w; |
| 43 | if (conv_param->has_stride_h() || conv_param->has_stride_w()) { |
| 44 | stride_h = conv_param->stride_h(); |
| 45 | stride_w = conv_param->stride_w(); |
| 46 | } else { |
| 47 | stride_h = stride_w = conv_param->stride_size() ? conv_param->stride(0) : 1; |
| 48 | } |
| 49 | int dilation_h, dilation_w; |
| 50 | dilation_h = dilation_w = conv_param->dilation_size() ? |
| 51 | conv_param->dilation(0) : 1; |
| 52 | int kernel_d, pad_d, stride_d, dilation_d; |
| 53 | if (has_depth) { |
| 54 | kernel_d = kernel_h; |
| 55 | stride_d = stride_h; |
| 56 | pad_d = pad_h; |
| 57 | dilation_d = dilation_h; |
| 58 | } else { |
| 59 | kernel_d = stride_d = dilation_d = 1; |
| 60 | pad_d = 0; |
| 61 | } |
| 62 | // Groups |
| 63 | int groups = conv_param->group(); |
| 64 | int o_g = out->shape(1) / groups; |
| 65 | int k_g = in->shape(1) / groups; |
| 66 | int o_head, k_head; |
| 67 | // Convolution |
| 68 | vector<int> weight_offset(4 + has_depth); |
| 69 | vector<int> in_offset(4 + has_depth); |
| 70 | vector<int> out_offset(4 + has_depth); |
| 71 | Dtype* out_data = out->mutable_cpu_data(); |
| 72 | for (int n = 0; n < out->shape(0); n++) { |
| 73 | for (int g = 0; g < groups; g++) { |
| 74 | o_head = o_g * g; |
| 75 | k_head = k_g * g; |
| 76 | for (int o = 0; o < o_g; o++) { |
| 77 | for (int k = 0; k < k_g; k++) { |
| 78 | for (int z = 0; z < (has_depth ? out->shape(2) : 1); z++) { |
| 79 | for (int y = 0; y < out->shape(2 + has_depth); y++) { |
no test coverage detected