1 // Copyright (C) 2019 Intel Corporation
2 // SPDX-License-Identifier: Apache-2.0
5 #include "ext_list.hpp"
6 #include "ext_base.hpp"
12 #include "ie_parallel.hpp"
14 namespace InferenceEngine {
15 namespace Extensions {
18 class RangeImpl: public ExtLayerBase {
20 explicit RangeImpl(const CNNLayer* layer) {
22 if (layer->insData.empty() || layer->outData.empty())
23 THROW_IE_EXCEPTION << layer->name << " Incorrect number of input/output edges!";
25 if (layer->insData.size() != 3)
26 THROW_IE_EXCEPTION << layer->name << " Incorrect number of input edges!";
28 SizeVector start_dims = layer->insData[RANGE_START].lock()->getTensorDesc().getDims();
29 if (start_dims.size() > 1)
30 THROW_IE_EXCEPTION << layer->name << " Start scalar should have 1 dimension";
32 SizeVector limit_dims = layer->insData[RANGE_LIMIT].lock()->getTensorDesc().getDims();
33 if (limit_dims.size() > 1)
34 THROW_IE_EXCEPTION << layer->name << " Limit scalar should have 1 dimension";
36 SizeVector delta_dims = layer->insData[RANGE_DELTA].lock()->getTensorDesc().getDims();
37 if (delta_dims.size() > 1)
38 THROW_IE_EXCEPTION << layer->name << " Delta scalar should have 1 dimension";
40 SizeVector dst_dims = layer->outData[0]->getTensorDesc().getDims();
41 if (dst_dims.size() > 1)
42 THROW_IE_EXCEPTION << layer->name << " Output vector should have 1 dimension";
44 if (!(layer->insData[RANGE_START].lock()->getTensorDesc().getPrecision() == Precision::I32 &&
45 layer->insData[RANGE_LIMIT].lock()->getTensorDesc().getPrecision() == Precision::I32 &&
46 layer->insData[RANGE_DELTA].lock()->getTensorDesc().getPrecision() == Precision::I32 &&
47 layer->outData[0]->getTensorDesc().getPrecision() == Precision::I32) &&
48 !(layer->insData[RANGE_START].lock()->getTensorDesc().getPrecision() == Precision::FP32 &&
49 layer->insData[RANGE_LIMIT].lock()->getTensorDesc().getPrecision() == Precision::FP32 &&
50 layer->insData[RANGE_DELTA].lock()->getTensorDesc().getPrecision() == Precision::FP32 &&
51 layer->outData[0]->getTensorDesc().getPrecision() == Precision::FP32)) {
52 THROW_IE_EXCEPTION << layer->name <<
53 " 'Start', 'Limit', 'Delta' input scalars and output tensor should have same precision" <<
54 "and only FP32 and I32 are supported!";
57 addConfig(layer, { DataConfigurator(ConfLayout::PLN), DataConfigurator(ConfLayout::PLN), DataConfigurator(ConfLayout::PLN) },
58 { DataConfigurator(ConfLayout::PLN) });
59 } catch (InferenceEngine::details::InferenceEngineException &ex) {
64 StatusCode execute(std::vector<Blob::Ptr>& inputs, std::vector<Blob::Ptr>& outputs, ResponseDesc *resp) noexcept override {
65 StatusCode retcode = OK;
66 switch (outputs[0]->precision()) {
67 case Precision::FP32: {
68 retcode = range((inputs[RANGE_START]->cbuffer().as<float *>() +
69 inputs[RANGE_START]->getTensorDesc().getBlockingDesc().getOffsetPadding())[0],
70 (inputs[RANGE_LIMIT]->cbuffer().as<float *>() +
71 inputs[RANGE_LIMIT]->getTensorDesc().getBlockingDesc().getOffsetPadding())[0],
72 (inputs[RANGE_DELTA]->cbuffer().as<float *>() +
73 inputs[RANGE_DELTA]->getTensorDesc().getBlockingDesc().getOffsetPadding())[0], outputs[0]);
76 case Precision::I32: {
77 retcode = range((inputs[RANGE_START]->cbuffer().as<int32_t *>() +
78 inputs[RANGE_START]->getTensorDesc().getBlockingDesc().getOffsetPadding())[0],
79 (inputs[RANGE_LIMIT]->cbuffer().as<int32_t *>() +
80 inputs[RANGE_LIMIT]->getTensorDesc().getBlockingDesc().getOffsetPadding())[0],
81 (inputs[RANGE_DELTA]->cbuffer().as<int32_t *>() +
82 inputs[RANGE_DELTA]->getTensorDesc().getBlockingDesc().getOffsetPadding())[0], outputs[0]);
87 std::string errorMsg = "Incorrect output precision. Only FP32 and I32 are supported!";
88 errorMsg.copy(resp->msg, sizeof(resp->msg) - 1);
90 retcode = GENERAL_ERROR;
92 if (resp && retcode == PARAMETER_MISMATCH) {
93 std::string errorMsg = "Range indexes exceeds data tensor dimension";
94 errorMsg.copy(resp->msg, sizeof(resp->msg) - 1);
100 const size_t RANGE_START = 0;
101 const size_t RANGE_LIMIT = 1;
102 const size_t RANGE_DELTA = 2;
104 template <typename data_t>
105 StatusCode range(data_t start, data_t limit, data_t delta, Blob::Ptr output);
108 template <typename data_t>
109 StatusCode RangeImpl::range(data_t start, data_t limit, data_t delta, Blob::Ptr output) {
110 size_t dst_size = (output->getTensorDesc().getDims())[0];
111 data_t* dst_data = output->cbuffer().as<data_t *>() +
112 output->getTensorDesc().getBlockingDesc().getOffsetPadding();
113 size_t work_amount_dst = static_cast<size_t>(std::floor(std::abs((limit - start) / delta)));
114 if (work_amount_dst != dst_size)
115 return PARAMETER_MISMATCH;
117 parallel_nt(0, [&](const int ithr, const int nthr) {
118 size_t iwork = 0, end = 0;
119 splitter(work_amount_dst, nthr, ithr, iwork, end);
120 data_t dst_value = start + iwork * delta;
122 for (; iwork < end; ++iwork, dst_value += delta) {
123 dst_data[iwork] = dst_value;
128 REG_FACTORY_FOR(ImplFactory<RangeImpl>, Range);
131 } // namespace Extensions
132 } // namespace InferenceEngine