• 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 #ifndef MINDSPORE_CCSRC_KERNEL_OPS_UTILS_H_
17 #define MINDSPORE_CCSRC_KERNEL_OPS_UTILS_H_
18 
19 #include <memory>
20 #include <string>
21 #include <vector>
22 #include <utility>
23 #include <algorithm>
24 #include "kernel/kernel.h"
25 #include "kernel/common_utils.h"
26 
27 namespace mindspore {
28 namespace kernel {
29 BACKEND_EXPORT float Scaling(size_t in_size, size_t out_size, bool align_corners);
30 float ScaleGrid(const int x, const float scale);
Scaler(const size_t x,const float scale,bool half_pixel_centers)31 inline float Scaler(const size_t x, const float scale, bool half_pixel_centers) {
32   if (half_pixel_centers) {
33     /**
34      * function with a std::floor(), so instead of subtracting the 0.5 as we
35      * do in HalfPixelScale, we leave it as is, as the std::floor does the
36      * correct thing.
37      * */
38     return (static_cast<float>(x) + 0.5f) * scale;
39   } else {
40     /**
41      * Older incorrect scaling method that causes all resizes to have a slight
42      * translation leading to inconsistent results. For example, a flip then a
43      * resize gives different results then a resize then a flip.
44      * */
45     return static_cast<float>(x) * scale;
46   }
47 }
48 
49 struct CachedInterpolation {
50   size_t lower;
51   size_t upper;
52   float lerp;
53 };
54 
55 template <typename T>
56 struct AlignCornersFunc {
operatorAlignCornersFunc57   T operator()(const T &new_x, const int &old_length, const int &new_length) const {
58     return new_length != 1 ? new_x * (old_length - 1) / (new_length - 1) : 0;
59   }
60 };
61 
62 template <typename T>
63 struct HalfPixelFunc {
operatorHalfPixelFunc64   T operator()(const T &new_x, const int &old_length, const int &new_length) const {
65     constexpr auto half_pixel = 0.5;
66     return new_length > 1 ? (new_x + half_pixel) * old_length / new_length - half_pixel : 0;
67   }
68 };
69 
70 void ComputeInterpolationWeights(const size_t out_size, const size_t in_size, const float scale,
71                                  CachedInterpolation *interpolation, bool half_pixel_centers);
72 
73 template <typename T>
ComputeLerp(T top_left,T top_right,T bottom_left,T bottom_right,T x_lerp,T y_lerp)74 inline T ComputeLerp(T top_left, T top_right, T bottom_left, T bottom_right, T x_lerp, T y_lerp) {
75   T top = top_left + (top_right - top_left) * x_lerp;
76   T bottom = bottom_left + (bottom_right - bottom_left) * x_lerp;
77   return top + (bottom - top) * y_lerp;
78 }
79 
80 BACKEND_EXPORT std::vector<bool> Dec2Bin(const int64_t &mask);
81 // ===========================New interface==========================================================
82 BACKEND_EXPORT void FillEmptyDims(const std::string &kernel_name, std::vector<int64_t> *begin,
83                                   std::vector<int64_t> *end, std::vector<int64_t> *stride, ShapeVector *input_shape,
84                                   bool is_gpu_strided = false);
85 BACKEND_EXPORT void ParseStrideSliceMasks(const std::vector<kernel::KernelTensor *> &inputs,
86                                           std::vector<int64_t> *begin, std::vector<int64_t> *end,
87                                           std::vector<int64_t> *stride, const ShapeVector &input_shape);
88 
89 // ===========================Old interface==========================================================
90 BACKEND_EXPORT void FillEmptyDims(const BaseOperatorPtr &base_operator, std::vector<int64_t> *begin,
91                                   std::vector<int64_t> *end, std::vector<int64_t> *stride, ShapeVector *input_shape,
92                                   bool is_gpu_strided = false);
93 
94 template <typename T>
ComputeScales(const double & scale,const size_t & input_size,const size_t & output_size)95 inline T ComputeScales(const double &scale, const size_t &input_size, const size_t &output_size) {
96   if (scale > 0.) {
97     return static_cast<T>(1.0 / scale);
98   } else if (output_size > 0) {
99     return (static_cast<T>(input_size) / output_size);
100   }
101   return 0;
102 }
103 
104 template <typename T>
ComputeScalesBackward(const double scale,const int64_t src_size,const int64_t dst_size)105 inline T ComputeScalesBackward(const double scale, const int64_t src_size, const int64_t dst_size) {
106   if (scale > 0.) {
107     return static_cast<T>(scale);
108   } else if (dst_size > 0) {
109     return static_cast<T>(src_size) / dst_size;
110   }
111   return 0;
112 }
113 
NearestNeighborSourceIndex(const float & scale,const size_t & dst_index,const size_t & input_size)114 inline size_t NearestNeighborSourceIndex(const float &scale, const size_t &dst_index, const size_t &input_size) {
115   size_t src_index = std::min(static_cast<size_t>(floorf(SizeToFloat(dst_index) * scale)), input_size - 1);
116   return src_index;
117 }
118 
NearestIndex(const size_t & output_index,const size_t & input_size,const size_t & output_size,const double & scales)119 inline size_t NearestIndex(const size_t &output_index, const size_t &input_size, const size_t &output_size,
120                            const double &scales) {
121   constexpr size_t kNumberTwo = 2;
122   if (output_size == input_size) {
123     // scale_factor = 1
124     return output_index;
125   } else if (output_size == kNumberTwo * input_size) {
126     // scale_factor = 2, shift input index
127     return output_index >> 1;
128   } else {
129     auto scale = ComputeScales<float>(scales, input_size, output_size);
130     return NearestNeighborSourceIndex(scale, output_index, input_size);
131   }
132 }
133 
134 template <typename T>
AreaPixelComputeScale(int64_t input_size,int64_t output_size,bool align_corners,double scale)135 inline T AreaPixelComputeScale(int64_t input_size, int64_t output_size, bool align_corners, double scale) {
136   if (align_corners) {
137     if (output_size > 1) {
138       return static_cast<T>(input_size - 1) / (output_size - 1);
139     } else {
140       return static_cast<T>(0);
141     }
142   } else {
143     return ComputeScales<T>(scale, input_size, output_size);
144   }
145 }
146 
147 template <typename T>
AreaPixelComputeSourceIndex(T scale,int64_t dst_index,bool align_corners)148 inline T AreaPixelComputeSourceIndex(T scale, int64_t dst_index, bool align_corners) {
149   if (align_corners) {
150     return scale * static_cast<T>(dst_index);
151   } else {
152     constexpr T zero = 0.;
153     T src_idx = scale * (LongToDouble(dst_index) + 0.5) - 0.5;
154     return src_idx < zero ? zero : src_idx;
155   }
156 }
157 
158 template <typename T>
DataIndexInit(const T * offset)159 inline T DataIndexInit(const T *offset) {
160   return *offset;
161 }
162 
163 template <typename T, typename... Args>
DataIndexInit(T * offset,T * x,const T * X,Args &&...args)164 inline T DataIndexInit(T *offset, T *x, const T *X, Args &&... args) {
165   auto off = DataIndexInit(offset, std::forward<Args>(args)...);
166   *x = off % *X;
167   return off / *X;
168 }
169 
DataIndexStep()170 inline bool DataIndexStep() { return true; }
171 
172 template <typename T, typename... Args>
DataIndexStep(T * x,const T * X,Args &&...args)173 inline bool DataIndexStep(T *x, const T *X, Args &&... args) {
174   if (DataIndexStep(std::forward<Args>(args)...)) {
175     *x = ((*x + 1) == *X) ? 0 : (*x + 1);
176     return *x == 0;
177   }
178   return false;
179 }
180 
181 template <typename T>
ComputeSourceIndexAndLambda(int64_t * const input_index0,int64_t * const input_index1,T * const lambda0,T * const lambda1,T ratio,int64_t output_index,int64_t input_size,int64_t output_size,bool align_corners)182 inline void ComputeSourceIndexAndLambda(int64_t *const input_index0, int64_t *const input_index1, T *const lambda0,
183                                         T *const lambda1, T ratio, int64_t output_index, int64_t input_size,
184                                         int64_t output_size, bool align_corners) {
185   if (output_size == input_size) {
186     // scale_factor = 1
187     *input_index0 = output_index;
188     *input_index1 = output_index;
189     *lambda0 = static_cast<T>(1);
190     *lambda1 = static_cast<T>(0);
191   } else {
192     const T real_input_index = AreaPixelComputeSourceIndex<T>(ratio, output_index, align_corners);
193     *input_index0 = static_cast<int64_t>(real_input_index);
194     int64_t offset = (*input_index0 < input_size - 1) ? 1 : 0;
195     *input_index1 = *input_index0 + offset;
196     *lambda1 = real_input_index - static_cast<T>(*input_index0);
197     constexpr T one = 1.0;
198     *lambda0 = one - *lambda1;
199   }
200 }
201 
202 BACKEND_EXPORT void CheckSliceValid(const std::vector<int64_t> &start, const std::vector<int64_t> &stop,
203                                     const std::vector<int64_t> &step, const std::vector<int64_t> &input_shape);
204 BACKEND_EXPORT size_t CalOffset(const std::vector<int64_t> &start, const std::vector<int64_t> &stop,
205                                 const std::vector<int64_t> &dim_offset);
206 BACKEND_EXPORT std::vector<int64_t> CalDimOffset(const std::vector<int64_t> &input_shape);
207 BACKEND_EXPORT size_t GetCopySize(const std::vector<int64_t> &dim_offset, const std::vector<int64_t> &start,
208                                   const std::vector<int64_t> &stop);
209 
210 BACKEND_EXPORT std::pair<MatrixDiag::Alignment, MatrixDiag::Alignment> GetAlignments(const std::string &alignment);
211 
212 namespace broadcast_utils {
213 BACKEND_EXPORT bool AlignedBroadCastShape(size_t align_rank, std::vector<size_t> *broadcast, std::vector<size_t> *lhs,
214                                           std::vector<size_t> *rhs);
215 }  // namespace broadcast_utils
216 
217 #define CHECK_KERNEL_WORKSPACE_SIZE(actual_size, expect_size, kernel_name)                                           \
218   do {                                                                                                               \
219     if ((actual_size) != (expect_size)) {                                                                            \
220       MS_LOG(EXCEPTION) << (kernel_name) << " requires " << (expect_size) << " workspace, but got " << (actual_size) \
221                         << ".";                                                                                      \
222     }                                                                                                                \
223   } while (0)
224 }  // namespace kernel
225 }  // namespace mindspore
226 
227 #endif  // MINDSPORE_CCSRC_KERNEL_OPS_UTILS_H_
228