|
|
|
@@ -16,6 +16,39 @@ |
|
|
|
|
|
|
|
#include "nnacl/infer/reduce_infer.h" |
|
|
|
|
|
|
|
int ReduceOnAllAxes(const TensorC *input, TensorC *output, int *out_shape, size_t out_shape_size, bool keep_dims) { |
|
|
|
if (keep_dims) { |
|
|
|
for (size_t i = 0; i < input->shape_size_; i++) { |
|
|
|
ShapePush(out_shape, &out_shape_size, 1); |
|
|
|
} |
|
|
|
} |
|
|
|
SetShapeArray(output, out_shape, out_shape_size); |
|
|
|
output->data_type_ = input->data_type_; |
|
|
|
return NNACL_OK; |
|
|
|
} |
|
|
|
|
|
|
|
int ReduceOnSelectedAxes(const TensorC *input, size_t num_axes, int *actual_axes, TensorC *output, int *out_shape, |
|
|
|
size_t out_shape_size, bool keep_dims) { |
|
|
|
for (size_t i = 0; i < input->shape_size_; i++) { |
|
|
|
bool reduce_axis = false; |
|
|
|
for (size_t idx = 0; idx < num_axes; ++idx) { |
|
|
|
if ((size_t)(actual_axes[idx]) == i || (size_t)(actual_axes[idx] + input->shape_size_) == i) { |
|
|
|
reduce_axis = true; |
|
|
|
break; |
|
|
|
} |
|
|
|
} |
|
|
|
if (reduce_axis) { |
|
|
|
if (keep_dims) { |
|
|
|
ShapePush(out_shape, &out_shape_size, 1); |
|
|
|
} |
|
|
|
} else { |
|
|
|
ShapePush(out_shape, &out_shape_size, input->shape_[i]); |
|
|
|
} |
|
|
|
} |
|
|
|
SetShapeArray(output, out_shape, out_shape_size); |
|
|
|
return NNACL_OK; |
|
|
|
} |
|
|
|
|
|
|
|
int ReduceInferShape(const TensorC *const *inputs, size_t inputs_size, TensorC **outputs, size_t outputs_size, |
|
|
|
OpParameter *parameter) { |
|
|
|
#ifdef Debug |
|
|
|
@@ -37,6 +70,9 @@ int ReduceInferShape(const TensorC *const *inputs, size_t inputs_size, TensorC * |
|
|
|
size_t out_shape_size = 0; |
|
|
|
// get axes from input tensor |
|
|
|
const TensorC *axes_input = inputs[1]; |
|
|
|
if (axes_input->shape_size_ == 1 && axes_input->shape_[0] == 0) { |
|
|
|
return ReduceOnAllAxes(input, output, out_shape, out_shape_size, keep_dims); |
|
|
|
} |
|
|
|
int *axes = (int *)axes_input->data_; |
|
|
|
if (axes == NULL) { |
|
|
|
return NNACL_NULL_PTR; |
|
|
|
@@ -70,32 +106,8 @@ int ReduceInferShape(const TensorC *const *inputs, size_t inputs_size, TensorC * |
|
|
|
} |
|
|
|
// reduce on all axes |
|
|
|
if (num_axes == 0) { |
|
|
|
if (keep_dims) { |
|
|
|
for (size_t i = 0; i < input->shape_size_; i++) { |
|
|
|
ShapePush(out_shape, &out_shape_size, 1); |
|
|
|
} |
|
|
|
} |
|
|
|
SetShapeArray(output, out_shape, out_shape_size); |
|
|
|
output->data_type_ = input->data_type_; |
|
|
|
return NNACL_OK; |
|
|
|
return ReduceOnAllAxes(input, output, out_shape, out_shape_size, keep_dims); |
|
|
|
} |
|
|
|
// reduce on selected axes |
|
|
|
for (size_t i = 0; i < input->shape_size_; i++) { |
|
|
|
bool reduce_axis = false; |
|
|
|
for (size_t idx = 0; idx < num_axes; ++idx) { |
|
|
|
if ((size_t)(actual_axes[idx]) == i || (size_t)(actual_axes[idx] + input->shape_size_) == i) { |
|
|
|
reduce_axis = true; |
|
|
|
break; |
|
|
|
} |
|
|
|
} |
|
|
|
if (reduce_axis) { |
|
|
|
if (keep_dims) { |
|
|
|
ShapePush(out_shape, &out_shape_size, 1); |
|
|
|
} |
|
|
|
} else { |
|
|
|
ShapePush(out_shape, &out_shape_size, input->shape_[i]); |
|
|
|
} |
|
|
|
} |
|
|
|
SetShapeArray(output, out_shape, out_shape_size); |
|
|
|
return NNACL_OK; |
|
|
|
return ReduceOnSelectedAxes(input, num_axes, actual_axes, output, out_shape, out_shape_size, keep_dims); |
|
|
|
} |