#include
#include "caffe/layers/concat_layer.hpp"
#include "caffe/util/math_functions.hpp"
namespace caffe {
template
void ConcatLayer::LayerSetUp(const vector& bottom,
const vector& top) {
const ConcatParameter& concat_param = this->layer_param_.concat_param();
CHECK(!(concat_param.has_axis() && concat_param.has_concat_dim()))
num_axes();
const ConcatParameter& concat_param = this->layer_param_.concat_param();
if (concat_param.has_concat_dim()) {
concat_axis_ = static_cast(concat_param.concat_dim());
// Don't allow negative indexing for concat_dim, a uint32 -- almost
// certainly unintended.
CHECK_GE(concat_axis_, 0) count();
for (int i = 1; i < bottom.size(); ++i) {
CHECK_EQ(num_axes, bottom[i]->num_axes())
shape(j))
count();
top_shape[concat_axis_] += bottom[i]->shape(concat_axis_);
}
top[0]->Reshape(top_shape);
CHECK_EQ(bottom_count_sum, top[0]->count());
if (bottom.size() == 1) {
top[0]->ShareData(*bottom[0]);
top[0]->ShareDiff(*bottom[0]);
}
}
template
void ConcatLayer::Forward_cpu(const vector& bottom,
const vector& top) {
if (bottom.size() == 1) { return; }
Dtype* top_data = top[0]->mutable_cpu_data();
int offset_concat_axis = 0;
const int top_concat_axis = top[0]->shape(concat_axis_);
for (int i = 0; i < bottom.size(); ++i) {
const Dtype* bottom_data = bottom[i]->cpu_data();
const int bottom_concat_axis = bottom[i]->shape(concat_axis_);
for (int n = 0; n < num_concats_; ++n) {
caffe_copy(bottom_concat_axis * concat_input_size_,
bottom_data + n * bottom_concat_axis * concat_input_size_,
top_data + (n * top_concat_axis + offset_concat_axis)
* concat_input_size_);
}
offset_concat_axis += bottom_concat_axis;
}
}
template
void ConcatLayer::Backward_cpu(const vector& top,
const vector& propagate_down, const vector& bottom) {
if (bottom.size() == 1) { return; }
const Dtype* top_diff = top[0]->cpu_diff();
int offset_concat_axis = 0;
const int top_concat_axis = top[0]->shape(concat_axis_);
for (int i = 0; i < bottom.size(); ++i) {
const int bottom_concat_axis = bottom[i]->shape(concat_axis_);
if (propagate_down[i]) {
Dtype* bottom_diff = bottom[i]->mutable_cpu_diff();
for (int n = 0; n < num_concats_; ++n) {
caffe_copy(bottom_concat_axis * concat_input_size_, top_diff +
(n * top_concat_axis + offset_concat_axis) * concat_input_size_,
bottom_diff + n * bottom_concat_axis * concat_input_size_);
}
}
offset_concat_axis += bottom_concat_axis;
}
}
#ifdef CPU_ONLY
STUB_GPU(ConcatLayer);
#endif
INSTANTIATE_CLASS(ConcatLayer);
#ifndef USE_ACL
REGISTER_LAYER_CLASS(Concat);
#endif
} // namespace caffe