已合并
refactor: 为公共op_api头文件增加NN后缀 #10791
refactor: 为公共op_api头文件增加NN后缀 #10791
已合并
clinglai0517创建于 22 天前
共 8 个文件变更+782-750
@@ -20,7 +20,7 @@
20#include "aclnn_kernels/contiguous.h"20#include "aclnn_kernels/contiguous.h"
21#include "logsigmoid.h"21#include "logsigmoid.h"
22#include "aclnn_kernels/reshape.h"22#include "aclnn_kernels/reshape.h"
23-#include "op_api/level2_base_caculation.h"23+#include "op_api/level2_base_caculation_nn.h"
24using namespace op;24using namespace op;
25#ifdef __cplusplus25#ifdef __cplusplus
26extern "C" {26extern "C" {
@@ -18,7 +18,7 @@
18#include "opdev/make_op_executor.h"18#include "opdev/make_op_executor.h"
19#include "opdev/platform.h"19#include "opdev/platform.h"
20#include "aclnn_kernels/common/op_error_check.h"20#include "aclnn_kernels/common/op_error_check.h"
21-#include "op_api/level2_base.h"21+#include "op_api/level2_base_nn.h"
22#include "mish.h"22#include "mish.h"
23#include "aclnn_mish.h"23#include "aclnn_mish.h"
24 24 
@@ -18,7 +18,7 @@
18#include "opdev/common_types.h"18#include "opdev/common_types.h"
19#include "opdev/data_type_utils.h"19#include "opdev/data_type_utils.h"
20#include "opdev/format_utils.h"20#include "opdev/format_utils.h"
21-#include "op_api/level2_base_caculation.h"21+#include "op_api/level2_base_caculation_nn.h"
22#include "opdev/op_dfx.h"22#include "opdev/op_dfx.h"
23#include "opdev/op_executor.h"23#include "opdev/op_executor.h"
24#include "opdev/op_log.h"24#include "opdev/op_log.h"
@@ -8,501 +8,9 @@
8 * See LICENSE in the root of the software repository for the full text of the License.8 * See LICENSE in the root of the software repository for the full text of the License.
9 */9 */
10 10 
11-#ifndef LEVEL2_BASE_H_11+#ifndef OPS_NN_LEGACY_LEVEL2_BASE_H_
12-#define LEVEL2_BASE_H_12+#define OPS_NN_LEGACY_LEVEL2_BASE_H_
13 13 
14-#include <algorithm>14+#include "op_api/level2_base_nn.h"
15-#include "op_api/op_api_def_nn.h"
16-#include "op_api/aclnn_util.h"
17-#include "aclnn/aclnn_base.h"
18-#include "opdev/platform.h"
19-#include "opdev/common_types.h"
20-#include "opdev/fast_vector.h"
21 15 
22-#ifdef __cplusplus16+#endif // OPS_NN_LEGACY_LEVEL2_BASE_H_
23-extern "C" {
24-#endif
25- 
26-namespace op {
27- 
28-// 根据API定义,需要列出所能支持的所有dtype
29-static const std::initializer_list<op::DataType> DTYPE_SUPPORT_LISTS = {
30- op::DataType::DT_FLOAT, op::DataType::DT_FLOAT16, op::DataType::DT_DOUBLE, op::DataType::DT_BF16};
31-static const int64_t UPSAMPLE_EXPECT_SIZE = 3;
32-static const int64_t UPSAMPLE_DIM_LIMIT = 5;
33-static constexpr size_t DIM_ZERO = 0;
34-static constexpr size_t DIM_ONE = 1;
35-static constexpr size_t DIM_TWO = 2;
36-static constexpr size_t DIM_THREE = 3;
37-static constexpr size_t DIM_FOUR = 4;
38- 
39-// 检查1个输入和1个输出是否是空指针
40-inline static bool CheckNotNull2Tensor(const aclTensor* t0, const aclTensor* t1)
41-{
42- OP_CHECK_NULL(t0, return false);
43- OP_CHECK_NULL(t1, return false);
44- 
45- return true;
46-}
47-inline static bool CheckNotNull3Tensor(const aclTensor* t0, const aclTensor* t1, const aclTensor* t2)
48-{
49- // 检查输入是否是空指针
50- OP_CHECK_NULL(t0, return false);
51- OP_CHECK_NULL(t1, return false);
52- // 检查输入是否是空指针
53- OP_CHECK_NULL(t2, return false);
54- 
55- return true;
56-}
57-// 检查3个输入和1个输出是否是空指针
58-inline static bool CheckNotNull4Tensor(const aclTensor* t0, const aclTensor* t1, const aclTensor* t2,
59- const aclTensor* t3)
60-{
61- // 检查输入是否是空指针
62- OP_CHECK_NULL(t0, return false);
63- OP_CHECK_NULL(t1, return false);
64- OP_CHECK_NULL(t2, return false);
65- // 检查输入是否是空指针
66- OP_CHECK_NULL(t3, return false);
67- 
68- return true;
69-}
70- 
71-inline static bool CheckNotNull2In1Out(const aclTensor* gradOutput, const aclTensor* input, const aclTensor* grid,
72- const aclTensor* inputGrad, const aclTensor* gridGrad)
73-{
74- OP_CHECK_NULL(gradOutput, return false);
75- OP_CHECK_NULL(input, return false);
76- OP_CHECK_NULL(grid, return false);
77- OP_CHECK_NULL(inputGrad, return false);
78- OP_CHECK_NULL(gridGrad, return false);
79- return true;
80-}
81- 
82-inline static bool CheckNotNull2In2Out(const aclTensor* gradOut, const aclIntArray* outputSize,
83- const aclIntArray* inputSize, const aclTensor* gradInput)
84-{
85- OP_CHECK_NULL(gradOut, return false);
86- OP_CHECK_NULL(outputSize, return false);
87- OP_CHECK_NULL(inputSize, return false);
88- OP_CHECK_NULL(gradInput, return false);
89- return true;
90-}
91- 
92-/**
93- * 1. 1个输入1个输出
94- * 2. 输入输出的shape必须一致
95- * 3. 输入的维度必须小于等于8
96- */
97-inline static bool CheckSameShape1In1Out(const aclTensor* self, const aclTensor* out)
98-{
99- // self和out的shape必须一致
100- OP_CHECK_SHAPE_NOT_EQUAL(self, out, return false);
101- // self的维度必须小于等于8
102- OP_CHECK_MAX_DIM(self, MAX_SUPPORT_DIMS_NUMS, return false);
103- 
104- return true;
105-}
106- 
107-inline static bool CheckShapeCumMinMax(const aclTensor* self, const aclTensor* valuesOut, const aclTensor* indicesOut)
108-{
109- // 所有输入的维度都不能超过8
110- OP_CHECK_MAX_DIM(self, MAX_SUPPORT_DIMS_NUMS, return false);
111- 
112- // self和valuesOut、indicesOut的shape必须一致
113- OP_CHECK_SHAPE_NOT_EQUAL(self, valuesOut, return false);
114- OP_CHECK_SHAPE_NOT_EQUAL(self, indicesOut, return false);
115- return true;
116-}
117- 
118-inline static bool CheckSameShapeNotlimit1In1Out(const aclTensor* self, const aclTensor* out)
119-{
120- // self和out的shape必须一致
121- OP_CHECK_SHAPE_NOT_EQUAL(self, out, return false);
122- return true;
123-}
124- 
125-inline static bool CheckShapeNotlimitDim1In1Out(const aclTensor* self)
126-{
127- OP_CHECK_MAX_DIM(self, MAX_SUPPORT_DIMS_NUMS, return false);
128- return true;
129-}
130- 
131-// 检查1个输入和1个输出的数据类型是否在算子的支持列表内
132-static inline bool CheckDtypeValid1In1Out(const aclTensor* self, const aclTensor* out,
133- const std::initializer_list<op::DataType>& dtypeSupportList,
134- const std::initializer_list<op::DataType>& dtypeOutList)
135-{
136- OP_CHECK_DTYPE_NOT_SUPPORT(self, dtypeSupportList, return false);
137- // 检查输出的数据类型是否在算子的支持列表内
138- OP_CHECK_DTYPE_NOT_SUPPORT(out, dtypeOutList, return false);
139- 
140- return true;
141-}
142- 
143-// 检查1个输入和1个输出的数据类型是否在算子的支持列表内
144-static inline bool CheckDtypeValid1In1OutScalar(const aclTensor* self, const aclScalar* attrScalar,
145- const aclTensor* out,
146- const std::initializer_list<op::DataType>& dtypeSupportList,
147- const std::initializer_list<op::DataType>& attrScalarSupportList,
148- const std::initializer_list<op::DataType>& dtypeOutList)
149-{
150- // 检查self的数据类型是否在支持列表内
151- OP_CHECK_DTYPE_NOT_SUPPORT(self, dtypeSupportList, return false);
152- // 检查attr的数据类型是否在支持列表内
153- OP_CHECK_DTYPE_NOT_SUPPORT(attrScalar, attrScalarSupportList, return false);
154- // 检查out的数据类型是否在支持列表内
155- OP_CHECK_DTYPE_NOT_SUPPORT(out, dtypeOutList, return false);
156- 
157- // 检查self和out的数据类型是否一致
158- OP_CHECK_DTYPE_NOT_SAME(self, out, return false);
159- 
160- return true;
161-}
162- 
163-// 检查1个输入和1个输出的数据类型是否在算子的支持列表内
164-static inline bool CheckDtypeValid1In1OutTensor(const aclTensor* self, const aclTensor* attrTensor,
165- const aclTensor* out,
166- const std::initializer_list<op::DataType>& dtypeSupportList,
167- const std::initializer_list<op::DataType>& attrTensorSupportList,
168- const std::initializer_list<op::DataType>& dtypeOutList)
169-{
170- // 检查self的数据类型是否在支持列表内
171- OP_CHECK_DTYPE_NOT_SUPPORT(self, dtypeSupportList, return false);
172- // 检查attr的数据类型是否在支持列表内
173- OP_CHECK_DTYPE_NOT_SUPPORT(attrTensor, attrTensorSupportList, return false);
174- // 检查out的数据类型是否在支持列表内
175- OP_CHECK_DTYPE_NOT_SUPPORT(out, dtypeOutList, return false);
176- 
177- // 检查self和out的数据类型是否一致
178- OP_CHECK_DTYPE_NOT_SAME(self, out, return false);
179- 
180- return true;
181-}
182- 
183-static inline bool CheckDtypeValid1In1OutMatch(const aclTensor* self, const aclTensor* valueOut,
184- const aclTensor* inverseOut, const aclTensor* countsOut,
185- const std::initializer_list<op::DataType>& dtypeSupportList)
186-{
187- // 检查self的数据类型是否在UniqueConsecutive算子的支持列表内
188- OP_CHECK_DTYPE_NOT_SUPPORT(self, dtypeSupportList, return false);
189- 
190- // 检查inverseOut数据类型
191- OP_CHECK_DTYPE_NOT_MATCH(inverseOut, op::DataType::DT_INT64, return false);
192- 
193- // 检查countsOut数据类型
194- OP_CHECK_DTYPE_NOT_MATCH(countsOut, op::DataType::DT_INT64, return false);
195- 
196- // 检查self与valueOut数据类型一致
197- OP_CHECK_DTYPE_NOT_MATCH(valueOut, self->GetDataType(), return false);
198- 
199- // 检查inverseOut与countsOut数据类型一致
200- OP_CHECK_DTYPE_NOT_MATCH(inverseOut, countsOut->GetDataType(), return false);
201- return true;
202-}
203- 
204-/**
205- * l1: DAV_2201 芯片,该算子支持的数据类型列表
206- * l2: 其他芯片,该算子支持的数据类型列表
207- */
208-inline static const std::initializer_list<DataType>& GetDtypeSupportListV1(
209- const std::initializer_list<op::DataType>& l1, const std::initializer_list<op::DataType>& l2)
210-{
211- if (GetCurrentPlatformInfo().GetCurNpuArch() == NpuArch::DAV_2201) {
212- return l1;
213- } else {
214- return l2;
215- }
216-}
217- 
218-/**
219- * l1: DAV_2201 和 DAV_3510芯片,该算子支持的数据类型列表
220- * l2: 其他芯片,该算子支持的数据类型列表
221- */
222-inline static const std::initializer_list<DataType>& GetDtypeSupportListV2(
223- const std::initializer_list<op::DataType>& l1, const std::initializer_list<op::DataType>& l2)
224-{
225- if (GetCurrentPlatformInfo().GetCurNpuArch() == NpuArch::DAV_2201 || Ops::NN::AclnnUtil::IsRegbase()) {
226- return l1;
227- } else {
228- return l2;
229- }
230-}
231- 
232-inline static const std::initializer_list<op::DataType> GetDtypeSupportListV3(
233- const std::initializer_list<op::DataType>& l1, const std::initializer_list<op::DataType>& l2)
234-{
235- auto npuArch = GetCurrentPlatformInfo().GetCurNpuArch();
236- switch (npuArch) {
237- case NpuArch::DAV_3510:
238- case NpuArch::DAV_2201: {
239- return l1;
240- }
241- case NpuArch::DAV_1001: {
242- return l2;
243- }
244- default: {
245- // 如果既不是1971也不是1980,先暂且默认当做1971处理
246- return l1;
247- }
248- }
249-}
250- 
251-static inline aclnnStatus CheckArrayDataAvgPoolBackWard(const aclIntArray* kernelSize, const aclIntArray* stride,
252- const aclIntArray* padding)
253-{
254- for (uint64_t i = 0; i < kernelSize->Size(); i++) {
255- auto size = (*kernelSize)[i];
256- if (size <= 0) {
257- OP_LOGE(ACLNN_ERR_PARAM_INVALID, "kernelSize [%lu] data [%li] is less than or equal to 0", i, size);
258- return ACLNN_ERR_PARAM_INVALID;
259- }
260- }
261- 
262- for (uint64_t i = 0; i < stride->Size(); i++) {
263- auto size = (*stride)[i];
264- if (size <= 0) {
265- OP_LOGE(ACLNN_ERR_PARAM_INVALID, "stride [%lu] data [%li] is less than or equal to 0", i, size);
266- return ACLNN_ERR_PARAM_INVALID;
267- }
268- }
269- 
270- if (kernelSize->Size() != padding->Size()) {
271- return ACLNN_ERR_PARAM_INVALID;
272- }
273- 
274- for (uint64_t i = 0; i < kernelSize->Size(); i++) {
275- auto halfKsize = (*kernelSize)[i] / 2;
276- auto padSize = (*padding)[i];
277- if (halfKsize < padSize) {
278- OP_LOGE(ACLNN_ERR_PARAM_INVALID, "padding [%lu] data [%li] should less than kernelSize / 2 [%ld]", i,
279- padSize, halfKsize);
280- return ACLNN_ERR_PARAM_INVALID;
281- }
282- if (padSize < 0) {
283- OP_LOGE(ACLNN_ERR_PARAM_INVALID, "padding [%lu] data [%li] is less than 0", i, padSize);
284- return ACLNN_ERR_PARAM_INVALID;
285- }
286- }
287- return ACLNN_SUCCESS;
288-}
289- 
290-inline static bool CheckPaddingValidAvgPool2D(const aclIntArray* kernelSize, const aclIntArray* padding)
291-{
292- const int64_t kKernelSizeHIdx = 0;
293- const int64_t kKernelSizeWIdx = 1;
294- const int64_t kPaddingUpIdx = 0;
295- const int64_t kPaddingLeftIdx = 1;
296- const int64_t kernelH = (*kernelSize)[kKernelSizeHIdx];
297- const int64_t kernelPaddingSize = 1;
298- const int64_t MULTIPLIER = 2;
299- // 1表示kernelSize长度为1
300- const int64_t kernelW = kernelSize->Size() == kernelPaddingSize ? (*kernelSize)[kKernelSizeHIdx] :
301- (*kernelSize)[kKernelSizeWIdx];
302- OP_CHECK(padding->Size() != 0, OP_LOGE(ACLNN_ERR_PARAM_INVALID, "padding is empty"), return false);
303- const int64_t paddingH = (*padding)[kPaddingUpIdx];
304- const int64_t paddingW = padding->Size() == kernelPaddingSize ? (*padding)[kPaddingUpIdx] :
305- (*padding)[kPaddingLeftIdx];
306- // MULTIPLIER 表示paddingH不能大于kernelH的一半,下同
307- if (kernelH < MULTIPLIER * paddingH) {
308- OP_LOGE(ACLNN_ERR_PARAM_INVALID,
309- "value of paddingH should be at most half of kernelH. Actual: paddingH is [%ld],kernelH is [%ld].",
310- paddingH, kernelH);
311- return false;
312- }
313- if (kernelW < MULTIPLIER * paddingW) {
314- OP_LOGE(ACLNN_ERR_PARAM_INVALID,
315- "value of paddingW should be at most half of kernelW. Actual: paddingW is [%ld],"
316- "kernelW is [%ld].",
317- paddingW, kernelW);
318- return false;
319- }
320- return true;
321-}
322- 
323-static inline bool CheckDtypeValid1Out1In(const aclTensor* gradOut, const aclTensor* gradInput)
324-{
325- // 检查gradOut的数据类型是否在ResizeNearestNeighborV2Grad算子的支持列表内
326- OP_CHECK_DTYPE_NOT_SUPPORT(gradOut, DTYPE_SUPPORT_LISTS, return false);
327- // 检查gradInput的数据类型是否与gradOut一致
328- OP_CHECK_DTYPE_NOT_MATCH(gradOut, gradInput->GetDataType(), return false);
329- return true;
330-}
331- 
332-inline static bool CheckUpsampleShape(const aclTensor* gradOut, const aclIntArray* outputSize,
333- const aclIntArray* inputSize)
334-{
335- size_t outputSizeNum = outputSize->Size();
336- size_t inputSizeNum = inputSize->Size();
337- OP_CHECK_WRONG_DIMENSION(gradOut, UPSAMPLE_DIM_LIMIT, return false);
338- OP_CHECK(
339- outputSizeNum == UPSAMPLE_EXPECT_SIZE,
340- OP_LOGE(ACLNN_ERR_PARAM_INVALID, "It is expected output_size equals to 3, but got size %zu", outputSizeNum),
341- return false);
342- 
343- OP_CHECK(inputSizeNum == UPSAMPLE_DIM_LIMIT,
344- OP_LOGE(ACLNN_ERR_PARAM_INVALID, "It is expected input_size equals to 5, but got size %zu", inputSizeNum),
345- return false);
346- return true;
347-}
348- 
349-static inline bool CheckPromoteTypeGeluBackward(const aclTensor* gradOutput, const aclTensor* self,
350- op::DataType& promoteType,
351- const std::initializer_list<DataType> dtypeSupportList)
352-{
353- // 检查self和gradOutput能否做数据类型推导
354- promoteType = op::PromoteType(gradOutput->GetDataType(), self->GetDataType());
355- if (promoteType == DataType::DT_UNDEFINED) {
356- OP_LOGE(ACLNN_ERR_PARAM_INVALID, "GradOutput dtype %s and Self dtype %s can not be promoted.",
357- op::ToString(gradOutput->GetDataType()).GetString(), op::ToString(self->GetDataType()).GetString());
358- return false;
359- }
360- 
361- if (!(GetCurrentPlatformInfo().GetCurNpuArch() == NpuArch::DAV_2201 || Ops::NN::AclnnUtil::IsRegbase()) &&
362- (promoteType == op::DataType::DT_BF16)) {
363- OP_LOGE(ACLNN_ERR_PARAM_INVALID, "Input dtype of gelu is not support bfloat16 in current socversion.");
364- return false;
365- }
366- 
367- // 检查promoteType的数据类型是否在支持列表内
368- if (!CheckType(promoteType, dtypeSupportList)) {
369- OP_LOGE(ACLNN_ERR_PARAM_INVALID, "promoteType dtype %s should be in dtype support list %s.",
370- op::ToString(promoteType).GetString(), op::ToString(dtypeSupportList).GetString());
371- return false;
372- }
373- return true;
374-}
375- 
376-// 循环判断size是否相等
377-inline static bool CheckSizeLoop(size_t dimNum, Shape gradOutShape, FVector<int64_t>& fullOutputSize)
378-{
379- for (size_t i = 0; i < dimNum; ++i) {
380- if (gradOutShape.GetDim(i) != fullOutputSize[i]) {
381- OP_LOGE(ACLNN_ERR_PARAM_INVALID,
382- "Expected grad_output to have the same shape as output;"
383- " output.size(%zu) = %ld but got grad_output.size(%zu) = %ld",
384- i, fullOutputSize[i], i, gradOutShape.GetDim(i));
385- return false;
386- }
387- }
388- return true;
389-}
390- 
391-static inline bool CheckInputNullTensorMaxUnPool3D(const aclTensor* self)
392-{
393- auto inputShape = self->GetViewShape();
394- size_t dimNum = inputShape.GetDimNum();
395- 
396- for (size_t i = 1; i < dimNum; ++i) {
397- if (inputShape.GetDim(i) <= 0) {
398- OP_LOGE(ACLNN_ERR_PARAM_INVALID,
399- "max_unpool3d(): Expected input to have non-zero size for non-batch dimensions, "
400- "but got %zu with dimension %zu being empty.",
401- dimNum, i);
402- return false;
403- }
404- }
405- return true;
406-}
407- 
408-static inline bool CheckIntArrayShapeMaxUnPool3D(const aclTensor* self, const aclIntArray* outputSize,
409- const aclIntArray* stride, const aclIntArray* padding)
410-{
411- constexpr size_t NCDHW_DIM_NUM = 5;
412- constexpr int64_t EXPECT_SIZE = 3;
413- 
414- OP_CHECK(outputSize->Size() == EXPECT_SIZE,
415- OP_LOGE(ACLNN_ERR_PARAM_INVALID,
416- "There should be exactly three elements (depth, height, width) in "
417- "output_size, but got %zu elements",
418- outputSize->Size()),
419- return false);
420- OP_CHECK(stride->Size() == EXPECT_SIZE,
421- OP_LOGE(ACLNN_ERR_PARAM_INVALID,
422- "There should be exactly three elements (depth, height, width) in "
423- "stride, but got %zu elements",
424- stride->Size()),
425- return false);
426- OP_CHECK(padding->Size() == EXPECT_SIZE,
427- OP_LOGE(ACLNN_ERR_PARAM_INVALID,
428- "There should be exactly three elements (depth, height, width) in "
429- "padding, but got %zu elements",
430- padding->Size()),
431- return false);
432- 
433- for (size_t i = 0; i < EXPECT_SIZE; ++i) {
434- if ((*stride)[i] <= 0) {
435- OP_LOGE(ACLNN_ERR_PARAM_INVALID, "strides[%zu] shoule be greater than zero, but got %ld.", i, (*stride)[i]);
436- return false;
437- }
438- if ((*outputSize)[i] <= 0) {
439- OP_LOGE(ACLNN_ERR_PARAM_INVALID, "outputSize[%zu] should be greater than zero, but got %ld.", i,
440- (*outputSize)[i]);
441- return false;
442- }
443- }
444- 
445- int64_t dimD = self->GetViewShape().GetDim(DIM_ONE);
446- int64_t dimH = self->GetViewShape().GetDim(DIM_TWO);
447- int64_t dimW = self->GetViewShape().GetDim(DIM_THREE);
448- 
449- if (self->GetViewShape().GetDimNum() == NCDHW_DIM_NUM) {
450- dimD = self->GetViewShape().GetDim(DIM_TWO);
451- dimH = self->GetViewShape().GetDim(DIM_THREE);
452- dimW = self->GetViewShape().GetDim(DIM_FOUR);
453- }
454- 
455- OP_CHECK(((*outputSize)[DIM_ZERO] * (*outputSize)[DIM_ONE] * (*outputSize)[DIM_TWO]) >= (dimD * dimH * dimW),
456- OP_LOGE(ACLNN_ERR_PARAM_INVALID,
457- "The output dimensions are of size %ld x %ld x %ld, "
458- "should be greater than or equal to self of size %ld x %ld x %ld.",
459- (*outputSize)[DIM_ZERO], (*outputSize)[DIM_ONE], (*outputSize)[DIM_TWO], dimD, dimH, dimW),
460- return false);
461- return true;
462-}
463- 
464-inline static void CalculateValuesSliceUpper(const aclTensor* self, int64_t& dim, int64_t& start, int64_t& end)
465-{
466- if (dim < 0) {
467- dim = dim + self->GetViewShape().GetDimNum();
468- }
469- if (start < 0) {
470- start = start + self->GetViewShape().GetDim(dim);
471- }
472- if (end < 0) {
473- end = end + self->GetViewShape().GetDim(dim);
474- }
475-}
476- 
477-inline static void CalculateValuesSliceLower(const aclTensor* self, int64_t& dim, int64_t& start, int64_t& end)
478-{
479- if (start < 0) {
480- start = 0;
481- } else if (start >= self->GetViewShape().GetDim(dim)) {
482- start = self->GetViewShape().GetDim(dim);
483- }
484- if (end < start) {
485- end = start;
486- } else if (end >= self->GetViewShape().GetDim(dim)) {
487- end = self->GetViewShape().GetDim(dim);
488- }
489-}
490- 
491-static inline bool CheckDimValueWithUnique(const aclTensor* self, int64_t dim)
492-{
493- int64_t dimSize = self->GetViewShape().GetDimNum();
494- int64_t dimMin = std::min(-1 * dimSize, dimSize - 1);
495- int64_t dimMax = std::max(-1 * dimSize, dimSize - 1);
496- if (dim > dimMax || dim < dimMin) {
497- OP_LOGE(ACLNN_ERR_PARAM_INVALID, "The param of dim must be in the range of [%ld, %ld], but got %ld.", dimMin,
498- dimMax, dim);
499- return false;
500- }
501- return true;
502-}
503- 
504-} // namespace op
505-#ifdef __cplusplus
506-}
507-#endif
508-#endif // LEVEL2_BASE_H_
@@ -8,255 +8,9 @@
8 * See LICENSE in the root of the software repository for the full text of the License.8 * See LICENSE in the root of the software repository for the full text of the License.
9 */9 */
10 10 
11-#ifndef LEVEL2_BASE_CALCULATION_H_11+#ifndef OPS_NN_LEGACY_LEVEL2_BASE_CACULATION_H_
12-#define LEVEL2_BASE_CALCULATION_H_12+#define OPS_NN_LEGACY_LEVEL2_BASE_CACULATION_H_
13 13 
14-#include <bitset>14+#include "op_api/level2_base_caculation_nn.h"
15-#include "op_api/op_api_def_nn.h"
16-#include "aclnn/aclnn_base.h"
17-#include "opdev/shape_utils.h"
18-#include "level0/fill.h"
19-#include "aclnn_kernels/reshape.h"
20-#include "aclnn_kernels/common/op_error_check.h"
21-#include "op_api/level2_base.h"
22 15 
23-#ifdef __cplusplus16+#endif // OPS_NN_LEGACY_LEVEL2_BASE_CACULATION_H_
24-extern "C" {
25-#endif
26- 
27-namespace op {
28-static inline bool CheckBroadcastLogAddExp(const aclTensor* self, const aclTensor* other, const aclTensor* out)
29-{
30- // 检查self和other是否能broadcast,如可以求broadcast之后的shape
31- OP_CHECK_BROADCAST(self, other, return false);
32- op::Shape broadcastShape;
33- BroadcastInferShape(self->GetViewShape(), other->GetViewShape(), broadcastShape);
34- 
35- // 检查self和other经过broadcast后的shape是否与out的shape一致
36- OP_CHECK_SHAPE_NOT_EQUAL_WITH_EXPECTED_SIZE(out, broadcastShape, return false);
37- return true;
38-}
39- 
40-// 检查传入的reduction数值是否在可选范围内
41-static inline FVector<int64_t> FillTensorGetTmpDim(const aclTensor* out)
42-{
43- FVector<int64_t> tmp;
44- if (out->GetViewShape().GetDimNum() != 0) {
45- size_t dimNum = out->GetViewShape().GetDimNum();
46- for (size_t idx = 0; idx < dimNum; idx++) {
47- int64_t tmpVal = out->GetViewShape().GetDim(idx);
48- tmp.push_back(tmpVal);
49- }
50- } else {
51- tmp.push_back(1);
52- }
53- return tmp;
54-}
55- 
56-static inline const aclTensor* FillTensorWithFalseValueWithInf(aclTensor* out, bool val, aclOpExecutor* executor)
57-{
58- FVector<int64_t> tmp = FillTensorGetTmpDim(out);
59- const aclTensor* dims = executor->ConvertToTensor(tmp.data(), tmp.size(), op::ToOpDataType(ACL_INT64));
60- aclIntArray* shapeArray = executor->AllocIntArray(tmp.data(), tmp.size());
61- FVector<bool> valVector = {val};
62- auto valTensor = executor->ConvertToTensor(valVector.data(), valVector.size(), out->GetDataType());
63- if (dims == nullptr || shapeArray == nullptr || valTensor == nullptr) {
64- return nullptr;
65- }
66- return l0op::Fill(dims, valTensor, shapeArray, executor);
67-}
68- 
69-static inline aclIntArray* GetTensorShapeActivation(const aclTensor* x, aclOpExecutor* executor)
70-{
71- auto shape = x->GetViewShape();
72- int64_t dimSize = x->GetViewShape().GetDimNum();
73- 
74- std::vector<int64_t> valuePerm(dimSize);
75- for (int i = 0; i < dimSize; i++) {
76- valuePerm[i] = shape[i];
77- }
78- auto perm = executor->AllocIntArray(valuePerm.data(), dimSize);
79- return perm;
80-}
81- 
82-static inline bool CheckSocVersionIsSupportBf16Activation(void)
83-{
84- return GetCurrentPlatformInfo().GetSocVersion() >= SocVersion::ASCEND910B &&
85- GetCurrentPlatformInfo().GetSocVersion() <= SocVersion::ASCEND910E;
86-}
87- 
88-static inline bool CheckDtypeValidActivation(const aclTensor* self, const aclTensor* out,
89- const std::initializer_list<op::DataType>& supportList)
90-{
91- OP_CHECK_DTYPE_NOT_SUPPORT(self, supportList, return false);
92- OP_CHECK_DTYPE_NOT_SUPPORT(out, supportList, return false);
93- OP_CHECK_DTYPE_NOT_MATCH(out, self->GetDataType(), return false);
94- bool bf16flag = CheckSocVersionIsSupportBf16Activation();
95- auto socVersion = GetCurrentPlatformInfo().GetSocVersion();
96- if (!bf16flag && self->GetDataType() == op::DataType::DT_BF16) {
97- OP_LOGE(ACLNN_ERR_PARAM_INVALID, "Self dtype %s is unsupported by the current SOC version [%s].",
98- op::ToString(self->GetDataType()).GetString(), op::ToString(socVersion).GetString());
99- return false;
100- }
101- return true;
102-}
103- 
104-static inline const aclTensor* ReshapeLongTensorActivation(const aclTensor* x, aclOpExecutor* executor,
105- int originalDimSize, aclIntArray* valuePerm = nullptr)
106-{
107- int64_t dimSize = x->GetViewShape().GetDimNum();
108- if (static_cast<int64_t>(originalDimSize) == dimSize && dimSize <= static_cast<int64_t>(MAX_SUPPORT_DIMS_NUMS)) {
109- return x;
110- }
111- 
112- auto reshapeSelf = l0op::Reshape(x, valuePerm, executor);
113- return reshapeSelf;
114-}
115- 
116-static inline const aclTensor* ReshapeSelfValueGetActivation(const aclTensor* self, size_t dimSize,
117- const aclTensor* selfContiguous,
118- UniqueExecutor& uniqueExecutor)
119-{
120- auto reshapeSelf = selfContiguous;
121- auto shapeOri = self->GetViewShape();
122- if (dimSize > MAX_SUPPORT_DIMS_NUMS) {
123- int64_t AllDimValue = 1;
124- for (size_t i = 0; i < dimSize; i++) {
125- AllDimValue *= shapeOri[i];
126- }
127- int64_t AllDim[1] = {AllDimValue};
128- auto shape1d = (uniqueExecutor)->AllocIntArray(AllDim, 1);
129- reshapeSelf = ReshapeLongTensorActivation(selfContiguous, uniqueExecutor.get(), dimSize, shape1d);
130- }
131- return reshapeSelf;
132-}
133- 
134-static inline FVector<int64_t> FillScalarGetShapeValue(const aclTensor* out)
135-{
136- FVector<int64_t> shape;
137- size_t dimNum = out->GetViewShape().GetDimNum();
138- for (size_t idx = 0; idx < dimNum; idx++) {
139- int64_t tmpVal = out->GetViewShape().GetDim(idx);
140- shape.push_back(tmpVal);
141- }
142- return shape;
143-}
144- 
145-static inline aclnnStatus CheckFillScalarShapeStdAndVar(aclTensor* out, float val, aclOpExecutor* executor)
146-{
147- FVector<int64_t> shape = FillScalarGetShapeValue(out);
148- auto dims = executor->ConvertToTensor(shape.data(), shape.size(), op::DataType::DT_INT64);
149- CHECK_RET(dims != nullptr, ACLNN_ERR_INNER_NULLPTR);
150- auto shapeArray = executor->AllocIntArray(shape.data(), shape.size());
151- CHECK_RET(shapeArray != nullptr, ACLNN_ERR_INNER_NULLPTR);
152- 
153- FVector<float> valVector = {val};
154- auto valTensor = executor->ConvertToTensor(valVector.data(), valVector.size(), out->GetDataType());
155- CHECK_RET(valTensor != nullptr, ACLNN_ERR_INNER_NULLPTR);
156- auto fillOut = l0op::Fill(dims, valTensor, shapeArray, executor);
157- CHECK_RET(fillOut != nullptr, ACLNN_ERR_INNER_NULLPTR);
158- auto viewCopyResult = l0op::ViewCopy(fillOut, out, executor);
159- CHECK_RET(viewCopyResult != nullptr, ACLNN_ERR_INNER_NULLPTR);
160- return ACLNN_SUCCESS;
161-}
162- 
163-static inline uint64_t GetPosDimWithStd(int64_t dim, int64_t selfdimNum)
164-{
165- if (selfdimNum <= 0) {
166- selfdimNum = 1;
167- }
168- return dim >= 0 ? dim : dim + selfdimNum;
169-}
170- 
171-static inline void ExpectShapeInferWithDimMask(const op::Shape& selfShape, const aclIntArray* dim, bool keepDim,
172- op::Shape& expectShape)
173-{
174- bitset<MAX_MASK_LEN64> dimMask = bitset<MAX_MASK_LEN64>();
175- 
176- // dim为空时,所有轴都视为mask,与竞品一致
177- if (dim->Size() == 0) {
178- dimMask.flip();
179- }
180- for (size_t i = 0; i < dim->Size(); i++) {
181- int64_t index = GetPosDimWithStd(dim->operator[](i), selfShape.GetDimNum());
182- // 前序已校验,此处dim不会重复
183- dimMask.set(index);
184- }
185- 
186- for (size_t i = 0; i < selfShape.GetDimNum(); i++) {
187- if (!dimMask[i]) {
188- expectShape.AppendDim(selfShape.GetDim(i));
189- } else if (keepDim) {
190- // dim为空时 所有轴reduce
191- expectShape.AppendDim(1);
192- }
193- }
194-}
195- 
196-static inline int64_t CalcShapeProdStdAndVarMean(const aclTensor* self, const aclIntArray* dim)
197-{
198- auto selfViewShape = self->GetViewShape();
199- int64_t shapeProd = 1;
200- if (selfViewShape.GetDimNum() != 0) {
201- // dim为all reduce
202- if (dim->Size() == 0) {
203- for (size_t i = 0; i < selfViewShape.GetDimNum(); i++) {
204- shapeProd *= selfViewShape.GetDim(i);
205- }
206- } else {
207- for (size_t i = 0; i < dim->Size(); i++) {
208- shapeProd *= selfViewShape.GetDim(dim->operator[](i));
209- }
210- }
211- }
212- return shapeProd;
213-}
214- 
215-static inline aclIntArray* CalcDimWithVar(const aclTensor* self, aclOpExecutor* executor)
216-{
217- FVector<int64_t> dimVector;
218- auto selfViewShape = self->GetViewShape();
219- size_t selfDimNum = selfViewShape.GetDimNum();
220- for (size_t i = 0; i < selfDimNum; i++) {
221- dimVector.push_back(static_cast<int64_t>(i));
222- }
223- return executor->AllocIntArray(dimVector.data(), dimVector.size());
224-}
225- 
226-static inline op::Shape ReduceShapeGetWithVar(const aclTensor* self, const aclIntArray* dim, bool keepdim)
227-{
228- auto selfShape = self->GetViewShape();
229- int64_t selfDimNum = selfShape.GetDimNum();
230- bool reduceArray[MAX_SUPPORT_DIMS_NUMS] = {false, false, false, false, false, false, false, false};
231- int64_t axis;
232- 
233- op::Shape reduceShape;
234- reduceShape.SetDimNum(0);
235- if (dim != nullptr && dim->Size() != 0) {
236- for (int64_t i = 0; i < static_cast<int64_t>(dim->Size()); i++) {
237- axis = dim->operator[](i);
238- if (axis < 0) {
239- axis = axis + selfDimNum;
240- }
241- reduceArray[axis] = true;
242- }
243- for (int64_t i = 0; i < selfDimNum; i++) {
244- if (!reduceArray[i]) {
245- reduceShape.AppendDim(selfShape.GetDim(i));
246- } else if (keepdim) {
247- reduceShape.AppendDim(1);
248- }
249- }
250- } else if (keepdim) {
251- for (int64_t i = 0; i < selfDimNum; i++) {
252- reduceShape.AppendDim(1);
253- }
254- }
255- return reduceShape;
256-}
257- 
258-} // namespace op
259-#ifdef __cplusplus
260-}
261-#endif
262-#endif // LEVEL2_BASE_CALCULATION_H_
@@ -0,0 +1,262 @@
1+/**
2+ * Copyright (c) 2025-2026 Huawei Technologies Co., Ltd.
3+ * This program is free software, you can redistribute it and/or modify it under the terms and conditions of
4+ * CANN Open Software License Agreement Version 2.0 (the "License").
5+ * Please refer to the License for details. You may not use this file except in compliance with the License.
6+ * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED,
7+ * INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE.
8+ * See LICENSE in the root of the software repository for the full text of the License.
9+ */
10+ 
11+#ifndef LEVEL2_BASE_CACULATION_NN_H_
12+#define LEVEL2_BASE_CACULATION_NN_H_
13+ 
14+#include <bitset>
15+#include "op_api/op_api_def_nn.h"
16+#include "aclnn/aclnn_base.h"
17+#include "opdev/shape_utils.h"
18+#include "level0/fill.h"
19+#include "aclnn_kernels/reshape.h"
20+#include "aclnn_kernels/common/op_error_check.h"
21+#include "op_api/level2_base_nn.h"
22+ 
23+#ifdef __cplusplus
24+extern "C" {
25+#endif
26+ 
27+namespace op {
28+static inline bool CheckBroadcastLogAddExp(const aclTensor* self, const aclTensor* other, const aclTensor* out)
29+{
30+ // 检查self和other是否能broadcast,如可以求broadcast之后的shape
31+ OP_CHECK_BROADCAST(self, other, return false);
32+ op::Shape broadcastShape;
33+ BroadcastInferShape(self->GetViewShape(), other->GetViewShape(), broadcastShape);
34+ 
35+ // 检查self和other经过broadcast后的shape是否与out的shape一致
36+ OP_CHECK_SHAPE_NOT_EQUAL_WITH_EXPECTED_SIZE(out, broadcastShape, return false);
37+ return true;
38+}
39+ 
40+// 检查传入的reduction数值是否在可选范围内
41+static inline FVector<int64_t> FillTensorGetTmpDim(const aclTensor* out)
42+{
43+ FVector<int64_t> tmp;
44+ if (out->GetViewShape().GetDimNum() != 0) {
45+ size_t dimNum = out->GetViewShape().GetDimNum();
46+ for (size_t idx = 0; idx < dimNum; idx++) {
47+ int64_t tmpVal = out->GetViewShape().GetDim(idx);
48+ tmp.push_back(tmpVal);
49+ }
50+ } else {
51+ tmp.push_back(1);
52+ }
53+ return tmp;
54+}
55+ 
56+static inline const aclTensor* FillTensorWithFalseValueWithInf(aclTensor* out, bool val, aclOpExecutor* executor)
57+{
58+ FVector<int64_t> tmp = FillTensorGetTmpDim(out);
59+ const aclTensor* dims = executor->ConvertToTensor(tmp.data(), tmp.size(), op::ToOpDataType(ACL_INT64));
60+ aclIntArray* shapeArray = executor->AllocIntArray(tmp.data(), tmp.size());
61+ FVector<bool> valVector = {val};
62+ auto valTensor = executor->ConvertToTensor(valVector.data(), valVector.size(), out->GetDataType());
63+ if (dims == nullptr || shapeArray == nullptr || valTensor == nullptr) {
64+ return nullptr;
65+ }
66+ return l0op::Fill(dims, valTensor, shapeArray, executor);
67+}
68+ 
69+static inline aclIntArray* GetTensorShapeActivation(const aclTensor* x, aclOpExecutor* executor)
70+{
71+ auto shape = x->GetViewShape();
72+ int64_t dimSize = x->GetViewShape().GetDimNum();
73+ 
74+ std::vector<int64_t> valuePerm(dimSize);
75+ for (int i = 0; i < dimSize; i++) {
76+ valuePerm[i] = shape[i];
77+ }
78+ auto perm = executor->AllocIntArray(valuePerm.data(), dimSize);
79+ return perm;
80+}
81+ 
82+static inline bool CheckSocVersionIsSupportBf16Activation(void)
83+{
84+ return GetCurrentPlatformInfo().GetSocVersion() >= SocVersion::ASCEND910B &&
85+ GetCurrentPlatformInfo().GetSocVersion() <= SocVersion::ASCEND910E;
86+}
87+ 
88+static inline bool CheckDtypeValidActivation(const aclTensor* self, const aclTensor* out,
89+ const std::initializer_list<op::DataType>& supportList)
90+{
91+ OP_CHECK_DTYPE_NOT_SUPPORT(self, supportList, return false);
92+ OP_CHECK_DTYPE_NOT_SUPPORT(out, supportList, return false);
93+ OP_CHECK_DTYPE_NOT_MATCH(out, self->GetDataType(), return false);
94+ bool bf16flag = CheckSocVersionIsSupportBf16Activation();
95+ auto socVersion = GetCurrentPlatformInfo().GetSocVersion();
96+ if (!bf16flag && self->GetDataType() == op::DataType::DT_BF16) {
97+ OP_LOGE(ACLNN_ERR_PARAM_INVALID, "Self dtype %s is unsupported by the current SOC version [%s].",
98+ op::ToString(self->GetDataType()).GetString(), op::ToString(socVersion).GetString());
99+ return false;
100+ }
101+ return true;
102+}
103+ 
104+static inline const aclTensor* ReshapeLongTensorActivation(const aclTensor* x, aclOpExecutor* executor,
105+ int originalDimSize, aclIntArray* valuePerm = nullptr)
106+{
107+ int64_t dimSize = x->GetViewShape().GetDimNum();
108+ if (static_cast<int64_t>(originalDimSize) == dimSize && dimSize <= static_cast<int64_t>(MAX_SUPPORT_DIMS_NUMS)) {
109+ return x;
110+ }
111+ 
112+ auto reshapeSelf = l0op::Reshape(x, valuePerm, executor);
113+ return reshapeSelf;
114+}
115+ 
116+static inline const aclTensor* ReshapeSelfValueGetActivation(const aclTensor* self, size_t dimSize,
117+ const aclTensor* selfContiguous,
118+ UniqueExecutor& uniqueExecutor)
119+{
120+ auto reshapeSelf = selfContiguous;
121+ auto shapeOri = self->GetViewShape();
122+ if (dimSize > MAX_SUPPORT_DIMS_NUMS) {
123+ int64_t AllDimValue = 1;
124+ for (size_t i = 0; i < dimSize; i++) {
125+ AllDimValue *= shapeOri[i];
126+ }
127+ int64_t AllDim[1] = {AllDimValue};
128+ auto shape1d = (uniqueExecutor)->AllocIntArray(AllDim, 1);
129+ reshapeSelf = ReshapeLongTensorActivation(selfContiguous, uniqueExecutor.get(), dimSize, shape1d);
130+ }
131+ return reshapeSelf;
132+}
133+ 
134+static inline FVector<int64_t> FillScalarGetShapeValue(const aclTensor* out)
135+{
136+ FVector<int64_t> shape;
137+ size_t dimNum = out->GetViewShape().GetDimNum();
138+ for (size_t idx = 0; idx < dimNum; idx++) {
139+ int64_t tmpVal = out->GetViewShape().GetDim(idx);
140+ shape.push_back(tmpVal);
141+ }
142+ return shape;
143+}
144+ 
145+static inline aclnnStatus CheckFillScalarShapeStdAndVar(aclTensor* out, float val, aclOpExecutor* executor)
146+{
147+ FVector<int64_t> shape = FillScalarGetShapeValue(out);
148+ auto dims = executor->ConvertToTensor(shape.data(), shape.size(), op::DataType::DT_INT64);
149+ CHECK_RET(dims != nullptr, ACLNN_ERR_INNER_NULLPTR);
150+ auto shapeArray = executor->AllocIntArray(shape.data(), shape.size());
151+ CHECK_RET(shapeArray != nullptr, ACLNN_ERR_INNER_NULLPTR);
152+ 
153+ FVector<float> valVector = {val};
154+ auto valTensor = executor->ConvertToTensor(valVector.data(), valVector.size(), out->GetDataType());
155+ CHECK_RET(valTensor != nullptr, ACLNN_ERR_INNER_NULLPTR);
156+ auto fillOut = l0op::Fill(dims, valTensor, shapeArray, executor);
157+ CHECK_RET(fillOut != nullptr, ACLNN_ERR_INNER_NULLPTR);
158+ auto viewCopyResult = l0op::ViewCopy(fillOut, out, executor);
159+ CHECK_RET(viewCopyResult != nullptr, ACLNN_ERR_INNER_NULLPTR);
160+ return ACLNN_SUCCESS;
161+}
162+ 
163+static inline uint64_t GetPosDimWithStd(int64_t dim, int64_t selfdimNum)
164+{
165+ if (selfdimNum <= 0) {
166+ selfdimNum = 1;
167+ }
168+ return dim >= 0 ? dim : dim + selfdimNum;
169+}
170+ 
171+static inline void ExpectShapeInferWithDimMask(const op::Shape& selfShape, const aclIntArray* dim, bool keepDim,
172+ op::Shape& expectShape)
173+{
174+ bitset<MAX_MASK_LEN64> dimMask = bitset<MAX_MASK_LEN64>();
175+ 
176+ // dim为空时,所有轴都视为mask,与竞品一致
177+ if (dim->Size() == 0) {
178+ dimMask.flip();
179+ }
180+ for (size_t i = 0; i < dim->Size(); i++) {
181+ int64_t index = GetPosDimWithStd(dim->operator[](i), selfShape.GetDimNum());
182+ // 前序已校验,此处dim不会重复
183+ dimMask.set(index);
184+ }
185+ 
186+ for (size_t i = 0; i < selfShape.GetDimNum(); i++) {
187+ if (!dimMask[i]) {
188+ expectShape.AppendDim(selfShape.GetDim(i));
189+ } else if (keepDim) {
190+ // dim为空时 所有轴reduce
191+ expectShape.AppendDim(1);
192+ }
193+ }
194+}
195+ 
196+static inline int64_t CalcShapeProdStdAndVarMean(const aclTensor* self, const aclIntArray* dim)
197+{
198+ auto selfViewShape = self->GetViewShape();
199+ int64_t shapeProd = 1;
200+ if (selfViewShape.GetDimNum() != 0) {
201+ // dim为all reduce
202+ if (dim->Size() == 0) {
203+ for (size_t i = 0; i < selfViewShape.GetDimNum(); i++) {
204+ shapeProd *= selfViewShape.GetDim(i);
205+ }
206+ } else {
207+ for (size_t i = 0; i < dim->Size(); i++) {
208+ shapeProd *= selfViewShape.GetDim(dim->operator[](i));
209+ }
210+ }
211+ }
212+ return shapeProd;
213+}
214+ 
215+static inline aclIntArray* CalcDimWithVar(const aclTensor* self, aclOpExecutor* executor)
216+{
217+ FVector<int64_t> dimVector;
218+ auto selfViewShape = self->GetViewShape();
219+ size_t selfDimNum = selfViewShape.GetDimNum();
220+ for (size_t i = 0; i < selfDimNum; i++) {
221+ dimVector.push_back(static_cast<int64_t>(i));
222+ }
223+ return executor->AllocIntArray(dimVector.data(), dimVector.size());
224+}
225+ 
226+static inline op::Shape ReduceShapeGetWithVar(const aclTensor* self, const aclIntArray* dim, bool keepdim)
227+{
228+ auto selfShape = self->GetViewShape();
229+ int64_t selfDimNum = selfShape.GetDimNum();
230+ bool reduceArray[MAX_SUPPORT_DIMS_NUMS] = {false, false, false, false, false, false, false, false};
231+ int64_t axis;
232+ 
233+ op::Shape reduceShape;
234+ reduceShape.SetDimNum(0);
235+ if (dim != nullptr && dim->Size() != 0) {
236+ for (int64_t i = 0; i < static_cast<int64_t>(dim->Size()); i++) {
237+ axis = dim->operator[](i);
238+ if (axis < 0) {
239+ axis = axis + selfDimNum;
240+ }
241+ reduceArray[axis] = true;
242+ }
243+ for (int64_t i = 0; i < selfDimNum; i++) {
244+ if (!reduceArray[i]) {
245+ reduceShape.AppendDim(selfShape.GetDim(i));
246+ } else if (keepdim) {
247+ reduceShape.AppendDim(1);
248+ }
249+ }
250+ } else if (keepdim) {
251+ for (int64_t i = 0; i < selfDimNum; i++) {
252+ reduceShape.AppendDim(1);
253+ }
254+ }
255+ return reduceShape;
256+}
257+ 
258+} // namespace op
259+#ifdef __cplusplus
260+}
261+#endif
262+#endif // LEVEL2_BASE_CACULATION_NN_H_
@@ -0,0 +1,508 @@
1+/**
2+ * Copyright (c) 2025-2026 Huawei Technologies Co., Ltd.
3+ * This program is free software, you can redistribute it and/or modify it under the terms and conditions of
4+ * CANN Open Software License Agreement Version 2.0 (the "License").
5+ * Please refer to the License for details. You may not use this file except in compliance with the License.
6+ * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED,
7+ * INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE.
8+ * See LICENSE in the root of the software repository for the full text of the License.
9+ */
10+ 
11+#ifndef LEVEL2_BASE_NN_H_
12+#define LEVEL2_BASE_NN_H_
13+ 
14+#include <algorithm>
15+#include "op_api/op_api_def_nn.h"
16+#include "op_api/aclnn_util.h"
17+#include "aclnn/aclnn_base.h"
18+#include "opdev/platform.h"
19+#include "opdev/common_types.h"
20+#include "opdev/fast_vector.h"
21+ 
22+#ifdef __cplusplus
23+extern "C" {
24+#endif
25+ 
26+namespace op {
27+ 
28+// 根据API定义,需要列出所能支持的所有dtype
29+static const std::initializer_list<op::DataType> DTYPE_SUPPORT_LISTS = {
30+ op::DataType::DT_FLOAT, op::DataType::DT_FLOAT16, op::DataType::DT_DOUBLE, op::DataType::DT_BF16};
31+static const int64_t UPSAMPLE_EXPECT_SIZE = 3;
32+static const int64_t UPSAMPLE_DIM_LIMIT = 5;
33+static constexpr size_t DIM_ZERO = 0;
34+static constexpr size_t DIM_ONE = 1;
35+static constexpr size_t DIM_TWO = 2;
36+static constexpr size_t DIM_THREE = 3;
37+static constexpr size_t DIM_FOUR = 4;
38+ 
39+// 检查1个输入和1个输出是否是空指针
40+inline static bool CheckNotNull2Tensor(const aclTensor* t0, const aclTensor* t1)
41+{
42+ OP_CHECK_NULL(t0, return false);
43+ OP_CHECK_NULL(t1, return false);
44+ 
45+ return true;
46+}
47+inline static bool CheckNotNull3Tensor(const aclTensor* t0, const aclTensor* t1, const aclTensor* t2)
48+{
49+ // 检查输入是否是空指针
50+ OP_CHECK_NULL(t0, return false);
51+ OP_CHECK_NULL(t1, return false);
52+ // 检查输入是否是空指针
53+ OP_CHECK_NULL(t2, return false);
54+ 
55+ return true;
56+}
57+// 检查3个输入和1个输出是否是空指针
58+inline static bool CheckNotNull4Tensor(const aclTensor* t0, const aclTensor* t1, const aclTensor* t2,
59+ const aclTensor* t3)
60+{
61+ // 检查输入是否是空指针
62+ OP_CHECK_NULL(t0, return false);
63+ OP_CHECK_NULL(t1, return false);
64+ OP_CHECK_NULL(t2, return false);
65+ // 检查输入是否是空指针
66+ OP_CHECK_NULL(t3, return false);
67+ 
68+ return true;
69+}
70+ 
71+inline static bool CheckNotNull2In1Out(const aclTensor* gradOutput, const aclTensor* input, const aclTensor* grid,
72+ const aclTensor* inputGrad, const aclTensor* gridGrad)
73+{
74+ OP_CHECK_NULL(gradOutput, return false);
75+ OP_CHECK_NULL(input, return false);
76+ OP_CHECK_NULL(grid, return false);
77+ OP_CHECK_NULL(inputGrad, return false);
78+ OP_CHECK_NULL(gridGrad, return false);
79+ return true;
80+}
81+ 
82+inline static bool CheckNotNull2In2Out(const aclTensor* gradOut, const aclIntArray* outputSize,
83+ const aclIntArray* inputSize, const aclTensor* gradInput)
84+{
85+ OP_CHECK_NULL(gradOut, return false);
86+ OP_CHECK_NULL(outputSize, return false);
87+ OP_CHECK_NULL(inputSize, return false);
88+ OP_CHECK_NULL(gradInput, return false);
89+ return true;
90+}
91+ 
92+/**
93+ * 1. 1个输入1个输出
94+ * 2. 输入输出的shape必须一致
95+ * 3. 输入的维度必须小于等于8
96+ */
97+inline static bool CheckSameShape1In1Out(const aclTensor* self, const aclTensor* out)
98+{
99+ // self和out的shape必须一致
100+ OP_CHECK_SHAPE_NOT_EQUAL(self, out, return false);
101+ // self的维度必须小于等于8
102+ OP_CHECK_MAX_DIM(self, MAX_SUPPORT_DIMS_NUMS, return false);
103+ 
104+ return true;
105+}
106+ 
107+inline static bool CheckShapeCumMinMax(const aclTensor* self, const aclTensor* valuesOut, const aclTensor* indicesOut)
108+{
109+ // 所有输入的维度都不能超过8
110+ OP_CHECK_MAX_DIM(self, MAX_SUPPORT_DIMS_NUMS, return false);
111+ 
112+ // self和valuesOut、indicesOut的shape必须一致
113+ OP_CHECK_SHAPE_NOT_EQUAL(self, valuesOut, return false);
114+ OP_CHECK_SHAPE_NOT_EQUAL(self, indicesOut, return false);
115+ return true;
116+}
117+ 
118+inline static bool CheckSameShapeNotlimit1In1Out(const aclTensor* self, const aclTensor* out)
119+{
120+ // self和out的shape必须一致
121+ OP_CHECK_SHAPE_NOT_EQUAL(self, out, return false);
122+ return true;
123+}
124+ 
125+inline static bool CheckShapeNotlimitDim1In1Out(const aclTensor* self)
126+{
127+ OP_CHECK_MAX_DIM(self, MAX_SUPPORT_DIMS_NUMS, return false);
128+ return true;
129+}
130+ 
131+// 检查1个输入和1个输出的数据类型是否在算子的支持列表内
132+static inline bool CheckDtypeValid1In1Out(const aclTensor* self, const aclTensor* out,
133+ const std::initializer_list<op::DataType>& dtypeSupportList,
134+ const std::initializer_list<op::DataType>& dtypeOutList)
135+{
136+ OP_CHECK_DTYPE_NOT_SUPPORT(self, dtypeSupportList, return false);
137+ // 检查输出的数据类型是否在算子的支持列表内
138+ OP_CHECK_DTYPE_NOT_SUPPORT(out, dtypeOutList, return false);
139+ 
140+ return true;
141+}
142+ 
143+// 检查1个输入和1个输出的数据类型是否在算子的支持列表内
144+static inline bool CheckDtypeValid1In1OutScalar(const aclTensor* self, const aclScalar* attrScalar,
145+ const aclTensor* out,
146+ const std::initializer_list<op::DataType>& dtypeSupportList,
147+ const std::initializer_list<op::DataType>& attrScalarSupportList,
148+ const std::initializer_list<op::DataType>& dtypeOutList)
149+{
150+ // 检查self的数据类型是否在支持列表内
151+ OP_CHECK_DTYPE_NOT_SUPPORT(self, dtypeSupportList, return false);
152+ // 检查attr的数据类型是否在支持列表内
153+ OP_CHECK_DTYPE_NOT_SUPPORT(attrScalar, attrScalarSupportList, return false);
154+ // 检查out的数据类型是否在支持列表内
155+ OP_CHECK_DTYPE_NOT_SUPPORT(out, dtypeOutList, return false);
156+ 
157+ // 检查self和out的数据类型是否一致
158+ OP_CHECK_DTYPE_NOT_SAME(self, out, return false);
159+ 
160+ return true;
161+}
162+ 
163+// 检查1个输入和1个输出的数据类型是否在算子的支持列表内
164+static inline bool CheckDtypeValid1In1OutTensor(const aclTensor* self, const aclTensor* attrTensor,
165+ const aclTensor* out,
166+ const std::initializer_list<op::DataType>& dtypeSupportList,
167+ const std::initializer_list<op::DataType>& attrTensorSupportList,
168+ const std::initializer_list<op::DataType>& dtypeOutList)
169+{
170+ // 检查self的数据类型是否在支持列表内
171+ OP_CHECK_DTYPE_NOT_SUPPORT(self, dtypeSupportList, return false);
172+ // 检查attr的数据类型是否在支持列表内
173+ OP_CHECK_DTYPE_NOT_SUPPORT(attrTensor, attrTensorSupportList, return false);
174+ // 检查out的数据类型是否在支持列表内
175+ OP_CHECK_DTYPE_NOT_SUPPORT(out, dtypeOutList, return false);
176+ 
177+ // 检查self和out的数据类型是否一致
178+ OP_CHECK_DTYPE_NOT_SAME(self, out, return false);
179+ 
180+ return true;
181+}
182+ 
183+static inline bool CheckDtypeValid1In1OutMatch(const aclTensor* self, const aclTensor* valueOut,
184+ const aclTensor* inverseOut, const aclTensor* countsOut,
185+ const std::initializer_list<op::DataType>& dtypeSupportList)
186+{
187+ // 检查self的数据类型是否在UniqueConsecutive算子的支持列表内
188+ OP_CHECK_DTYPE_NOT_SUPPORT(self, dtypeSupportList, return false);
189+ 
190+ // 检查inverseOut数据类型
191+ OP_CHECK_DTYPE_NOT_MATCH(inverseOut, op::DataType::DT_INT64, return false);
192+ 
193+ // 检查countsOut数据类型
194+ OP_CHECK_DTYPE_NOT_MATCH(countsOut, op::DataType::DT_INT64, return false);
195+ 
196+ // 检查self与valueOut数据类型一致
197+ OP_CHECK_DTYPE_NOT_MATCH(valueOut, self->GetDataType(), return false);
198+ 
199+ // 检查inverseOut与countsOut数据类型一致
200+ OP_CHECK_DTYPE_NOT_MATCH(inverseOut, countsOut->GetDataType(), return false);
201+ return true;
202+}
203+ 
204+/**
205+ * l1: DAV_2201 芯片,该算子支持的数据类型列表
206+ * l2: 其他芯片,该算子支持的数据类型列表
207+ */
208+inline static const std::initializer_list<DataType>& GetDtypeSupportListV1(
209+ const std::initializer_list<op::DataType>& l1, const std::initializer_list<op::DataType>& l2)
210+{
211+ if (GetCurrentPlatformInfo().GetCurNpuArch() == NpuArch::DAV_2201) {
212+ return l1;
213+ } else {
214+ return l2;
215+ }
216+}
217+ 
218+/**
219+ * l1: DAV_2201 和 DAV_3510芯片,该算子支持的数据类型列表
220+ * l2: 其他芯片,该算子支持的数据类型列表
221+ */
222+inline static const std::initializer_list<DataType>& GetDtypeSupportListV2(
223+ const std::initializer_list<op::DataType>& l1, const std::initializer_list<op::DataType>& l2)
224+{
225+ if (GetCurrentPlatformInfo().GetCurNpuArch() == NpuArch::DAV_2201 || Ops::NN::AclnnUtil::IsRegbase()) {
226+ return l1;
227+ } else {
228+ return l2;
229+ }
230+}
231+ 
232+inline static const std::initializer_list<op::DataType> GetDtypeSupportListV3(
233+ const std::initializer_list<op::DataType>& l1, const std::initializer_list<op::DataType>& l2)
234+{
235+ auto npuArch = GetCurrentPlatformInfo().GetCurNpuArch();
236+ switch (npuArch) {
237+ case NpuArch::DAV_3510:
238+ case NpuArch::DAV_2201: {
239+ return l1;
240+ }
241+ case NpuArch::DAV_1001: {
242+ return l2;
243+ }
244+ default: {
245+ // 如果既不是1971也不是1980,先暂且默认当做1971处理
246+ return l1;
247+ }
248+ }
249+}
250+ 
251+static inline aclnnStatus CheckArrayDataAvgPoolBackWard(const aclIntArray* kernelSize, const aclIntArray* stride,
252+ const aclIntArray* padding)
253+{
254+ for (uint64_t i = 0; i < kernelSize->Size(); i++) {
255+ auto size = (*kernelSize)[i];
256+ if (size <= 0) {
257+ OP_LOGE(ACLNN_ERR_PARAM_INVALID, "kernelSize [%lu] data [%li] is less than or equal to 0", i, size);
258+ return ACLNN_ERR_PARAM_INVALID;
259+ }
260+ }
261+ 
262+ for (uint64_t i = 0; i < stride->Size(); i++) {
263+ auto size = (*stride)[i];
264+ if (size <= 0) {
265+ OP_LOGE(ACLNN_ERR_PARAM_INVALID, "stride [%lu] data [%li] is less than or equal to 0", i, size);
266+ return ACLNN_ERR_PARAM_INVALID;
267+ }
268+ }
269+ 
270+ if (kernelSize->Size() != padding->Size()) {
271+ return ACLNN_ERR_PARAM_INVALID;
272+ }
273+ 
274+ for (uint64_t i = 0; i < kernelSize->Size(); i++) {
275+ auto halfKsize = (*kernelSize)[i] / 2;
276+ auto padSize = (*padding)[i];
277+ if (halfKsize < padSize) {
278+ OP_LOGE(ACLNN_ERR_PARAM_INVALID, "padding [%lu] data [%li] should less than kernelSize / 2 [%ld]", i,
279+ padSize, halfKsize);
280+ return ACLNN_ERR_PARAM_INVALID;
281+ }
282+ if (padSize < 0) {
283+ OP_LOGE(ACLNN_ERR_PARAM_INVALID, "padding [%lu] data [%li] is less than 0", i, padSize);
284+ return ACLNN_ERR_PARAM_INVALID;
285+ }
286+ }
287+ return ACLNN_SUCCESS;
288+}
289+ 
290+inline static bool CheckPaddingValidAvgPool2D(const aclIntArray* kernelSize, const aclIntArray* padding)
291+{
292+ const int64_t kKernelSizeHIdx = 0;
293+ const int64_t kKernelSizeWIdx = 1;
294+ const int64_t kPaddingUpIdx = 0;
295+ const int64_t kPaddingLeftIdx = 1;
296+ const int64_t kernelH = (*kernelSize)[kKernelSizeHIdx];
297+ const int64_t kernelPaddingSize = 1;
298+ const int64_t MULTIPLIER = 2;
299+ // 1表示kernelSize长度为1
300+ const int64_t kernelW = kernelSize->Size() == kernelPaddingSize ? (*kernelSize)[kKernelSizeHIdx] :
301+ (*kernelSize)[kKernelSizeWIdx];
302+ OP_CHECK(padding->Size() != 0, OP_LOGE(ACLNN_ERR_PARAM_INVALID, "padding is empty"), return false);
303+ const int64_t paddingH = (*padding)[kPaddingUpIdx];
304+ const int64_t paddingW = padding->Size() == kernelPaddingSize ? (*padding)[kPaddingUpIdx] :
305+ (*padding)[kPaddingLeftIdx];
306+ // MULTIPLIER 表示paddingH不能大于kernelH的一半,下同
307+ if (kernelH < MULTIPLIER * paddingH) {
308+ OP_LOGE(ACLNN_ERR_PARAM_INVALID,
309+ "value of paddingH should be at most half of kernelH. Actual: paddingH is [%ld],kernelH is [%ld].",
310+ paddingH, kernelH);
311+ return false;
312+ }
313+ if (kernelW < MULTIPLIER * paddingW) {
314+ OP_LOGE(ACLNN_ERR_PARAM_INVALID,
315+ "value of paddingW should be at most half of kernelW. Actual: paddingW is [%ld],"
316+ "kernelW is [%ld].",
317+ paddingW, kernelW);
318+ return false;
319+ }
320+ return true;
321+}
322+ 
323+static inline bool CheckDtypeValid1Out1In(const aclTensor* gradOut, const aclTensor* gradInput)
324+{
325+ // 检查gradOut的数据类型是否在ResizeNearestNeighborV2Grad算子的支持列表内
326+ OP_CHECK_DTYPE_NOT_SUPPORT(gradOut, DTYPE_SUPPORT_LISTS, return false);
327+ // 检查gradInput的数据类型是否与gradOut一致
328+ OP_CHECK_DTYPE_NOT_MATCH(gradOut, gradInput->GetDataType(), return false);
329+ return true;
330+}
331+ 
332+inline static bool CheckUpsampleShape(const aclTensor* gradOut, const aclIntArray* outputSize,
333+ const aclIntArray* inputSize)
334+{
335+ size_t outputSizeNum = outputSize->Size();
336+ size_t inputSizeNum = inputSize->Size();
337+ OP_CHECK_WRONG_DIMENSION(gradOut, UPSAMPLE_DIM_LIMIT, return false);
338+ OP_CHECK(
339+ outputSizeNum == UPSAMPLE_EXPECT_SIZE,
340+ OP_LOGE(ACLNN_ERR_PARAM_INVALID, "It is expected output_size equals to 3, but got size %zu", outputSizeNum),
341+ return false);
342+ 
343+ OP_CHECK(inputSizeNum == UPSAMPLE_DIM_LIMIT,
344+ OP_LOGE(ACLNN_ERR_PARAM_INVALID, "It is expected input_size equals to 5, but got size %zu", inputSizeNum),
345+ return false);
346+ return true;
347+}
348+ 
349+static inline bool CheckPromoteTypeGeluBackward(const aclTensor* gradOutput, const aclTensor* self,
350+ op::DataType& promoteType,
351+ const std::initializer_list<DataType> dtypeSupportList)
352+{
353+ // 检查self和gradOutput能否做数据类型推导
354+ promoteType = op::PromoteType(gradOutput->GetDataType(), self->GetDataType());
355+ if (promoteType == DataType::DT_UNDEFINED) {
356+ OP_LOGE(ACLNN_ERR_PARAM_INVALID, "GradOutput dtype %s and Self dtype %s can not be promoted.",
357+ op::ToString(gradOutput->GetDataType()).GetString(), op::ToString(self->GetDataType()).GetString());
358+ return false;
359+ }
360+ 
361+ if (!(GetCurrentPlatformInfo().GetCurNpuArch() == NpuArch::DAV_2201 || Ops::NN::AclnnUtil::IsRegbase()) &&
362+ (promoteType == op::DataType::DT_BF16)) {
363+ OP_LOGE(ACLNN_ERR_PARAM_INVALID, "Input dtype of gelu is not support bfloat16 in current socversion.");
364+ return false;
365+ }
366+ 
367+ // 检查promoteType的数据类型是否在支持列表内
368+ if (!CheckType(promoteType, dtypeSupportList)) {
369+ OP_LOGE(ACLNN_ERR_PARAM_INVALID, "promoteType dtype %s should be in dtype support list %s.",
370+ op::ToString(promoteType).GetString(), op::ToString(dtypeSupportList).GetString());
371+ return false;
372+ }
373+ return true;
374+}
375+ 
376+// 循环判断size是否相等
377+inline static bool CheckSizeLoop(size_t dimNum, Shape gradOutShape, FVector<int64_t>& fullOutputSize)
378+{
379+ for (size_t i = 0; i < dimNum; ++i) {
380+ if (gradOutShape.GetDim(i) != fullOutputSize[i]) {
381+ OP_LOGE(ACLNN_ERR_PARAM_INVALID,
382+ "Expected grad_output to have the same shape as output;"
383+ " output.size(%zu) = %ld but got grad_output.size(%zu) = %ld",
384+ i, fullOutputSize[i], i, gradOutShape.GetDim(i));
385+ return false;
386+ }
387+ }
388+ return true;
389+}
390+ 
391+static inline bool CheckInputNullTensorMaxUnPool3D(const aclTensor* self)
392+{
393+ auto inputShape = self->GetViewShape();
394+ size_t dimNum = inputShape.GetDimNum();
395+ 
396+ for (size_t i = 1; i < dimNum; ++i) {
397+ if (inputShape.GetDim(i) <= 0) {
398+ OP_LOGE(ACLNN_ERR_PARAM_INVALID,
399+ "max_unpool3d(): Expected input to have non-zero size for non-batch dimensions, "
400+ "but got %zu with dimension %zu being empty.",
401+ dimNum, i);
402+ return false;
403+ }
404+ }
405+ return true;
406+}
407+ 
408+static inline bool CheckIntArrayShapeMaxUnPool3D(const aclTensor* self, const aclIntArray* outputSize,
409+ const aclIntArray* stride, const aclIntArray* padding)
410+{
411+ constexpr size_t NCDHW_DIM_NUM = 5;
412+ constexpr int64_t EXPECT_SIZE = 3;
413+ 
414+ OP_CHECK(outputSize->Size() == EXPECT_SIZE,
415+ OP_LOGE(ACLNN_ERR_PARAM_INVALID,
416+ "There should be exactly three elements (depth, height, width) in "
417+ "output_size, but got %zu elements",
418+ outputSize->Size()),
419+ return false);
420+ OP_CHECK(stride->Size() == EXPECT_SIZE,
421+ OP_LOGE(ACLNN_ERR_PARAM_INVALID,
422+ "There should be exactly three elements (depth, height, width) in "
423+ "stride, but got %zu elements",
424+ stride->Size()),
425+ return false);
426+ OP_CHECK(padding->Size() == EXPECT_SIZE,
427+ OP_LOGE(ACLNN_ERR_PARAM_INVALID,
428+ "There should be exactly three elements (depth, height, width) in "
429+ "padding, but got %zu elements",
430+ padding->Size()),
431+ return false);
432+ 
433+ for (size_t i = 0; i < EXPECT_SIZE; ++i) {
434+ if ((*stride)[i] <= 0) {
435+ OP_LOGE(ACLNN_ERR_PARAM_INVALID, "strides[%zu] shoule be greater than zero, but got %ld.", i, (*stride)[i]);
436+ return false;
437+ }
438+ if ((*outputSize)[i] <= 0) {
439+ OP_LOGE(ACLNN_ERR_PARAM_INVALID, "outputSize[%zu] should be greater than zero, but got %ld.", i,
440+ (*outputSize)[i]);
441+ return false;
442+ }
443+ }
444+ 
445+ int64_t dimD = self->GetViewShape().GetDim(DIM_ONE);
446+ int64_t dimH = self->GetViewShape().GetDim(DIM_TWO);
447+ int64_t dimW = self->GetViewShape().GetDim(DIM_THREE);
448+ 
449+ if (self->GetViewShape().GetDimNum() == NCDHW_DIM_NUM) {
450+ dimD = self->GetViewShape().GetDim(DIM_TWO);
451+ dimH = self->GetViewShape().GetDim(DIM_THREE);
452+ dimW = self->GetViewShape().GetDim(DIM_FOUR);
453+ }
454+ 
455+ OP_CHECK(((*outputSize)[DIM_ZERO] * (*outputSize)[DIM_ONE] * (*outputSize)[DIM_TWO]) >= (dimD * dimH * dimW),
456+ OP_LOGE(ACLNN_ERR_PARAM_INVALID,
457+ "The output dimensions are of size %ld x %ld x %ld, "
458+ "should be greater than or equal to self of size %ld x %ld x %ld.",
459+ (*outputSize)[DIM_ZERO], (*outputSize)[DIM_ONE], (*outputSize)[DIM_TWO], dimD, dimH, dimW),
460+ return false);
461+ return true;
462+}
463+ 
464+inline static void CalculateValuesSliceUpper(const aclTensor* self, int64_t& dim, int64_t& start, int64_t& end)
465+{
466+ if (dim < 0) {
467+ dim = dim + self->GetViewShape().GetDimNum();
468+ }
469+ if (start < 0) {
470+ start = start + self->GetViewShape().GetDim(dim);
471+ }
472+ if (end < 0) {
473+ end = end + self->GetViewShape().GetDim(dim);
474+ }
475+}
476+ 
477+inline static void CalculateValuesSliceLower(const aclTensor* self, int64_t& dim, int64_t& start, int64_t& end)
478+{
479+ if (start < 0) {
480+ start = 0;
481+ } else if (start >= self->GetViewShape().GetDim(dim)) {
482+ start = self->GetViewShape().GetDim(dim);
483+ }
484+ if (end < start) {
485+ end = start;
486+ } else if (end >= self->GetViewShape().GetDim(dim)) {
487+ end = self->GetViewShape().GetDim(dim);
488+ }
489+}
490+ 
491+static inline bool CheckDimValueWithUnique(const aclTensor* self, int64_t dim)
492+{
493+ int64_t dimSize = self->GetViewShape().GetDimNum();
494+ int64_t dimMin = std::min(-1 * dimSize, dimSize - 1);
495+ int64_t dimMax = std::max(-1 * dimSize, dimSize - 1);
496+ if (dim > dimMax || dim < dimMin) {
497+ OP_LOGE(ACLNN_ERR_PARAM_INVALID, "The param of dim must be in the range of [%ld, %ld], but got %ld.", dimMin,
498+ dimMax, dim);
499+ return false;
500+ }
501+ return true;
502+}
503+ 
504+} // namespace op
505+#ifdef __cplusplus
506+}
507+#endif
508+#endif // LEVEL2_BASE_NN_H_
@@ -26,7 +26,7 @@
26#include "opdev/op_log.h"26#include "opdev/op_log.h"
27#include "opdev/tensor_view_utils.h"27#include "opdev/tensor_view_utils.h"
28#include "opdev/make_op_executor.h"28#include "opdev/make_op_executor.h"
29-#include "op_api/level2_base.h"29+#include "op_api/level2_base_nn.h"
30 30 
31using namespace op;31using namespace op;
32#ifdef __cplusplus32#ifdef __cplusplus