Publishing 2019 R1 content
[platform/upstream/dldt.git] / inference-engine / src / inference_engine / shape_infer / const_infer / ie_fill_const_infer.hpp
1 // Copyright (C) 2019 Intel Corporation
2 // SPDX-License-Identifier: Apache-2.0
3 //
4
5 #pragma once
6
7 #include <ie_blob.h>
8 #include <map>
9 #include <memory>
10 #include <string>
11 #include <vector>
12 #include <ie_layers.h>
13 #include <ie_memcpy.h>
14 #include "ie_const_infer_impl.hpp"
15
16 namespace InferenceEngine {
17 namespace ShapeInfer {
18
19 /**
20  *@brief Implementation of Const inference for Fill layer
21  */
22 class FillConstInfer : public ConstInferImpl {
23 public:
24     explicit FillConstInfer(const std::string& type) : ConstInferImpl(type) {}
25
26     void inferImpl(const std::vector<Blob::CPtr>& inData,
27                    const std::map<std::string, std::string>& params,
28                    const std::map<std::string, Blob::Ptr>& blobs,
29                    std::vector<Blob::Ptr>& outData) override {
30         const size_t FILL_DIMS = 0;
31         const size_t FILL_VALUE = 1;
32         if (inData.empty() || outData.empty())
33             THROW_IE_EXCEPTION << " Incorrect number of input/output edges!";
34
35         if (inData.size() != 2)
36             THROW_IE_EXCEPTION << " Incorrect number of input edges!";
37
38         SizeVector dims = inData[FILL_DIMS]->getTensorDesc().getDims();
39         if (dims.size() > 1)
40             THROW_IE_EXCEPTION << " Fill dimensions vector should be 1 dimension";
41
42         if (inData[FILL_DIMS]->getTensorDesc().getPrecision() != Precision::I32)
43             THROW_IE_EXCEPTION << " Fill dimensions vector should be I32!";
44
45         SizeVector value_dims = inData[FILL_VALUE]->getTensorDesc().getDims();
46         if (value_dims.size() > 1)
47             THROW_IE_EXCEPTION << " Value scalar should have 1 dimension";
48
49         if (!(inData[FILL_VALUE]->getTensorDesc().getPrecision() == Precision::I32 &&
50               outData[0]->getTensorDesc().getPrecision() == Precision::I32) &&
51             !(inData[FILL_VALUE]->getTensorDesc().getPrecision() == Precision::FP32 &&
52               outData[0]->getTensorDesc().getPrecision() == Precision::FP32)) {
53             THROW_IE_EXCEPTION <<
54                                " 'Value' input scalars and output tensor should have same precision and only FP32 and I32 are supported!";
55         }
56
57         int32_t* fill_dims = inData[FILL_DIMS]->cbuffer().as<int32_t*>() +
58                              inData[FILL_DIMS]->getTensorDesc().getBlockingDesc().getOffsetPadding();
59         size_t fill_size = inData[FILL_DIMS]->getTensorDesc().getDims()[0];
60         SizeVector dst_dims = outData[0]->getTensorDesc().getDims();
61
62         if (dst_dims.size() != fill_size) {
63             THROW_IE_EXCEPTION << "Output tensor dimension mismatch";
64         }
65
66         size_t work_amount_dst = 1;
67         for (size_t i = 0; i < dst_dims.size(); i++) {
68             work_amount_dst *= fill_dims[i];
69             if (static_cast<int>(dst_dims[i]) != fill_dims[i]) {
70                 THROW_IE_EXCEPTION << "Output tensor dimension size mismatch";
71             }
72         }
73
74         switch (outData[0]->precision()) {
75             case Precision::FP32: {
76                 float* dst_data = outData[0]->cbuffer().as<float*>() +
77                                   outData[0]->getTensorDesc().getBlockingDesc().getOffsetPadding();
78                 float value = (inData[FILL_VALUE]->cbuffer().as<float*>() +
79                                inData[FILL_VALUE]->getTensorDesc().getBlockingDesc().getOffsetPadding())[0];
80
81                 parallel_nt(0, [&](const int ithr, const int nthr) {
82                     size_t start = 0, end = 0;
83                     splitter(work_amount_dst, nthr, ithr, start, end);
84                     std::fill_n(dst_data + start, end - start, value);
85                 });
86             }
87                 break;
88             case Precision::I32: {
89                 int32_t* dst_data = outData[0]->cbuffer().as<int32_t*>() +
90                                     outData[0]->getTensorDesc().getBlockingDesc().getOffsetPadding();
91                 int32_t value = (inData[FILL_VALUE]->cbuffer().as<int32_t*>() +
92                                  inData[FILL_VALUE]->getTensorDesc().getBlockingDesc().getOffsetPadding())[0];
93
94                 parallel_nt(0, [&](const int ithr, const int nthr) {
95                     size_t start = 0, end = 0;
96                     splitter(work_amount_dst, nthr, ithr, start, end);
97                     std::fill_n(dst_data + start, end - start, value);
98                 });
99             }
100                 break;
101             default:
102                 THROW_IE_EXCEPTION << "Incorrect output precision. Only FP32 and I32 are supported!";
103         }
104     }
105 };
106
107 }  // namespace ShapeInfer
108 }  // namespace InferenceEngine