• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /**
2  * Copyright 2023 Huawei Technologies Co., Ltd
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include "ops/ops_func_impl/tile.h"
18 
19 #include <algorithm>
20 #include <memory>
21 #include "ir/functor.h"
22 #include "mindapi/base/shape_vector.h"
23 #include "ops/op_utils.h"
24 #include "ops/op_name.h"
25 #include "plugin/device/cpu/kernel/nnacl/op_base.h"
26 #include "utils/check_convert_utils.h"
27 #include "utils/convert_utils_base.h"
28 #include "utils/shape_utils.h"
29 #include "utils/log_adapter.h"
30 #include "ir/primitive.h"
31 #include "abstract/dshape.h"
32 #include "base/base.h"
33 #include "ir/dtype/number.h"
34 
35 namespace mindspore::ops {
36 namespace {
ToMultiplesVector(const ArrayValue<int64_t> & array_value)37 ShapeVector ToMultiplesVector(const ArrayValue<int64_t> &array_value) {
38   auto len = array_value.size();
39   ShapeVector multiples_vec;
40   multiples_vec.reserve(len);
41   for (size_t i = 0; i < len; ++i) {
42     if (array_value.IsValueUnknown(i)) {
43       multiples_vec.push_back(abstract::Shape::kShapeDimAny);
44       continue;
45     }
46 
47     if (array_value[i] < 0) {
48       MS_EXCEPTION(ValueError) << "For 'Tile', 'dims' cannot contain negative integer numbers, but got "
49                                << array_value[i] << " in " << i << "th.";
50     }
51     multiples_vec.push_back(array_value[i]);
52   }
53 
54   return multiples_vec;
55 }
56 }  // namespace
AdaptShapeAndMultipies(ShapeVector * shape,ShapeVector * dims)57 void AdaptShapeAndMultipies(ShapeVector *shape, ShapeVector *dims) {
58   MS_EXCEPTION_IF_NULL(shape);
59   if (MS_UNLIKELY(IsDynamicRank(*shape))) {
60     MS_LOG(INTERNAL_EXCEPTION) << "Shape should not be dynamic rank!";
61   }
62   MS_EXCEPTION_IF_NULL(dims);
63 
64   auto rank = shape->size();
65   auto len = dims->size();
66   if (len == rank) {
67     return;
68   }
69 
70   auto expect_len = std::max(rank, len);
71   auto ExpandInHeadIfNeed = [](ShapeVector *vec, size_t length) -> void {
72     if (vec->size() == length) {
73       return;
74     }
75 
76     auto offset = length - vec->size();
77     ShapeVector res;
78     vec->reserve(length);
79     vec->insert(vec->begin(), offset, 1);
80   };
81 
82   ExpandInHeadIfNeed(shape, expect_len);
83   ExpandInHeadIfNeed(dims, expect_len);
84 }
85 
InferShape(const PrimitivePtr & primitive,const std::vector<AbstractBasePtr> & input_args) const86 BaseShapePtr TileFuncImpl::InferShape(const PrimitivePtr &primitive,
87                                       const std::vector<AbstractBasePtr> &input_args) const {
88   // The output rank is determined by data's rank and dims's length.
89   auto x_base_shape = input_args[kInputIndex0]->GetShape();
90   auto x_shape = x_base_shape->GetShapeVector();
91   if (MS_UNLIKELY(IsDynamicRank(x_shape))) {
92     return std::make_shared<abstract::TensorShape>(ShapeVector{abstract::TensorShape::kShapeRankAny});
93   }
94 
95   auto dims_base_shape = input_args[kInputIndex1]->GetShape();
96   if (MS_UNLIKELY(dims_base_shape->isa<abstract::DynamicSequenceShape>())) {
97     return std::make_shared<abstract::TensorShape>(ShapeVector{abstract::TensorShape::kShapeRankAny});
98   }
99 
100   auto dims_array_opt = GetArrayValue<int64_t>(input_args[kInputIndex1]);
101   MS_CHECK_VALUE(dims_array_opt.has_value(),
102                  CheckAndConvertUtils::FormatCommMsg("For primitive[Tile], the dims must has value here."));
103   auto dims_array = dims_array_opt.value();
104   auto dims = ToMultiplesVector(dims_array);
105 
106   AdaptShapeAndMultipies(&x_shape, &dims);
107   auto adapted_rank = x_shape.size();
108   ShapeVector inferred_shape;
109   inferred_shape.reserve(adapted_rank);
110   for (size_t i = 0; i < adapted_rank; ++i) {
111     if (x_shape[i] == abstract::Shape::kShapeDimAny || dims[i] == abstract::Shape::kShapeDimAny) {
112       inferred_shape.push_back(abstract::Shape::kShapeDimAny);
113       continue;
114     }
115 
116     inferred_shape.push_back(dims[i] * x_shape[i]);
117   }
118   return std::make_shared<abstract::TensorShape>(inferred_shape);
119 }
120 
InferType(const PrimitivePtr & primitive,const std::vector<AbstractBasePtr> & input_args) const121 TypePtr TileFuncImpl::InferType(const PrimitivePtr &primitive, const std::vector<AbstractBasePtr> &input_args) const {
122   auto input_type = input_args[kInputIndex0]->GetType();
123   return input_type->Clone();
124 }
125 }  // namespace mindspore::ops
126