已合并
[feat] Add operator scale_and_translate #693
FengHaozhan创建于 4月9日
[feat] Add operator scale_and_translate #693
已合并
FengHaozhan创建于 4月9日
17 个文件变更+2611-0
@@ -395,6 +395,7 @@ function(gen_aicpu_kernel_symbol enable_built_in)
395 -o ${ARM_SO_OUTPUT}395 -o ${ARM_SO_OUTPUT}
396 DEPENDS ${AICPU_CUST_OBJ_TARGETS}396 DEPENDS ${AICPU_CUST_OBJ_TARGETS}
397 COMMENT "Linking aicpu_kernels.so using ARM toolchain"397 COMMENT "Linking aicpu_kernels.so using ARM toolchain"
398+ COMMAND_EXPAND_LISTS
398 )399 )
399 400 
400 add_custom_target(aicpu_kernels ALL DEPENDS ${ARM_SO_OUTPUT})401 add_custom_target(aicpu_kernels ALL DEPENDS ${ARM_SO_OUTPUT})
@@ -0,0 +1,27 @@
1+# ---------------------------------------------------------------------------------------------------------
2+# Copyright (c) 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+set(ASCEND_OP_NAME "" CACHE STRING "Ascend op names to compile")
11+set(OP_TYPE "scale_and_translate")
12+ 
13+skip_aicpu_kernel("${OP_TYPE}" "${ASCEND_OP_NAME}")
14+ 
15+if(SKIP_FLAG)
16+ return()
17+endif()
18+ 
19+file(GLOB CURRENT_DIRS RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/*)
20+list(REMOVE_ITEM CURRENT_DIRS tests)
21+foreach(SUB_DIR ${CURRENT_DIRS})
22+ if(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/${SUB_DIR}/CMakeLists.txt")
23+ add_subdirectory(${SUB_DIR})
24+ endif()
25+endforeach()
26+ 
27+add_all_modules_sources(OPTYPE scale_and_translate ACLNNTYPE aclnn_exclude)
@@ -0,0 +1,307 @@
1+/**
2+ * Copyright (c) 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+#include <iostream>
12+#include <fstream>
13+#include <string.h>
14+#include <stdint.h>
15+#include <vector>
16+#include <string>
17+#include <map>
18+#include "assert.h"
19+ 
20+#include "graph.h"
21+#include "types.h"
22+#include "tensor.h"
23+#include "ge_error_codes.h"
24+#include "ge_api_types.h"
25+#include "ge_api.h"
26+#include "array_ops.h"
27+#include "ge_ir_build.h"
28+ 
29+#include "../op_graph/scale_and_translate_proto.h"
30+ 
31+#define FAILED -1
32+#define SUCCESS 0
33+ 
34+using namespace ge;
35+using std::map;
36+using std::string;
37+using std::vector;
38+#define ADD_INPUT(inputIndex, inputName, inputDtype, inputShape, value) \
39+ vector<int64_t> placeholder##inputIndex##_shape = inputShape; \
40+ auto placeholder##inputIndex = op::Data("placeholder" + inputIndex).set_attr_index(0); \
41+ TensorDesc placeholder##inputIndex##_desc = \
42+ TensorDesc(ge::Shape(placeholder##inputIndex##_shape), FORMAT_NHWC, inputDtype); \
43+ placeholder##inputIndex##_desc.SetPlacement(ge::kPlacementHost); \
44+ placeholder##inputIndex##_desc.SetFormat(FORMAT_NHWC); \
45+ Tensor tensor_placeholder##inputIndex; \
46+ ret = GenOnesDataFloat32( \
47+ placeholder##inputIndex##_shape, tensor_placeholder##inputIndex, placeholder##inputIndex##_desc, value); \
48+ if (ret != SUCCESS) { \
49+ printf("%s - ERROR - [XIR]: Generate input data failed\n", GetTime().c_str()); \
50+ return FAILED; \
51+ } \
52+ input.push_back(tensor_placeholder##inputIndex); \
53+ graph.AddOp(placeholder##inputIndex); \
54+ add1.set_input_##inputName(placeholder##inputIndex); \
55+ add1.update_input_desc_##inputName(placeholder##inputIndex##_desc); \
56+ inputs.push_back(placeholder##inputIndex);
57+ 
58+#define ADD_INPUT_INT(inputIndex, inputName, inputDtype, inputShape) \
59+ vector<int64_t> placeholder##inputIndex##_shape = inputShape; \
60+ auto placeholder##inputIndex = op::Data("placeholder" + inputIndex).set_attr_index(0); \
61+ TensorDesc placeholder##inputIndex##_desc = \
62+ TensorDesc(ge::Shape(placeholder##inputIndex##_shape), FORMAT_NHWC, inputDtype); \
63+ placeholder##inputIndex##_desc.SetPlacement(ge::kPlacementHost); \
64+ placeholder##inputIndex##_desc.SetFormat(FORMAT_NHWC); \
65+ Tensor tensor_placeholder##inputIndex; \
66+ ret = GenOnesData(placeholder##inputIndex##_shape, \
67+ tensor_placeholder##inputIndex, \
68+ placeholder##inputIndex##_desc, \
69+ inputDtype, \
70+ 1); \
71+ if (ret != SUCCESS) { \
72+ printf("%s - ERROR - [XIR]: Generate input data failed\n", GetTime().c_str()); \
73+ return FAILED; \
74+ } \
75+ input.push_back(tensor_placeholder##inputIndex); \
76+ graph.AddOp(placeholder##inputIndex); \
77+ add1.set_input_##inputName(placeholder##inputIndex); \
78+ add1.update_input_desc_##inputName(placeholder##inputIndex##_desc); \
79+ inputs.push_back(placeholder##inputIndex);
80+ 
81+#define ADD_OUTPUT(outputIndex, outputName, outputDtype, outputShape) \
82+ TensorDesc outputName##outputIndex##_desc = TensorDesc(ge::Shape(outputShape), FORMAT_NHWC, outputDtype); \
83+ add1.update_output_desc_##outputName(outputName##outputIndex##_desc);
84+ 
85+#define LOG_PRINT(message, ...) \
86+ do { \
87+ printf(message, ##__VA_ARGS__); \
88+ } while (0)
89+ 
90+string GetTime()
91+{
92+ time_t timep;
93+ time(&timep);
94+ char tmp[64];
95+ strftime(tmp, sizeof(tmp), "%Y-%m-%d %H:%M:%S,000", localtime(&timep));
96+ return tmp;
97+}
98+ 
99+uint32_t GetDataTypeSize(DataType dt)
100+{
101+ uint32_t dilation = 1;
102+ uint32_t oneByte = 1;
103+ uint32_t twoByte = 2;
104+ uint32_t fourByte = 4;
105+ uint32_t eightByte = 8;
106+ 
107+ if (dt == ge::DT_FLOAT) {
108+ dilation = fourByte;
109+ } else if (dt == ge::DT_FLOAT16) {
110+ dilation = twoByte;
111+ } else if (dt == ge::DT_BF16) {
112+ dilation = twoByte;
113+ } else if (dt == ge::DT_INT16) {
114+ dilation = twoByte;
115+ } else if (dt == ge::DT_UINT16) {
116+ dilation = twoByte;
117+ } else if (dt == ge::DT_INT32) {
118+ dilation = fourByte;
119+ } else if (dt == ge::DT_UINT32) {
120+ dilation = fourByte;
121+ } else if (dt == ge::DT_INT64) {
122+ dilation = eightByte;
123+ } else if (dt == ge::DT_UINT64) {
124+ dilation = eightByte;
125+ } else if (dt == ge::DT_INT8) {
126+ dilation = oneByte;
127+ }
128+ return dilation;
129+}
130+ 
131+int32_t GenOnesDataFloat32(vector<int64_t> shapes, Tensor &input_tensor, TensorDesc &input_tensor_desc, float value)
132+{
133+ input_tensor_desc.SetRealDimCnt(shapes.size());
134+ size_t size = 1;
135+ for (uint32_t i = 0; i < shapes.size(); i++) {
136+ size *= shapes[i];
137+ }
138+ uint32_t byteSizeFloat32 = 4;
139+ uint32_t data_len = size * byteSizeFloat32;
140+ float *pData = new (std::nothrow) float[size];
141+ 
142+ for (size_t i = 0; i < size; ++i) {
143+ *(pData + i) = value;
144+ }
145+ input_tensor = Tensor(input_tensor_desc, (uint8_t *)pData, data_len);
146+ return SUCCESS;
147+}
148+ 
149+int32_t GenOnesData(
150+ vector<int64_t> shapes, Tensor &input_tensor, TensorDesc &input_tensor_desc, DataType data_type, int value)
151+{
152+ input_tensor_desc.SetRealDimCnt(shapes.size());
153+ size_t size = 1;
154+ for (uint32_t i = 0; i < shapes.size(); i++) {
155+ size *= shapes[i];
156+ }
157+ uint32_t data_len = size * GetDataTypeSize(data_type);
158+ int32_t *pData = new (std::nothrow) int32_t[data_len];
159+ for (uint32_t i = 0; i < size; ++i) {
160+ *(pData + i) = value;
161+ }
162+ input_tensor = Tensor(input_tensor_desc, reinterpret_cast<uint8_t *>(pData), data_len);
163+ return SUCCESS;
164+}
165+ 
166+int32_t WriteDataToFile(string bin_file, uint64_t data_size, uint8_t *inputData)
167+{
168+ FILE *fp;
169+ fp = fopen(bin_file.c_str(), "w");
170+ fwrite(inputData, sizeof(uint8_t), data_size, fp);
171+ fclose(fp);
172+ return SUCCESS;
173+}
174+ 
175+int CreateOppInGraph(DataType inDtype, std::vector<ge::Tensor> &input, std::vector<Operator> &inputs,
176+ std::vector<Operator> &outputs, Graph &graph)
177+{
178+ Status ret = SUCCESS;
179+ // 自定义代码:添加单算子定义到图中
180+ auto add1 = op::ScaleAndTranslate("scale_and_translate");
181+ std::vector<int64_t> imagesShape = {1, 4, 4, 3};
182+ std::vector<int64_t> sizeShape = {2};
183+ std::vector<int64_t> scaleShape = {2};
184+ std::vector<int64_t> translationShape = {2};
185+ 
186+ ADD_INPUT(1, images, DT_FLOAT, imagesShape, 1.0);
187+ ADD_INPUT_INT(2, size, DT_INT32, sizeShape);
188+ ADD_INPUT(3, scale, DT_FLOAT, scaleShape, 1.0);
189+ ADD_INPUT(4, translation, DT_FLOAT, translationShape, 0.0);
190+ 
191+ add1.set_attr_kernel_type("lanczos3");
192+ add1.set_attr_antialias(true);
193+ 
194+ outputs.push_back(add1);
195+ // 添加完毕
196+ return SUCCESS;
197+}
198+ 
199+int main(int argc, char *argv[])
200+{
201+ const char *graph_name = "tc_ge_irrun_test";
202+ Graph graph(graph_name);
203+ std::vector<ge::Tensor> input;
204+ 
205+ printf("%s - INFO - [XIR]: Start to initialize ge using ge global options\n", GetTime().c_str());
206+ std::map<AscendString, AscendString> global_options = {{"ge.exec.deviceId", "0"}, {"ge.graphRunMode", "1"}};
207+ Status ret = ge::GEInitialize(global_options);
208+ if (ret != SUCCESS) {
209+ printf("%s - INFO - [XIR]: Initialize ge using ge global options failed\n", GetTime().c_str());
210+ return FAILED;
211+ }
212+ printf("%s - INFO - [XIR]: Initialize ge using ge global options success\n", GetTime().c_str());
213+ 
214+ std::vector<Operator> inputs{};
215+ std::vector<Operator> outputs{};
216+ 
217+ std::cout << argv[1] << std::endl;
218+ char *endptr;
219+ 
220+ DataType inDtype = DT_FLOAT;
221+ std::cout << inDtype << std::endl;
222+ 
223+ ret = CreateOppInGraph(inDtype, input, inputs, outputs, graph);
224+ if (ret != SUCCESS) {
225+ printf("%s - ERROR - [XIR]: Create ir session using build options failed\n", GetTime().c_str());
226+ return FAILED;
227+ }
228+ 
229+ if (!inputs.empty() && !outputs.empty()) {
230+ graph.SetInputs(inputs).SetOutputs(outputs);
231+ }
232+ 
233+ std::map<AscendString, AscendString> build_options = {
234+ 
235+ };
236+ printf("%s - INFO - [XIR]: Start to create ir session using build options\n", GetTime().c_str());
237+ ge::Session *session = new Session(build_options);
238+ 
239+ if (session == nullptr) {
240+ printf("%s - ERROR - [XIR]: Create ir session using build options failed\n", GetTime().c_str());
241+ return FAILED;
242+ }
243+ printf("%s - INFO - [XIR]: Create ir session using build options success\n", GetTime().c_str());
244+ printf("%s - INFO - [XIR]: Start to add compute graph to ir session\n", GetTime().c_str());
245+ 
246+ std::map<AscendString, AscendString> graph_options = {
247+ 
248+ };
249+ uint32_t graph_id = 0;
250+ ret = session->AddGraph(graph_id, graph, graph_options);
251+ 
252+ printf("%s - INFO - [XIR]: Session add ir compute graph to ir session success\n", GetTime().c_str());
253+ printf("%s - INFO - [XIR]: dump graph to txt\n", GetTime().c_str());
254+ std::string file_path = "./dump";
255+ aclgrphDumpGraph(graph, file_path.c_str(), file_path.length());
256+ printf("%s - INFO - [XIR]: Start to run ir compute graph\n", GetTime().c_str());
257+ std::vector<ge::Tensor> output;
258+ ret = session->RunGraph(graph_id, input, output);
259+ if (ret != SUCCESS) {
260+ printf("%s - INFO - [XIR]: Run graph failed\n", GetTime().c_str());
261+ delete session;
262+ GEFinalize();
263+ return FAILED;
264+ }
265+ printf("%s - INFO - [XIR]: Session run ir compute graph success\n", GetTime().c_str());
266+ 
267+ int input_num = input.size();
268+ for (int i = 0; i < input_num; i++) {
269+ std::cout << "input " << i << " dtype : " << input[i].GetTensorDesc().GetDataType() << std::endl;
270+ string input_file = "./tc_ge_irrun_test_0008_npu_input_" + std::to_string(i) + ".bin";
271+ uint8_t *input_data_i = input[i].GetData();
272+ int64_t input_shape = input[i].GetTensorDesc().GetShape().GetShapeSize();
273+ std::cout << "this is " << i << "th input, input shape size =" << input_shape << std::endl;
274+ uint32_t data_size = input_shape * GetDataTypeSize(input[i].GetTensorDesc().GetDataType());
275+ WriteDataToFile((const char *)input_file.c_str(), data_size, input_data_i);
276+ }
277+ 
278+ int output_num = output.size();
279+ for (int i = 0; i < output_num; i++) {
280+ std::cout << "output " << i << " dtype : " << output[i].GetTensorDesc().GetDataType() << std::endl;
281+ string output_file = "./tc_ge_irrun_test_0008_npu_output_" + std::to_string(i) + ".bin";
282+ uint8_t *output_data_i = output[i].GetData();
283+ int64_t output_shape = output[i].GetTensorDesc().GetShape().GetShapeSize();
284+ std::cout << "this is " << i << "th output, output shape size =" << output_shape << std::endl;
285+ uint32_t data_size = output_shape * GetDataTypeSize(output[i].GetTensorDesc().GetDataType());
286+ WriteDataToFile((const char *)output_file.c_str(), data_size, output_data_i);
287+ uint8_t *resultData = (uint8_t*)output_data_i;
288+ for (int64_t j = 0; j < output_shape; j++) {
289+ LOG_PRINT("result[%ld] is: %u\n", j, resultData[j]);
290+ }
291+ }
292+ 
293+ ge::AscendString error_msg = ge::GEGetErrorMsgV2();
294+ std::string error_str(error_msg.GetString());
295+ std::cout << "Error message: " << error_str << std::endl;
296+ ge::AscendString warning_msg = ge::GEGetWarningMsgV2();
297+ std::string warning_str(warning_msg.GetString());
298+ std::cout << "Warning message: " << warning_str << std::endl;
299+ printf("%s - INFO - [XIR]: Start to finalize ir graph session\n", GetTime().c_str());
300+ ret = ge::GEFinalize();
301+ if (ret != SUCCESS) {
302+ printf("%s - INFO - [XIR]: Finalize ir graph session failed\n", GetTime().c_str());
303+ return FAILED;
304+ }
305+ printf("%s - INFO - [XIR]: Finalize ir graph session success\n", GetTime().c_str());
306+ return SUCCESS;
307+}
@@ -0,0 +1,58 @@
1+/**
2+ * Copyright (c) 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+ * The code snippet comes from Huawei's open-source Mindspore project.
11+ * Copyright 2019-2020 Huawei Technologies Co., Ltd
12+ * Licensed under the Apache License, Version 2.0 (the "License");
13+ * You may obtain a copy of the License at
14+ * http://www.apache.org/licenses/LICENSE-2.0
15+ *
16+ */
17+ 
18+#ifndef SCALE_AND_TRANSLATE_PROTO_H
19+#define SCALE_AND_TRANSLATE_PROTO_H
20+ 
21+#include "graph/operator.h"
22+#include "graph/operator_reg.h"
23+ 
24+namespace ge {
25+/**
26+ * @brief Resizes "images" to "size" by scale and translate . \n
27+ *
28+ * @par Inputs:
29+ * @li images: A `Tensor`. Must be one of the following types: `int8`, `uint8`,
30+ * `int16`, `uint16`, `int32`, `int64`, `float16`, `float32`, `float64`.
31+ * @li size: A `Tensor` of type `int32`.
32+ * @li scale: A `Tensor` of type `float32`.
33+ * @li translation: A `Tensor` of type `float32` . \n
34+ *
35+ * @par Attributes:
36+ * @li kernel_type: type is string, default is lanczos3.
37+ * @li antialias: type is bool, default is true. \n
38+ *
39+ * @par Outputs:
40+ * y: A Tensor with type float32 . \n
41+ *
42+ * @par Third-party framework compatibility
43+ * Compatible with TensorFlow ScaleAndTranslate operator.
44+*/
45+ 
46+REG_OP(ScaleAndTranslate)
47+ .INPUT(images, TensorType({DT_INT8, DT_UINT8, DT_INT16, DT_UINT16,
48+ DT_INT32, DT_INT64, DT_FLOAT16, DT_FLOAT, DT_DOUBLE}))
49+ .INPUT(size, TensorType({DT_INT32}))
50+ .INPUT(scale, TensorType({DT_FLOAT}))
51+ .INPUT(translation, TensorType({DT_FLOAT}))
52+ .OUTPUT(y, TensorType({DT_FLOAT}))
53+ .ATTR(kernel_type, String, "lanczos3")
54+ .ATTR(antialias, Bool, true)
55+ .OP_END_FACTORY_REG(ScaleAndTranslate)
56+}
57+ 
58+#endif
@@ -0,0 +1,14 @@
1+/**
2+ * Copyright (c) 2026 Huawei Technologies Co., Ltd.
CANN-robot
CANN-robotCANN-robot4月9日
代码结构与可维护性: 版权声明中的年份为2026年,但当前是2026年,这表明代码可能使用了固定的未来年份而非实际年份。虽然这不影响功能,但可能表明代码是从模板复制而来,未更新为实际年份,降低了代码的可维护性和专业性。
问题类型: 代码结构与可维护性
文件路径: image/scale_and_translate/op_host/scale_and_translate_infershape.cpp
行号: 2
问题代码:
 * Copyright (c) 2026 Huawei Technologies Co., Ltd.
修改建议:
建议将版权年份更新为实际年份(例如2025年),或使用动态年份(如`__DATE__`宏)或范围(如2024-2026),以确保版权信息的准确性。
---
此评论由代码审查工具自动生成
likedislike
FengHaozhan
FengHaozhan
4月11日 评论:
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+/*!
12+ * \file scale_and_translate_infershape.cpp
13+ * \brief scale_and_translate infershape
14+ */
@@ -0,0 +1,37 @@
1+# ---------------------------------------------------------------------------------------------------------
2+# Copyright (c) 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+if (BUILD_WITH_INSTALLED_DEPENDENCY_CANN_PKG)
12+ if (NOT (UT_TEST_ALL OR OP_KERNEL_AICPU_UT))
13+ add_definitions(-D_GLIBCXX_USE_CXX11_ABI=1)
14+ set(CMAKE_CXX_COMPILER ${ASCEND_DIR}/toolkit/toolchain/hcc/bin/aarch64-target-linux-gnu-g++)
15+ endif()
16+ 
17+ # aicpu op_def
18+ file(GLOB_RECURSE OP_DEF_FILE ${CMAKE_CURRENT_SOURCE_DIR}/*_aicpu_def.cpp)
19+ set_property(GLOBAL APPEND PROPERTY AICPU_OP_DEF_FILES ${OP_DEF_FILE})
20+ 
21+ # aicpu cust kernel
22+ file(GLOB AICPU_SRC ${CMAKE_CURRENT_SOURCE_DIR}/*_aicpu.cpp)
23+ file(GLOB AICPU_EXTRA_SRC ${CMAKE_CURRENT_SOURCE_DIR}/sampling_kernels.cpp)
24+ list(APPEND AICPU_SRC ${AICPU_EXTRA_SRC})
25+ message(STATUS "[scale_and_translate] Found aicpu sources: ${AICPU_SRC}, ascend dir: ${ASCEND_DIR}, ophsot name: ${OPHOST_NAME}")
26+ 
27+ set(OBJ_NAME scale_and_translate_cust_obj)
28+ add_aicpu_cust_kernel_modules(${OBJ_NAME})
29+ target_sources(${OBJ_NAME} PRIVATE ${AICPU_SRC})
30+endif()
31+ 
32+if(UT_TEST_ALL OR OP_KERNEL_AICPU_UT)
33+ AddAicpuOpTestCase(scale_and_translate)
34+ target_sources(scale_and_translate_cases_obj PRIVATE
35+ ${CMAKE_CURRENT_SOURCE_DIR}/sampling_kernels.cpp
36+ )
37+endif()
@@ -0,0 +1,36 @@
1+/**
2+ * Copyright (c) 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+#include "sampling_kernels.h"
12+#include <map>
13+ 
14+namespace aicpu {
15+SamplingKernelType SamplingKernelTypeFromString(const std::string &str)
16+{
17+ // Define map for different types of sampling kernels
18+ static const std::map<std::string, SamplingKernelType> SamplingTypesInfo {
19+ {"lanczos1", LANCZOS1_KERNEL},
20+ {"lanczos3", LANCZOS3_KERNEL},
21+ {"lanczos5", LANCZOS5_KERNEL},
22+ {"gaussian", GAUSSIAN_KERNEL},
23+ {"box", BOX_KERNEL},
24+ {"triangle", TRIANGLE_KERNEL},
25+ {"keyscubic", KEYS_CUBIC_KERNEL},
26+ {"mitchellcubic", MITCHELL_CUBIC_KERNEL},
27+ };
28+ 
29+ std::map<std::string, SamplingKernelType>::const_iterator iter = SamplingTypesInfo.find(str);
30+ if (iter != SamplingTypesInfo.end()) {
31+ return iter->second;
32+ }
33+ 
34+ return SAMPLING_KERNEL_TYPE_END;
35+}
36+} // namespace aicpu
@@ -0,0 +1,256 @@
1+/**
2+ * Copyright (c) 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 AICPU_UTILS_SAMPLING_KERNELS_H
12+#define AICPU_UTILS_SAMPLING_KERNELS_H
13+ 
14+#include <cmath>
15+#include <cstdio>
16+#include <string>
17+#include "cpu_context.h"
18+#include "utils/kernel_util.h"
19+ 
20+namespace aicpu {
21+// Defines functions for different types of sampling kernels.
22+enum SamplingKernelType {
23+ // Lanczos kernel with radius 1. Aliases but does not ring.
24+ LANCZOS1_KERNEL,
25+ 
26+ /**
27+ * Lanczos kernel with radius 3. High-quality practical filter but may have
28+ * some ringing especially on synthetic images.
29+ */
30+ LANCZOS3_KERNEL,
31+ 
32+ /**
33+ * Lanczos kernel with radius 5. Very-high-quality filter but may have
34+ * stronger ringing.
35+ */
36+ LANCZOS5_KERNEL,
37+ 
38+ // Gaussian kernel with radius 3, sigma = 1.5 / 3. Less commonly used.
39+ GAUSSIAN_KERNEL,
40+ 
41+ /**
42+ * Rectangle function. Equivalent to "nearest" sampling when upscaling.
43+ * Has value 1 in interval (-0.5, 0.5), value 0.5 on edge, and 0 elsewhere.
44+ */
45+ BOX_KERNEL,
46+ 
47+ /**
48+ * Hat/tent function with radius 1. Equivalent to "bilinear" reconstruction
49+ * when upsampling.
50+ * Has value zero at -1.0 and 1.0.
51+ */
52+ TRIANGLE_KERNEL,
53+ 
54+ /**
55+ * Cubic interpolant of Keys. Equivalent to Catmull-Rom kernel. Reasonably
56+ * good quality and faster than LANCZOS3_KERNEL.
57+ */
58+ KEYS_CUBIC_KERNEL,
59+ 
60+ /**
61+ * Cubic non-interpolating scheme. For synthetic images (especially those
62+ * lacking proper prefiltering), less ringing than Keys cubic kernel but less
63+ * sharp.
64+ */
65+ MITCHELL_CUBIC_KERNEL,
66+ 
67+ // Always insert new kernel types before this.
68+ SAMPLING_KERNEL_TYPE_END
69+};
70+ 
71+/**
72+ * Converts a string into the corresponding kernel type.
73+ * Returns SAMPLING_KERNEL_TYPE_END if the string couldn't be converted.
74+ */
75+SamplingKernelType SamplingKernelTypeFromString(const std::string &str);
76+ 
77+// A function object for a Lanczos kernel.
78+struct LanczosKernelFunc {
79+ // Pass 1 for Lanczos1 kernel, 3 for Lanczos3 etc.
80+ explicit LanczosKernelFunc(float _radius) : radius(_radius) {}
81+ float operator()(float x) const
82+ {
83+ constexpr float kPI = 3.14159265359f;
84+ x = std::abs(x);
85+ if (x > radius) {
86+ return 0.0;
87+ }
88+ // Need to special case the limit case of sin(x) / x when x is zero.
89+ if (x <= 1e-3) {
90+ return 1.0;
91+ }
92+ return radius * std::sin(kPI * x) * std::sin(kPI * x / radius) /
93+ (kPI * kPI * x * x);
94+ }
95+ float Radius() const
96+ {
97+ return radius;
98+ }
99+ const float radius;
100+};
101+ 
102+struct GaussianKernelFunc {
103+ static constexpr float kRadiusMultiplier = 3.0f;
104+ /**
105+ * https://en.wikipedia.org/wiki/Gaussian_function
106+ * We use sigma = 0.5, as suggested on p. 4 of Ken Turkowski's "Filters
107+ * for Common Resampling Tasks" for kernels with a support of 3 pixels:
108+ * www.realitypixels.com/turk/computergraphics/ResamplingFilters.pdf
109+ * This implies a radius of 1.5,
110+ */
111+ explicit GaussianKernelFunc(float _radius = 1.5f)
112+ : radius(_radius), sigma(_radius / kRadiusMultiplier) {}
113+ float operator()(float x) const
114+ {
115+ x = std::abs(x);
116+ if (x >= radius) {
117+ return 0.0;
118+ }
119+ return static_cast<float>(std::exp(-x * x / (2.0 * sigma * sigma)));
120+ }
121+ float Radius() const
122+ {
123+ return radius;
124+ }
125+ const float radius;
126+ // Gaussian standard deviation
127+ const float sigma;
128+};
129+ 
130+struct BoxKernelFunc {
131+ float operator()(float x) const
132+ {
133+ x = std::abs(x);
134+ constexpr float pointFive = 0.5f;
135+ constexpr float onePoint = 1.0f;
136+ return x < pointFive ? onePoint : IsValueEqual<float>(x, pointFive) ? pointFive : 0.0f;
137+ }
138+ float Radius() const
139+ {
140+ return 1.f;
141+ }
142+};
143+ 
144+struct TriangleKernelFunc {
145+ // https://en.wikipedia.org/wiki/Triangle_function
146+ float operator()(float x) const
147+ {
148+ x = std::abs(x);
149+ return x < 1.0f ? 1.0f - x : 0.0f;
150+ }
151+ float Radius() const
152+ {
153+ return 1.f;
154+ }
155+};
156+ 
157+struct KeysCubicKernelFunc {
158+ /**
159+ * http://ieeexplore.ieee.org/document/1163711/
160+ * R. G. Keys. Cubic convolution interpolation for digital image
161+ * processing. IEEE Transactions on Acoustics, Speech, and Signal
162+ * Processing, 29(6):1153-1160, 1981.
163+ */
164+ float operator()(float i) const
165+ {
166+ i = std::abs(i);
167+ if (i >= 2.0f) {
168+ return 0.0f;
169+ } else if (i >= 1.0f) {
170+ return ((-0.5f * i + 2.5f) * i - 4.0f) * i + 2.0f;
171+ } else {
172+ return ((1.5f * i - 2.5f) * i) * i + 1.0f;
173+ }
174+ }
175+ float Radius() const
176+ {
177+ return 2.f;
178+ }
179+};
180+ 
181+struct MitchellCubicKernelFunc {
182+ /**
183+ * https://doi.org/10.1145/378456.378514
184+ * D. P. Mitchell and A. N. Netravali. Reconstruction filters in computer
185+ * graphics. Computer Graphics (Proceedings of ACM SIGGRAPH 1988),
186+ * 22(4):221-228, 1988.
187+ */
188+ float operator()(float i) const
189+ {
190+ i = std::abs(i);
191+ if (i >= 2.0f) {
192+ return 0.0f;
193+ } else if (i >= 1.0f) {
194+ return (((-7.0f / 18.0f) * i + 2.0f) * i - 10.0f / 3.0f) * i +
195+ 16.0f / 9.0f;
196+ } else {
197+ return (((7.0f / 6.0f) * i - 2.0f) * i) * i + 8.0f / 9.0f;
198+ }
199+ }
200+ float Radius() const
201+ {
202+ return 2.f;
203+ }
204+};
205+ 
206+inline LanczosKernelFunc CreateLanczos1Kernel()
207+{
208+ float i = 1.0;
209+ return LanczosKernelFunc(i);
210+}
211+ 
212+inline LanczosKernelFunc CreateLanczos3Kernel()
213+{
214+ float i = 3.0;
215+ return LanczosKernelFunc(i);
216+}
217+ 
218+inline LanczosKernelFunc CreateLanczos5Kernel()
219+{
220+ float i = 5.0;
221+ return LanczosKernelFunc(i);
222+}
223+ 
224+inline GaussianKernelFunc CreateGaussianKernel()
225+{
226+ float i = 1.5;
227+ return GaussianKernelFunc(i);
228+}
229+ 
230+inline BoxKernelFunc CreateBoxKernel()
231+{
232+ BoxKernelFunc retfunc = BoxKernelFunc();
233+ return retfunc;
234+}
235+ 
236+inline TriangleKernelFunc CreateTriangleKernel()
237+{
238+ TriangleKernelFunc retfunc = TriangleKernelFunc();
239+ return retfunc;
240+}
241+ 
242+inline KeysCubicKernelFunc CreateKeysCubicKernel()
243+{
244+ KeysCubicKernelFunc retfunc = KeysCubicKernelFunc();
245+ return retfunc;
246+}
247+ 
248+inline MitchellCubicKernelFunc CreateMitchellCubicKernel()
249+{
250+ MitchellCubicKernelFunc retfunc = MitchellCubicKernelFunc();
251+ return retfunc;
252+}
253+ 
254+} // namespace aicpu
255+ 
256+#endif // AICPU_UTILS_SAMPLING_KERNELS_H
@@ -0,0 +1,515 @@
1+/**
2+ * Copyright (c) 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+#include "scale_and_translate_aicpu.h"
12+ 
13+#include <iostream>
14+#include <type_traits>
15+ 
16+#include "cpu_kernel_utils.h"
17+#include "utils/eigen_tensor.h"
18+#include "utils/kernel_util.h"
19+#include "sampling_kernels.h"
20+#include "log.h"
21+ 
22+namespace {
23+const uint32_t kOutputNum = 1;
24+const uint32_t kInputNum = 4;
25+constexpr int64_t kParallelDataNums = 1024;
26+const char *kScaleAndTranslate = "ScaleAndTranslate";
27+ 
28+#define SCALEANDTRANSLATE_COMPUTE_CASE(DTYPE, TYPE, CTX) \
29+ case (DTYPE): { \
30+ uint32_t result = ScaleAndTranslateCompute<TYPE>(CTX); \
31+ if (result != KERNEL_STATUS_OK) { \
32+ KERNEL_LOG_ERROR("ScaleAndTranslate kernel compute failed."); \
33+ return result; \
34+ } \
35+ break; \
36+ }
37+ 
38+#define SWITCH_PARALLEL(SHARD, end_num, ctx) \
39+ if ((end_num) <= kParallelDataNums) { \
40+ for (size_t i = 0; i < size_t(end_num); i++) { \
41+ SHARD(i, i + 1); \
42+ } \
43+ } else { \
44+ KERNEL_HANDLE_ERROR(CpuKernelUtils::ParallelFor(ctx, end_num, 1, SHARD), \
45+ "ScaleAndTranslate #SHARD Compute failed.") \
46+ }
47+ 
48+} // namespace
49+ 
50+namespace aicpu {
51+uint32_t ScaleAndTranslateCpuKernel::Compute(CpuKernelContext &ctx)
52+{
53+ // check params
54+ KERNEL_HANDLE_ERROR(
55+ NormalCheck(ctx, kInputNum, kOutputNum),
56+ "ScaleAndTranslate check input and output number failed.");
57+ KERNEL_HANDLE_ERROR(ScaleAndTranslateCheck(ctx),
58+ "ScaleAndTranslate check params failed.");
59+ auto data_type = ctx.Input(0)->GetDataType();
60+ switch (data_type) {
61+ SCALEANDTRANSLATE_COMPUTE_CASE(DT_INT8, int8_t, ctx)
62+ SCALEANDTRANSLATE_COMPUTE_CASE(DT_UINT8, uint8_t, ctx)
63+ SCALEANDTRANSLATE_COMPUTE_CASE(DT_INT16, int16_t, ctx)
64+ SCALEANDTRANSLATE_COMPUTE_CASE(DT_UINT16, uint16_t, ctx)
65+ SCALEANDTRANSLATE_COMPUTE_CASE(DT_INT32, int32_t, ctx)
66+ SCALEANDTRANSLATE_COMPUTE_CASE(DT_INT64, int64_t, ctx)
67+ SCALEANDTRANSLATE_COMPUTE_CASE(DT_FLOAT16, Eigen::half, ctx)
68+ SCALEANDTRANSLATE_COMPUTE_CASE(DT_FLOAT, float, ctx)
69+ SCALEANDTRANSLATE_COMPUTE_CASE(DT_DOUBLE, double, ctx)
70+ default:
71+ KERNEL_LOG_ERROR("ScaleAndTranslate kernel data type [%s] not support.",
72+ DTypeStr(data_type).c_str());
73+ return KERNEL_STATUS_PARAM_INVALID;
74+ }
75+ return KERNEL_STATUS_OK;
76+}
77+ 
78+uint32_t ScaleAndTranslateCpuKernel::ScaleAndTranslateCheck(
79+ CpuKernelContext &ctx)
80+{
81+ auto input0_shape = ctx.Input(0)->GetTensorShape();
82+ auto input1_shape = ctx.Input(1)->GetTensorShape();
83+ auto input2_shape = ctx.Input(2)->GetTensorShape();
84+ auto input3_shape = ctx.Input(3)->GetTensorShape();
85+ // dims check
86+ KERNEL_CHECK_FALSE(
87+ (input0_shape->GetDims() == 4), KERNEL_STATUS_PARAM_INVALID,
88+ "The input0's dims=[%d] must be 4-dimensional", input0_shape->GetDims())
89+ KERNEL_CHECK_FALSE(
90+ (input1_shape->GetDims() == 1), KERNEL_STATUS_PARAM_INVALID,
91+ "The input1's dims=[%d] must be 1-dimensional", input1_shape->GetDims())
92+ KERNEL_CHECK_FALSE((input1_shape->NumElements() == 2),
93+ KERNEL_STATUS_PARAM_INVALID,
94+ "The input1's numelements=[%d] must have two elements",
95+ input1_shape->NumElements())
96+ 
97+ DataType input1_type = ctx.Input(1)->GetDataType();
98+ DataType input2_type = ctx.Input(2)->GetDataType();
99+ DataType input3_type = ctx.Input(3)->GetDataType();
100+ 
101+ // dtypes check
102+ KERNEL_CHECK_FALSE((input1_type == DT_INT32), KERNEL_STATUS_PARAM_INVALID,
103+ "The input1's dtype=[%d] must be DT_INT32",
104+ DTypeStr(input1_type).c_str())
105+ KERNEL_CHECK_FALSE((input2_type == DT_FLOAT), KERNEL_STATUS_PARAM_INVALID,
106+ "The input2's dtype=[%d] must be DT_FLOAT",
107+ DTypeStr(input2_type).c_str())
108+ KERNEL_CHECK_FALSE((input3_type == DT_FLOAT), KERNEL_STATUS_PARAM_INVALID,
109+ "The input3's dtype=[%d] must be DT_FLOAT",
110+ DTypeStr(input3_type).c_str())
111+ 
112+ KERNEL_LOG_INFO(
113+ "ScaleAndTranslateCpuKernel[%s], input0: size[%llu], input1: size[%llu];"
114+ "input2: size[%llu], input3: size[%llu], output: size[%llu].",
115+ ctx.GetOpType().c_str(), ctx.Input(0)->GetDataSize(),
116+ ctx.Input(1)->GetDataSize(), ctx.Input(2)->GetDataSize(),
117+ ctx.Input(3)->GetDataSize(), ctx.Output(0)->GetDataSize());
118+ return KERNEL_STATUS_OK;
119+}
120+ 
121+template <typename T>
122+inline const T &Clamp(const T &lower, const T &higher, const T &value)
123+{
124+ if (higher < value) {
125+ return higher;
126+ }
127+ if (value < lower) {
128+ return lower;
129+ }
130+ return value;
131+}
132+ 
133+static void NormalizeSpanWeights(const std::vector<float> &temp_weights,
134+ float total_weight, int span_size, int x,
135+ Eigen::TensorMap<Eigen::Tensor<float, 1>> &weights_vec)
136+{
137+ if (std::abs(total_weight) >=
138+ 1000.0f * std::numeric_limits<float>::min()) {
139+ float one_over_total_weight = 1.0f / total_weight;
140+ int out_index = span_size * x;
141+ for (float weight : temp_weights) {
142+ weights_vec(out_index) = weight * one_over_total_weight;
143+ ++out_index;
144+ }
145+ }
146+}
147+ 
148+template <typename Kernel>
149+uint32_t InitSpans(const Kernel &kernel, int64_t output_size,
150+ int64_t input_size, bool antialias, float inv_scale,
151+ Spans *spans, float &kernel_scale)
152+{
153+ kernel_scale = antialias ? std::max(inv_scale, 1.0f) : 1.0f;
154+ spans->span_size = std::min(
155+ 2 * static_cast<int>(std::ceil(kernel.Radius() * kernel_scale)) + 1,
156+ static_cast<int>(input_size));
157+ 
158+ spans->starts = new (std::nothrow) Eigen::Tensor<int32_t, 1>(output_size);
159+ KERNEL_CHECK_NULLPTR(spans->starts, KERNEL_STATUS_PARAM_INVALID,
160+ "New spans starts failed.")
161+ spans->weights = new (std::nothrow) Eigen::Tensor<float, 1>(spans->span_size * output_size);
162+ KERNEL_CHECK_NULLPTR(spans->weights, KERNEL_STATUS_PARAM_INVALID,
163+ "New spans weights failed.")
164+ return KERNEL_STATUS_OK;
165+}
166+ 
167+template <typename Kernel>
168+uint32_t ComputeSpansCore(CpuKernelContext &context, const Kernel &kernel, const int64_t output_size,
169+ const int64_t input_size, const float scale, const float translate,
170+ const bool antialias, Spans *spans)
171+{
172+ const float inv_scale = 1.0 / scale;
173+ const float inv_translate = -inv_scale * translate;
174+ float kernel_scale = 0.0f;
175+ KERNEL_HANDLE_ERROR(InitSpans(kernel, output_size, input_size, antialias,
176+ inv_scale, spans, kernel_scale), "InitSpans failed.");
177+ Eigen::TensorMap<Eigen::Tensor<int32_t, 1>> starts_vec( spans->starts->data(), spans->starts->dimensions());
178+ Eigen::TensorMap<Eigen::Tensor<float, 1>> weights_vec(spans->weights->data(), spans->weights->dimensions());
179+ weights_vec.setZero();
180+ const float one_over_kernel_scale = 1.0f / kernel_scale;
181+ int max_span_size = 0;
182+ std::vector<float> temp_weights;
183+ uint32_t shard_ret = KERNEL_STATUS_OK;
184+ auto shard_x = [&](int start, int end) {
185+ for (auto x = start; x < end; ++x) {
186+ const float col_f = x + 0.5f;
187+ const float sample_f = col_f * inv_scale + inv_translate;
188+ // Don't sample when the sampling location is outside the source image.
189+ if (sample_f < 0 || sample_f > input_size) {
190+ // Add an empty span.
191+ starts_vec(x) = 0;
192+ continue;
193+ }
194+ int64_t span_start = std::ceil(sample_f - kernel.Radius() * kernel_scale - 0.5f);
195+ int64_t span_end = std::floor(sample_f + kernel.Radius() * kernel_scale - 0.5f);
196+ span_start = Clamp(static_cast<int64_t>(0), input_size - 1, span_start);
197+ span_end = Clamp(static_cast<int64_t>(0), input_size - 1, span_end) + 1;
198+ const int this_span_size = span_end - span_start;
199+ if (this_span_size > spans->span_size) {
200+ KERNEL_LOG_ERROR("Span is too large: [%d] vs [%d].", this_span_size, spans->span_size);
201+ shard_ret = KERNEL_STATUS_PARAM_INVALID;
202+ return;
203+ }
204+ float total_weight = 0.0f;
205+ temp_weights.clear();
206+ for (int source = span_start; source < span_end; ++source) {
207+ float kernel_pos = static_cast<float>(source) + 0.5f - sample_f;
208+ float weight = kernel(std::abs(kernel_pos * one_over_kernel_scale));
209+ total_weight += weight;
210+ temp_weights.push_back(weight);
211+ }
212+ max_span_size = std::max(max_span_size, this_span_size);
213+ NormalizeSpanWeights(temp_weights, total_weight, spans->span_size, x, weights_vec);
214+ starts_vec(x) = span_start;
215+ }
216+ };
217+ SWITCH_PARALLEL(shard_x, output_size, context);
218+ if (shard_ret != KERNEL_STATUS_OK) {
219+ return shard_ret;
220+ }
221+ return KERNEL_STATUS_OK;
222+}
223+ 
224+uint32_t ComputeSpans(CpuKernelContext &context,
225+ const SamplingKernelType kernel_type,
226+ const int64_t output_size, const int64_t input_size,
227+ const float scale, const float translate,
228+ const bool antialias, Spans *spans)
229+{
230+ switch (kernel_type) {
231+ case LANCZOS1_KERNEL: {
232+ return ComputeSpansCore(context, CreateLanczos1Kernel(), output_size,
233+ input_size, scale, translate, antialias, spans);
234+ }
235+ case LANCZOS3_KERNEL: {
236+ return ComputeSpansCore(context, CreateLanczos3Kernel(), output_size,
237+ input_size, scale, translate, antialias, spans);
238+ }
239+ case LANCZOS5_KERNEL: {
240+ return ComputeSpansCore(context, CreateLanczos5Kernel(), output_size,
241+ input_size, scale, translate, antialias, spans);
242+ }
243+ case GAUSSIAN_KERNEL: {
244+ return ComputeSpansCore(context, CreateGaussianKernel(), output_size,
245+ input_size, scale, translate, antialias, spans);
246+ }
247+ case BOX_KERNEL: {
248+ return ComputeSpansCore(context, CreateBoxKernel(), output_size,
249+ input_size, scale, translate, antialias, spans);
250+ }
251+ case TRIANGLE_KERNEL: {
252+ return ComputeSpansCore(context, CreateTriangleKernel(), output_size,
253+ input_size, scale, translate, antialias, spans);
254+ }
255+ case KEYS_CUBIC_KERNEL: {
256+ return ComputeSpansCore(context, CreateKeysCubicKernel(), output_size,
257+ input_size, scale, translate, antialias, spans);
258+ }
259+ case MITCHELL_CUBIC_KERNEL: {
260+ return ComputeSpansCore(context, CreateMitchellCubicKernel(), output_size,
261+ input_size, scale, translate, antialias, spans);
262+ }
263+ default:
264+ KERNEL_LOG_ERROR("kernel_type kernel data type [%u] not support.",
265+ kernel_type);
266+ return KERNEL_STATUS_PARAM_INVALID;
267+ }
268+ return KERNEL_STATUS_OK;
269+}
270+ 
271+struct ScaleAndTranslateParams {
272+ SamplingKernelType kernel_type;
273+ bool antialias;
274+ int64_t batch_size;
275+ int64_t input_height;
276+ int64_t input_width;
277+ int64_t channels;
278+ int64_t output_height;
279+ int64_t output_width;
280+ float row_scale;
281+ float col_scale;
282+ float row_translation;
283+ float col_translation;
284+};
285+ 
286+static uint32_t ParseScaleAndTranslateParams(CpuKernelContext &ctx,
287+ ScaleAndTranslateParams &p)
288+{
289+ auto input_size = reinterpret_cast<int32_t *>(ctx.Input(1)->GetData());
290+ auto input_scale = reinterpret_cast<float *>(ctx.Input(2)->GetData());
291+ auto input_translation = reinterpret_cast<float *>(ctx.Input(3)->GetData());
292+ KERNEL_CHECK_NULLPTR(ctx.GetAttr("kernel_type"), KERNEL_STATUS_PARAM_INVALID, "Get attr [kernel_type] failed.");
293+ std::string kernel_type_str = ctx.GetAttr("kernel_type")->GetString();
294+ KERNEL_CHECK_NULLPTR(ctx.GetAttr("antialias"), KERNEL_STATUS_PARAM_INVALID, "Get attr [antialias] failed.");
295+ p.antialias = ctx.GetAttr("antialias")->GetBool();
296+ p.kernel_type = SamplingKernelTypeFromString(kernel_type_str);
297+ 
298+ auto input0_shape = ctx.Input(0)->GetTensorShape();
299+ 
300+ p.output_height = input_size[0];
301+ p.output_width = input_size[1];
302+ 
303+ p.batch_size = input0_shape->GetDimSize(0);
304+ p.input_height = input0_shape->GetDimSize(1);
305+ p.input_width = input0_shape->GetDimSize(2);
306+ p.channels = input0_shape->GetDimSize(3);
307+ 
308+ KERNEL_CHECK_FALSE(
309+ (p.output_height > 0 && p.output_width > 0), KERNEL_STATUS_PARAM_INVALID,
310+ "output_height = [%d] and output_width = [%d] must be positive",
311+ p.output_height, p.output_width)
312+ KERNEL_CHECK_FALSE((p.channels > 0), KERNEL_STATUS_PARAM_INVALID,
313+ "image_channel = [%d] must have at least one", p.channels)
314+ KERNEL_CHECK_FALSE(
315+ (p.input_height > 0 && p.input_width > 0), KERNEL_STATUS_PARAM_INVALID,
316+ "input_height = [%d] and input_width = [%d] must be of non-zero size",
317+ p.input_height, p.input_width)
318+ 
319+ p.row_scale = input_scale[0];
320+ p.col_scale = input_scale[1];
321+ 
322+ KERNEL_CHECK_FALSE(
323+ (p.row_scale > 0 && p.col_scale > 0), KERNEL_STATUS_PARAM_INVALID,
324+ "row_scale = [%d] and col_scale = [%d] must be greater than zero.",
325+ p.row_scale, p.col_scale)
326+ 
327+ p.row_translation = input_translation[0];
328+ p.col_translation = input_translation[1];
329+ return KERNEL_STATUS_OK;
330+}
331+ 
332+template <typename T>
333+uint32_t ScaleAndTranslateCpuKernel::ScaleAndTranslateCompute(
334+ CpuKernelContext &ctx)
335+{
336+ ScaleAndTranslateParams p;
337+ KERNEL_HANDLE_ERROR(ParseScaleAndTranslateParams(ctx, p),
338+ "ScaleAndTranslate parse params failed.");
339+ 
340+ Tensor *input = ctx.Input(0);
341+ Tensor *output = ctx.Output(0);
342+ 
343+ EigenTensor inputTensor(input, input->GetData());
344+ EigenTensor outputTensor(output, output->GetData());
345+ 
346+ typename TTypes<T, 4>::Tensor image_data(inputTensor.tensor<T, 4>());
347+ 
348+ typename TTypes<float, 4>::Tensor output_data(
349+ outputTensor.tensor<float, 4>());
350+ 
351+ Spans col_spans;
352+ ComputeSpans(ctx, p.kernel_type, p.output_width, p.input_width, p.col_scale,
353+ p.col_translation, p.antialias, &col_spans);
354+ 
355+ Spans row_spans;
356+ ComputeSpans(ctx, p.kernel_type, p.output_height, p.input_height, p.row_scale,
357+ p.row_translation, p.antialias, &row_spans);
358+ 
359+ Eigen::Tensor<float, 4> intermediate_tensor_middle(p.batch_size, p.output_height,
360+ p.input_width, p.channels);
361+ Eigen::TensorMap<Eigen::Tensor<float, 4>> intermediate_data(
362+ intermediate_tensor_middle.data(),
363+ intermediate_tensor_middle.dimensions());
364+ Eigen::TensorMap<Eigen::Tensor<int32_t, 1>> row_starts(
365+ row_spans.starts->data(), row_spans.starts->dimensions());
366+ Eigen::TensorMap<Eigen::Tensor<float, 1>> row_weights(
367+ row_spans.weights->data(), row_spans.weights->dimensions());
368+ Eigen::TensorMap<Eigen::Tensor<int32_t, 1>> col_starts(
369+ col_spans.starts->data(), col_spans.starts->dimensions());
370+ Eigen::TensorMap<Eigen::Tensor<float, 1>> col_weights(
371+ col_spans.weights->data(), col_spans.weights->dimensions());
372+ 
373+ GatherSpans<T>()(ctx, row_spans.span_size, row_starts, row_weights,
374+ col_spans.span_size, col_starts, col_weights, image_data,
375+ intermediate_data, output_data);
376+ 
377+ delete col_spans.starts;
378+ delete col_spans.weights;
379+ delete row_spans.starts;
380+ delete row_spans.weights;
381+ 
382+ return KERNEL_STATUS_OK;
383+}
384+ 
385+template <typename T>
386+inline void GatherColumnPixel(const T *input_row_start, const int32_t *starts,
387+ const float *weights, int x, int span_size,
388+ int64_t input_width, int channels, float *out_pixel)
389+{
390+ const T *in_pixel = input_row_start + starts[x] * channels;
391+ const float *weights_start = weights + x * span_size;
392+ const int real_span_size =
393+ std::min(starts[x] + span_size, static_cast<int>(input_width)) - starts[x];
394+ const float *weights_end = weights_start + real_span_size;
395+ for (int c = 0; c < channels; ++c) {
396+ out_pixel[c] = 0.0f;
397+ }
398+ for (const float *weight_ptr = weights_start; weight_ptr != weights_end; ++weight_ptr) {
399+ float weight = *weight_ptr;
400+ for (int c = 0; c < channels; ++c) {
401+ out_pixel[c] += weight * static_cast<float>(in_pixel[c]);
402+ }
403+ in_pixel += channels;
404+ }
405+}
406+ 
407+template <typename T>
408+uint32_t GatherColumns(CpuKernelContext &context, int span_size,
409+ const int32_t *starts, const float *weights,
410+ const T *image, const int64_t input_height,
411+ const int64_t input_width, const int64_t output_height,
412+ const int64_t output_width, const int channels,
413+ float *output)
414+{
415+ const int64_t in_row_size = input_width * channels;
416+ const int64_t out_row_size = output_width * channels;
417+ auto shard_column = [&](int start, int end) {
418+ for (int y = start; y < end; ++y) {
419+ const T *input_row_start = image + in_row_size * y;
420+ float *out_pixel = output + out_row_size * y;
421+ for (int x = 0; x < output_width; ++x, out_pixel += channels) {
422+ GatherColumnPixel(input_row_start, starts, weights, x, span_size,
423+ input_width, channels, out_pixel);
424+ }
425+ }
426+ };
427+ SWITCH_PARALLEL(shard_column, output_height, context);
428+ return KERNEL_STATUS_OK;
429+}
430+ 
431+template <typename T>
432+inline void AddScaledVector(const T *in_vec, int vec_length, float weight,
433+ float *out_vec)
434+{
435+ float *out_vec_end = out_vec + vec_length;
436+ for (; out_vec != out_vec_end; ++out_vec, ++in_vec) {
437+ *out_vec += weight * static_cast<float>(*in_vec);
438+ }
439+}
440+ 
441+template <typename T>
442+uint32_t GatherRows(CpuKernelContext &context, int span_size,
443+ const int32_t *starts, const float *weights, const T *image,
444+ const int64_t input_height, const int64_t input_width,
445+ const int64_t output_height, const int64_t output_width,
446+ const int channels, float *output)
447+{
448+ const int64_t in_row_size = input_width * channels;
449+ const int64_t out_row_size = output_width * channels;
450+ auto shard_rows = [&](int start, int end) {
451+ for (int y = start; y < end; ++y) {
452+ float *output_row_data = output + out_row_size * y;
453+ std::fill(output_row_data, output_row_data + out_row_size, 0.0f);
454+ int in_row = starts[y];
455+ const T *input_row_data = image + in_row_size * in_row;
456+ const float *weights_start = weights + y * span_size;
457+ const int real_span_size =
458+ std::min(starts[y] + span_size, static_cast<int>(input_height)) - starts[y];
459+ const float *const weights_end = weights_start + real_span_size;
460+ 
461+ for (const float *weight_it = weights_start; weight_it != weights_end; ++weight_it) {
462+ AddScaledVector(input_row_data, in_row_size, *weight_it, output_row_data);
463+ input_row_data += in_row_size;
464+ }
465+ }
466+ };
467+ SWITCH_PARALLEL(shard_rows, output_height, context);
468+ return KERNEL_STATUS_OK;
469+}
470+ 
471+template <typename T>
472+uint32_t GatherSpans<T>::operator()(
473+ aicpu::CpuKernelContext &context, int row_span_size,
474+ Eigen::TensorMap<Eigen::Tensor<int32_t, 1>> row_starts,
475+ Eigen::TensorMap<Eigen::Tensor<float, 1>> row_weights, int col_span_size,
476+ Eigen::TensorMap<Eigen::Tensor<int32_t, 1>> col_starts,
477+ Eigen::TensorMap<Eigen::Tensor<float, 1>> col_weights,
478+ typename TTypes<T, 4>::Tensor images,
479+ Eigen::TensorMap<Eigen::Tensor<float, 4>> intermediate_buffer,
480+ typename TTypes<float, 4>::Tensor resized_images)
481+{
482+ const int batch_size = images.dimension(0);
483+ const int64_t input_height = images.dimension(1);
484+ const int64_t input_width = images.dimension(2);
485+ const int channels = images.dimension(3);
486+ 
487+ const int64_t output_height = resized_images.dimension(1);
488+ const int64_t output_width = resized_images.dimension(2);
489+ 
490+ const int64_t input_pix_per_batch = input_width * input_height * channels;
491+ const int64_t intermediate_pix_per_batch =
492+ input_width * output_height * channels;
493+ const int64_t output_pix_per_batch = output_width * output_height * channels;
494+ float *intermediate_ptr = intermediate_buffer.data();
495+ 
496+ const T *image_ptr = images.data();
497+ float *out_ptr = resized_images.data();
498+ 
499+ auto row_start_data = row_starts.data();
500+ auto row_weights_data = row_weights.data();
501+ for (int b = 0; b < batch_size; ++b, image_ptr += input_pix_per_batch,
502+ intermediate_ptr += intermediate_pix_per_batch,
503+ out_ptr += output_pix_per_batch) {
504+ GatherRows(context, row_span_size, row_start_data, row_weights_data,
505+ image_ptr, input_height, input_width, output_height, input_width,
506+ channels, intermediate_ptr);
507+ GatherColumns(context, col_span_size, col_starts.data(), col_weights.data(),
508+ intermediate_ptr, output_height, input_width, output_height,
509+ output_width, channels, out_ptr);
510+ }
511+ return KERNEL_STATUS_OK;
512+}
513+ 
514+REGISTER_CPU_KERNEL(kScaleAndTranslate, ScaleAndTranslateCpuKernel);
515+} // namespace aicpu
@@ -0,0 +1,63 @@
1+/**
2+ * Copyright (c) 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 AICPU_KERNELS_NORMALIZED_SCALE_AND_TRANSLATE_H_
12+#define AICPU_KERNELS_NORMALIZED_SCALE_AND_TRANSLATE_H_
13+ 
14+#include "cpu_kernel.h"
15+#include "cpu_kernel_utils.h"
16+#include "cpu_types.h"
17+#include "log.h"
18+#include "status.h"
19+#include "sampling_kernels.h"
20+#include "utils/eigen_tensor.h"
21+#include "utils/kernel_util.h"
22+#include "unsupported/Eigen/CXX11/Tensor"
23+ 
24+namespace aicpu {
25+ 
26+class ScaleAndTranslateCpuKernel : public CpuKernel {
27+public:
28+ ScaleAndTranslateCpuKernel() = default;
29+ ~ScaleAndTranslateCpuKernel() override = default;
30+ 
31+protected:
32+ uint32_t Compute(CpuKernelContext &ctx) override;
33+ 
34+private:
35+ static uint32_t ScaleAndTranslateCheck(CpuKernelContext &ctx);
36+ 
37+ template <typename T>
38+ static uint32_t ScaleAndTranslateCompute(CpuKernelContext &ctx);
39+};
40+ 
41+struct Spans {
42+ // The maximum span size of any output pixel.
43+ int span_size;
44+ // int32 tensor of size [output_dim].
45+ Eigen::Tensor<int32_t, 1> *starts;
46+ // float tensor of size [output_dim, span_size].
47+ Eigen::Tensor<float, 1> *weights;
48+};
49+ 
50+template <typename T>
51+struct GatherSpans {
52+ uint32_t operator()(aicpu::CpuKernelContext &context, int row_span_size,
53+ Eigen::TensorMap<Eigen::Tensor<int32_t, 1>> row_starts,
54+ Eigen::TensorMap<Eigen::Tensor<float, 1>> row_weights,
55+ int col_span_size,
56+ Eigen::TensorMap<Eigen::Tensor<int32_t, 1>> col_starts,
57+ Eigen::TensorMap<Eigen::Tensor<float, 1>> col_weights,
58+ typename TTypes<T, 4>::Tensor input_images,
59+ Eigen::TensorMap<Eigen::Tensor<float, 4>> intermediate_buffer,
60+ typename TTypes<float, 4>::Tensor output_images);
61+};
62+} // namespace aicpu
63+#endif // AICPU_KERNELS_NORMALIZED_SCALE_AND_TRANSLATE_H_
@@ -0,0 +1,39 @@
1+/**
2+ * Copyright (c) 2025 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+/*!
12+ * \file scale_and_translate_aicpu_def.cpp
13+ * \brief scale_and_translate def
14+ */
15+ 
16+#include "register/op_def_registry.h"
17+#include "../../../common/inc/aicpu/aicpu_op_def.h"
18+ 
19+namespace ops {
20+class ScaleAndTranslate : public OpDef {
21+public:
22+ explicit ScaleAndTranslate(const char* name) : OpDef(name)
23+ {
24+ ApplyCvAicpuDefaultCfg(*this);
25+ this->Input("images").DataType(
26+ {ge::DT_INT8, ge::DT_UINT8, ge::DT_INT16, ge::DT_UINT16,
27+ ge::DT_INT32, ge::DT_INT64, ge::DT_FLOAT16, ge::DT_FLOAT, ge::DT_DOUBLE});
28+ this->Input("size").DataType({ge::DT_INT32});
29+ this->Input("scale").DataType({ge::DT_FLOAT});
30+ this->Input("translation").DataType({ge::DT_FLOAT});
31+ this->Output("y").DataType({ge::DT_FLOAT});
32+ this->Attr("kernel_type").AttrType(OPTIONAL).String("lanczos3");
33+ this->Attr("antialias").AttrType(OPTIONAL).Bool(true);
34+ this->AICPU().ExtendCfgInfo(OP_INFO_OPS_FLAG.c_str(), OPEN_OPS_FLAG.c_str());
35+ }
36+};
37+ 
38+OP_ADD(ScaleAndTranslate);
39+} // namespace ops
@@ -0,0 +1,16 @@
1+# -----------------------------------------------------------------------------------------------------------
2+# Copyright (c) 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+file(GLOB CURRENT_DIRS RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/*)
12+foreach(SUB_DIR ${CURRENT_DIRS})
13+ if(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/${SUB_DIR}/CMakeLists.txt")
14+ add_subdirectory(${SUB_DIR})
15+ endif()
16+endforeach()
@@ -0,0 +1,15 @@
1+# -----------------------------------------------------------------------------------------------------------
2+# Copyright (c) 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+file(GLOB CURRENT_DIRS RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/*)
11+foreach(SUB_DIR ${CURRENT_DIRS})
12+ if(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/${SUB_DIR}/CMakeLists.txt")
13+ add_subdirectory(${SUB_DIR})
14+ endif()
15+endforeach()
@@ -0,0 +1,21 @@
1+# ---------------------------------------------------------------------------------------------------------
2+# Copyright (c) 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+ 
12+file(GLOB CURRENT_DIRS RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/*)
13+foreach(SUB_DIR ${CURRENT_DIRS})
14+ if(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/${SUB_DIR}/CMakeLists.txt")
15+ add_subdirectory(${SUB_DIR})
16+ endif()
17+endforeach()
18+ 
19+if(TILING_UT OR (UT_TEST_ALL AND NOT AICPU_ONLY))
20+ target_sources(ops_cpp_proto_utest PRIVATE test_scale_and_translate_infershape.cpp)
21+endif()
@@ -0,0 +1,11 @@
1+/**
2+ * Copyright (c) 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+// Placeholder for ScaleAndTranslate infershape test
@@ -0,0 +1,16 @@
1+# -----------------------------------------------------------------------------------------------------------
2+# Copyright (c) 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+file(GLOB CURRENT_SOURCE_DIRS LIST_DIRECTORIES true ${CMAKE_CURRENT_SOURCE_DIR}/*)
12+foreach(SUB_DIR ${CURRENT_SOURCE_DIRS})
13+ if(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/${SUB_DIR}/CMakeLists.txt")
14+ add_subdirectory(${SUB_DIR})
15+ endif()
16+endforeach()
@@ -0,0 +1,1179 @@
1+/**
2+ * Copyright (c) 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+#include "gtest/gtest.h"
11+#ifndef private
12+#define private public
13+#define protected public
14+#endif
15+#include "utils/aicpu_test_utils.h"
16+#include "cpu_kernel_utils.h"
17+#include "node_def_builder.h"
18+#undef private
19+#undef protected
20+#include "Eigen/Core"
21+#include <random>
22+ 
23+using namespace std;
24+using namespace aicpu;
25+ 
26+class TEST_SCALEANDTRANSLATE_UT : public testing::Test {};
27+ 
28+template<typename T>
29+void SetCheckerboardImageInput(int64_t batch_size, int64_t num_row_squares,
30+ int64_t num_col_squares, int64_t square_size,
31+ int64_t num_channels, std::vector<T>& data) {
32+ const int64_t row_size = num_col_squares * square_size * num_channels;
33+ const int64_t image_size = num_row_squares * square_size * row_size;
34+ data.resize(batch_size * image_size);
35+ typedef std::mt19937 RNG_Engine;
36+ RNG_Engine rng;
37+ rng.seed(0);
38+ std::uniform_real_distribution<float> Unifrom_01(0, 1);
39+ std::vector<float> col(num_channels);
40+ for (int b = 0; b < batch_size; ++b) {
41+ for (int y = 0; y < num_row_squares; ++y) {
42+ for (int x = 0; x < num_col_squares; ++x) {
43+ for (int n = 0; n < num_channels; ++n) {
44+ col[n] = Unifrom_01(rng);
45+ }
46+ for (int r = y * square_size; r < (y + 1) * square_size; ++r) {
47+ auto it = data.begin() + b * image_size + r * row_size +
48+ x * square_size * num_channels;
49+ for (int n = 0; n < square_size; ++n) {
50+ for (int chan = 0; chan < num_channels; ++chan, ++it) {
51+ *it = static_cast<T>(col[chan] * 255.0f);
52+ }
53+ }
54+ }
55+ }
56+ }
57+ }
58+ 
59+}
60+ 
61+#define CREATE_NODEDEF(shapes, data_types, datas, kernel_type_str, antialias) \
62+ auto node_def = CpuKernelUtils::CpuKernelUtils::CreateNodeDef(); \
63+ NodeDefBuilder(node_def.get(), "ScaleAndTranslate", "ScaleAndTranslate") \
64+ .Input({"images", (data_types)[0], (shapes)[0], (datas)[0]}) \
65+ .Input({"size", (data_types)[1], (shapes)[1], (datas)[1]}) \
66+ .Input({"scale", (data_types)[2], (shapes)[2], (datas)[2]}) \
67+ .Input({"translation", (data_types)[3], (shapes)[3], (datas)[3]}) \
68+ .Output({"y", (data_types)[4], (shapes)[4], (datas)[4]}) \
69+ .Attr("kernel_type", std::string(kernel_type_str)) \
70+ .Attr("antialias", (bool)(antialias));
71+ 
72+TEST_F(TEST_SCALEANDTRANSLATE_UT, DATA_TYPE_FLOAT_BOX_SUCC) {
73+ vector<DataType> data_types = {DT_FLOAT, DT_INT32, DT_FLOAT, DT_FLOAT, DT_FLOAT};
74+ vector<int64_t> in_shape = {1, 2, 3, 1};
75+ vector<int64_t> out_shape = {1, 4, 6, 1};
76+ vector<vector<int64_t>> shapes = {in_shape, {2}, {2}, {2}, out_shape};
77+ 
78+ float image_data[6] = {138.568253f, 70.984192f, 108.251984f, 215.417908f, 1.203308f, 31.000126f};
79+ int32_t size_data[2] = {4, 6};
80+ float scale_data[2] = {1.000000f, 1.000000f};
81+ float translate_data[2] = {0.000000f, 0.000000f};
82+ 
83+ float output[24] = {0};
84+ float output_exp[24] = {
85+ 138.568253f, 70.984192f, 108.251984f, 0.000000f, 0.000000f, 0.000000f,
86+ 215.417908f, 1.203308f, 31.000126f, 0.000000f, 0.000000f, 0.000000f,
87+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
88+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f};
89+ 
90+ vector<void*> datas = {(void*)image_data, (void*)size_data, (void*)scale_data, (void*)translate_data, (void*)output};
91+ CREATE_NODEDEF(shapes, data_types, datas, "box", true);
92+ RUN_KERNEL(node_def, HOST, KERNEL_STATUS_OK);
93+ 
94+ bool compare = CompareResult(output, output_exp, 24);
95+ EXPECT_EQ(compare, true);
96+}
97+ 
98+TEST_F(TEST_SCALEANDTRANSLATE_UT, DATA_TYPE_FLOAT_KEYSCUBIC_SUCC) {
99+ vector<DataType> data_types = {DT_FLOAT, DT_INT32, DT_FLOAT, DT_FLOAT, DT_FLOAT};
100+ vector<int64_t> in_shape = {1, 2, 3, 1};
101+ vector<int64_t> out_shape = {1, 4, 6, 1};
102+ vector<vector<int64_t>> shapes = {in_shape, {2}, {2}, {2}, out_shape};
103+ 
104+ float image_data[6] = {131.681656f, 145.520233f, 7.260928f, 43.738022f, 174.745636f, 212.643707f};
105+ int32_t size_data[2] = {4, 6};
106+ float scale_data[2] = {1.200000f, 1.500000f};
107+ float translate_data[2] = {0.100000f, 0.200000f};
108+ 
109+ float output[24] = {0};
110+ float output_exp[24] = {
111+ 136.860214f, 145.327011f, 140.872299f, 29.942684f, -22.839226f, 0.000000f,
112+ 60.625866f, 100.689201f, 167.188705f, 157.434418f, 149.374008f, 0.000000f,
113+ 18.317068f, 75.915985f, 181.793854f, 228.190155f, 244.949417f, 0.000000f,
114+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f};
115+ 
116+ vector<void*> datas = {(void*)image_data, (void*)size_data, (void*)scale_data, (void*)translate_data, (void*)output};
117+ CREATE_NODEDEF(shapes, data_types, datas, "keyscubic", true);
118+ RUN_KERNEL(node_def, HOST, KERNEL_STATUS_OK);
119+ 
120+ bool compare = CompareResult(output, output_exp, 24);
121+ EXPECT_EQ(compare, true);
122+}
123+ 
124+TEST_F(TEST_SCALEANDTRANSLATE_UT, DATA_TYPE_FLOAT_MITCHELLCUBIC_SUCC) {
125+ vector<DataType> data_types = {DT_FLOAT, DT_INT32, DT_FLOAT, DT_FLOAT, DT_FLOAT};
126+ vector<int64_t> in_shape = {1, 2, 3, 1};
127+ vector<int64_t> out_shape = {1, 4, 6, 1};
128+ vector<vector<int64_t>> shapes = {in_shape, {2}, {2}, {2}, out_shape};
129+ 
130+ float image_data[6] = {152.408798f, 172.376663f, 76.316841f, 186.338776f, 147.578552f, 206.299500f};
131+ int32_t size_data[2] = {4, 6};
132+ float scale_data[2] = {1.000000f, 1.000000f};
133+ float translate_data[2] = {0.300000f, 0.100000f};
134+ 
135+ float output[24] = {0};
136+ float output_exp[24] = {
137+ 151.321594f, 169.369431f, 83.013969f, 0.000000f, 0.000000f, 0.000000f,
138+ 176.018616f, 157.613495f, 166.405380f, 0.000000f, 0.000000f, 0.000000f,
139+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
140+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f};
141+ 
142+ vector<void*> datas = {(void*)image_data, (void*)size_data, (void*)scale_data, (void*)translate_data, (void*)output};
143+ CREATE_NODEDEF(shapes, data_types, datas, "mitchellcubic", true);
144+ RUN_KERNEL(node_def, HOST, KERNEL_STATUS_OK);
145+ 
146+ bool compare = CompareResult(output, output_exp, 24);
147+ EXPECT_EQ(compare, true);
148+}
149+ 
150+TEST_F(TEST_SCALEANDTRANSLATE_UT, DATA_TYPE_FLOAT_GAUSSIAN_SUCC) {
151+ vector<DataType> data_types = {DT_FLOAT, DT_INT32, DT_FLOAT, DT_FLOAT, DT_FLOAT};
152+ vector<int64_t> in_shape = {1, 2, 3, 1};
153+ vector<int64_t> out_shape = {1, 4, 6, 1};
154+ vector<vector<int64_t>> shapes = {in_shape, {2}, {2}, {2}, out_shape};
155+ 
156+ float image_data[6] = {110.188354f, 44.424892f, 43.590641f, 211.046219f, 149.728668f, 117.135208f};
157+ int32_t size_data[2] = {4, 6};
158+ float scale_data[2] = {1.500000f, 1.000000f};
159+ float translate_data[2] = {0.000000f, 0.300000f};
160+ 
161+ float output[24] = {0};
162+ float output_exp[24] = {
163+ 114.176651f, 70.930641f, 49.267105f, 0.000000f, 0.000000f, 0.000000f,
164+ 158.128662f, 115.779861f, 85.544647f, 0.000000f, 0.000000f, 0.000000f,
165+ 202.080704f, 160.629074f, 121.822182f, 0.000000f, 0.000000f, 0.000000f,
166+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f};
167+ 
168+ vector<void*> datas = {(void*)image_data, (void*)size_data, (void*)scale_data, (void*)translate_data, (void*)output};
169+ CREATE_NODEDEF(shapes, data_types, datas, "gaussian", true);
170+ RUN_KERNEL(node_def, HOST, KERNEL_STATUS_OK);
171+ 
172+ bool compare = CompareResult(output, output_exp, 24);
173+ EXPECT_EQ(compare, true);
174+}
175+ 
176+TEST_F(TEST_SCALEANDTRANSLATE_UT, DATA_TYPE_INT32_BOX_SUCC) {
177+ vector<DataType> data_types = {DT_INT32, DT_INT32, DT_FLOAT, DT_FLOAT, DT_FLOAT};
178+ vector<int64_t> in_shape = {1, 2, 3, 1};
179+ vector<int64_t> out_shape = {1, 4, 6, 1};
180+ vector<vector<int64_t>> shapes = {in_shape, {2}, {2}, {2}, out_shape};
181+ 
182+ int32_t image_data[6] = {26, 105, 16, 68, 42, 183};
183+ int32_t size_data[2] = {4, 6};
184+ float scale_data[2] = {1.000000f, 1.000000f};
185+ float translate_data[2] = {0.000000f, 0.000000f};
186+ 
187+ float output[24] = {0};
188+ float output_exp[24] = {
189+ 26.000000f, 105.000000f, 16.000000f, 0.000000f, 0.000000f, 0.000000f,
190+ 68.000000f, 42.000000f, 183.000000f, 0.000000f, 0.000000f, 0.000000f,
191+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
192+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f};
193+ 
194+ vector<void*> datas = {(void*)image_data, (void*)size_data, (void*)scale_data, (void*)translate_data, (void*)output};
195+ CREATE_NODEDEF(shapes, data_types, datas, "box", false);
196+ RUN_KERNEL(node_def, HOST, KERNEL_STATUS_OK);
197+ 
198+ bool compare = CompareResult(output, output_exp, 24);
199+ EXPECT_EQ(compare, true);
200+}
201+ 
202+TEST_F(TEST_SCALEANDTRANSLATE_UT, DATA_TYPE_INT32_KEYSCUBIC_SUCC) {
203+ vector<DataType> data_types = {DT_INT32, DT_INT32, DT_FLOAT, DT_FLOAT, DT_FLOAT};
204+ vector<int64_t> in_shape = {1, 2, 3, 1};
205+ vector<int64_t> out_shape = {1, 4, 6, 1};
206+ vector<vector<int64_t>> shapes = {in_shape, {2}, {2}, {2}, out_shape};
207+ 
208+ int32_t image_data[6] = {0, 41, 0, 97, 100, 245};
209+ int32_t size_data[2] = {4, 6};
210+ float scale_data[2] = {1.300000f, 1.200000f};
211+ float translate_data[2] = {0.200000f, 0.100000f};
212+ 
213+ float output[24] = {0};
214+ float output_exp[24] = {
215+ -11.912914f, 25.384739f, 7.328219f, -28.820704f, 0.000000f, 0.000000f,
216+ 47.052631f, 59.714275f, 99.323532f, 127.973701f, 0.000000f, 0.000000f,
217+ 106.018173f, 94.043808f, 191.318848f, 284.768097f, 0.000000f, 0.000000f,
218+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f};
219+ 
220+ vector<void*> datas = {(void*)image_data, (void*)size_data, (void*)scale_data, (void*)translate_data, (void*)output};
221+ CREATE_NODEDEF(shapes, data_types, datas, "keyscubic", false);
222+ RUN_KERNEL(node_def, HOST, KERNEL_STATUS_OK);
223+ 
224+ bool compare = CompareResult(output, output_exp, 24);
225+ EXPECT_EQ(compare, true);
226+}
227+ 
228+TEST_F(TEST_SCALEANDTRANSLATE_UT, DATA_TYPE_INT32_MITCHELLCUBIC_SUCC) {
229+ vector<DataType> data_types = {DT_INT32, DT_INT32, DT_FLOAT, DT_FLOAT, DT_FLOAT};
230+ vector<int64_t> in_shape = {1, 2, 3, 1};
231+ vector<int64_t> out_shape = {1, 4, 6, 1};
232+ vector<vector<int64_t>> shapes = {in_shape, {2}, {2}, {2}, out_shape};
233+ 
234+ int32_t image_data[6] = {147, 151, 60, 204, 40, 169};
235+ int32_t size_data[2] = {4, 6};
236+ float scale_data[2] = {1.000000f, 1.500000f};
237+ float translate_data[2] = {0.100000f, 0.000000f};
238+ 
239+ float output[24] = {0};
240+ float output_exp[24] = {
241+ 147.859848f, 151.504288f, 134.076508f, 76.278763f, 55.579456f, 0.000000f,
242+ 198.232605f, 124.231392f, 70.288658f, 137.711273f, 162.962631f, 0.000000f,
243+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
244+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f};
245+ 
246+ vector<void*> datas = {(void*)image_data, (void*)size_data, (void*)scale_data, (void*)translate_data, (void*)output};
247+ CREATE_NODEDEF(shapes, data_types, datas, "mitchellcubic", false);
248+ RUN_KERNEL(node_def, HOST, KERNEL_STATUS_OK);
249+ 
250+ bool compare = CompareResult(output, output_exp, 24);
251+ EXPECT_EQ(compare, true);
252+}
253+ 
254+TEST_F(TEST_SCALEANDTRANSLATE_UT, DATA_TYPE_INT32_GAUSSIAN_SUCC) {
255+ vector<DataType> data_types = {DT_INT32, DT_INT32, DT_FLOAT, DT_FLOAT, DT_FLOAT};
256+ vector<int64_t> in_shape = {1, 2, 3, 1};
257+ vector<int64_t> out_shape = {1, 4, 6, 1};
258+ vector<vector<int64_t>> shapes = {in_shape, {2}, {2}, {2}, out_shape};
259+ 
260+ int32_t image_data[6] = {108, 133, 220, 146, 8, 81};
261+ int32_t size_data[2] = {4, 6};
262+ float scale_data[2] = {1.500000f, 1.300000f};
263+ float translate_data[2] = {0.000000f, 0.200000f};
264+ 
265+ float output[24] = {0};
266+ float output_exp[24] = {
267+ 111.103859f, 117.673843f, 148.115021f, 202.018265f, 0.000000f, 0.000000f,
268+ 124.510078f, 98.750000f, 94.324577f, 142.182220f, 0.000000f, 0.000000f,
269+ 137.916306f, 79.826157f, 40.534134f, 82.346161f, 0.000000f, 0.000000f,
270+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f};
271+ 
272+ vector<void*> datas = {(void*)image_data, (void*)size_data, (void*)scale_data, (void*)translate_data, (void*)output};
273+ CREATE_NODEDEF(shapes, data_types, datas, "gaussian", false);
274+ RUN_KERNEL(node_def, HOST, KERNEL_STATUS_OK);
275+ 
276+ bool compare = CompareResult(output, output_exp, 24);
277+ EXPECT_EQ(compare, true);
278+}
279+ 
280+TEST_F(TEST_SCALEANDTRANSLATE_UT, DATA_TYPE_INT32_LANCZOS1_SUCC) {
281+ vector<DataType> data_types = {DT_INT32, DT_INT32, DT_FLOAT, DT_FLOAT, DT_FLOAT};
282+ vector<int64_t> in_shape = {1, 2, 3, 1};
283+ vector<int64_t> out_shape = {1, 4, 6, 1};
284+ vector<vector<int64_t>> shapes = {in_shape, {2}, {2}, {2}, out_shape};
285+ 
286+ int32_t image_data[6] = {65, 252, 245, 13, 229, 26};
287+ int32_t size_data[2] = {4, 6};
288+ float scale_data[2] = {1.000000f, 1.000000f};
289+ float translate_data[2] = {0.000000f, 0.000000f};
290+ 
291+ float output[24] = {0};
292+ float output_exp[24] = {
293+ 65.000000f, 252.000000f, 245.000000f, 0.000000f, 0.000000f, 0.000000f,
294+ 13.000000f, 229.000000f, 26.000000f, 0.000000f, 0.000000f, 0.000000f,
295+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
296+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f};
297+ 
298+ vector<void*> datas = {(void*)image_data, (void*)size_data, (void*)scale_data, (void*)translate_data, (void*)output};
299+ CREATE_NODEDEF(shapes, data_types, datas, "lanczos1", true);
300+ RUN_KERNEL(node_def, HOST, KERNEL_STATUS_OK);
301+ 
302+ bool compare = CompareResult(output, output_exp, 24);
303+ EXPECT_EQ(compare, true);
304+}
305+ 
306+TEST_F(TEST_SCALEANDTRANSLATE_UT, DATA_TYPE_INT64_LANCZOS1_SUCC) {
307+ vector<DataType> data_types = {DT_INT64, DT_INT32, DT_FLOAT, DT_FLOAT, DT_FLOAT};
308+ vector<int64_t> in_shape = {1, 2, 3, 1};
309+ vector<int64_t> out_shape = {1, 4, 6, 1};
310+ vector<vector<int64_t>> shapes = {in_shape, {2}, {2}, {2}, out_shape};
311+ 
312+ int64_t image_data[6] = {66, 36, 238, 184, 221, 148};
313+ int32_t size_data[2] = {4, 6};
314+ float scale_data[2] = {1.200000f, 1.000000f};
315+ float translate_data[2] = {0.100000f, 0.100000f};
316+ 
317+ float output[24] = {0};
318+ float output_exp[24] = {
319+ 66.000000f, 36.365852f, 235.536621f, 0.000000f, 0.000000f, 0.000000f,
320+ 160.399994f, 183.712189f, 166.219543f, 0.000000f, 0.000000f, 0.000000f,
321+ 184.000000f, 220.548782f, 148.890259f, 0.000000f, 0.000000f, 0.000000f,
322+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f};
323+ 
324+ vector<void*> datas = {(void*)image_data, (void*)size_data, (void*)scale_data, (void*)translate_data, (void*)output};
325+ CREATE_NODEDEF(shapes, data_types, datas, "lanczos1", false);
326+ RUN_KERNEL(node_def, HOST, KERNEL_STATUS_OK);
327+ 
328+ bool compare = CompareResult(output, output_exp, 24);
329+ EXPECT_EQ(compare, true);
330+}
331+ 
332+TEST_F(TEST_SCALEANDTRANSLATE_UT, DATA_TYPE_INT16_LANCZOS3_SUCC) {
333+ vector<DataType> data_types = {DT_INT16, DT_INT32, DT_FLOAT, DT_FLOAT, DT_FLOAT};
334+ vector<int64_t> in_shape = {1, 2, 3, 1};
335+ vector<int64_t> out_shape = {1, 4, 6, 1};
336+ vector<vector<int64_t>> shapes = {in_shape, {2}, {2}, {2}, out_shape};
337+ 
338+ int16_t image_data[6] = {21, 210, 200, 164, 62, 202};
339+ int32_t size_data[2] = {4, 6};
340+ float scale_data[2] = {1.000000f, 1.200000f};
341+ float translate_data[2] = {0.000000f, 0.100000f};
342+ 
343+ float output[24] = {0};
344+ float output_exp[24] = {
345+ 3.307576f, 142.551056f, 228.000000f, 189.905411f, 0.000000f, 0.000000f,
346+ 177.385513f, 79.621498f, 128.000000f, 229.652969f, 0.000000f, 0.000000f,
347+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
348+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f};
349+ 
350+ vector<void*> datas = {(void*)image_data, (void*)size_data, (void*)scale_data, (void*)translate_data, (void*)output};
351+ CREATE_NODEDEF(shapes, data_types, datas, "lanczos3", false);
352+ RUN_KERNEL(node_def, HOST, KERNEL_STATUS_OK);
353+ 
354+ bool compare = CompareResult(output, output_exp, 24);
355+ EXPECT_EQ(compare, true);
356+}
357+ 
358+TEST_F(TEST_SCALEANDTRANSLATE_UT, DATA_TYPE_UINT16_LANCZOS3_SUCC) {
359+ vector<DataType> data_types = {DT_UINT16, DT_INT32, DT_FLOAT, DT_FLOAT, DT_FLOAT};
360+ vector<int64_t> in_shape = {1, 2, 3, 1};
361+ vector<int64_t> out_shape = {1, 4, 6, 1};
362+ vector<vector<int64_t>> shapes = {in_shape, {2}, {2}, {2}, out_shape};
363+ 
364+ uint16_t image_data[6] = {6, 50, 181, 160, 78, 1};
365+ int32_t size_data[2] = {4, 6};
366+ float scale_data[2] = {1.000000f, 1.000000f};
367+ float translate_data[2] = {0.200000f, 0.000000f};
368+ 
369+ float output[24] = {0};
370+ float output_exp[24] = {
371+ -16.416292f, 45.924309f, 207.200882f, 0.000000f, 0.000000f, 0.000000f,
372+ 131.879150f, 72.887115f, 33.868526f, 0.000000f, 0.000000f, 0.000000f,
373+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
374+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f};
375+ 
376+ vector<void*> datas = {(void*)image_data, (void*)size_data, (void*)scale_data, (void*)translate_data, (void*)output};
377+ CREATE_NODEDEF(shapes, data_types, datas, "lanczos3", false);
378+ RUN_KERNEL(node_def, HOST, KERNEL_STATUS_OK);
379+ 
380+ bool compare = CompareResult(output, output_exp, 24);
381+ EXPECT_EQ(compare, true);
382+}
383+ 
384+TEST_F(TEST_SCALEANDTRANSLATE_UT, DATA_TYPE_FLOAT_LANCZOS3_SUCC) {
385+ vector<DataType> data_types = {DT_FLOAT, DT_INT32, DT_FLOAT, DT_FLOAT, DT_FLOAT};
386+ vector<int64_t> in_shape = {1, 2, 3, 1};
387+ vector<int64_t> out_shape = {1, 4, 6, 1};
388+ vector<vector<int64_t>> shapes = {in_shape, {2}, {2}, {2}, out_shape};
389+ 
390+ float image_data[6] = {28.281147f, 206.032852f, 17.464172f, 244.885483f, 249.871445f, 92.243668f};
391+ int32_t size_data[2] = {4, 6};
392+ float scale_data[2] = {1.500000f, 1.500000f};
393+ float translate_data[2] = {0.000000f, 0.000000f};
394+ 
395+ float output[24] = {0};
396+ float output_exp[24] = {
397+ -22.442028f, 112.591362f, 189.377502f, 38.449009f, -44.437092f, 0.000000f,
398+ 123.233429f, 198.194443f, 208.764771f, 78.613449f, 11.813992f, 0.000000f,
399+ 268.908905f, 283.797546f, 228.152069f, 118.777908f, 68.065079f, 0.000000f,
400+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f};
401+ 
402+ vector<void*> datas = {(void*)image_data, (void*)size_data, (void*)scale_data, (void*)translate_data, (void*)output};
403+ CREATE_NODEDEF(shapes, data_types, datas, "lanczos3", true);
404+ RUN_KERNEL(node_def, HOST, KERNEL_STATUS_OK);
405+ 
406+ bool compare = CompareResult(output, output_exp, 24);
407+ EXPECT_EQ(compare, true);
408+}
409+ 
410+TEST_F(TEST_SCALEANDTRANSLATE_UT, DATA_TYPE_INT8_LANCZOS5_SUCC) {
411+ vector<DataType> data_types = {DT_INT8, DT_INT32, DT_FLOAT, DT_FLOAT, DT_FLOAT};
412+ vector<int64_t> in_shape = {1, 2, 3, 1};
413+ vector<int64_t> out_shape = {1, 4, 6, 1};
414+ vector<vector<int64_t>> shapes = {in_shape, {2}, {2}, {2}, out_shape};
415+ 
416+ int8_t image_data[6] = {-34, 125, -16, -95, 71, -22};
417+ int32_t size_data[2] = {4, 6};
418+ float scale_data[2] = {1.000000f, 1.000000f};
419+ float translate_data[2] = {0.100000f, 0.200000f};
420+ 
421+ float output[24] = {0};
422+ float output_exp[24] = {
423+ -53.807579f, 115.260719f, 15.897320f, 0.000000f, 0.000000f, 0.000000f,
424+ -111.851692f, 53.257767f, 4.182123f, 0.000000f, 0.000000f, 0.000000f,
425+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
426+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f};
427+ 
428+ vector<void*> datas = {(void*)image_data, (void*)size_data, (void*)scale_data, (void*)translate_data, (void*)output};
429+ CREATE_NODEDEF(shapes, data_types, datas, "lanczos5", true);
430+ RUN_KERNEL(node_def, HOST, KERNEL_STATUS_OK);
431+ 
432+ bool compare = CompareResult(output, output_exp, 24);
433+ EXPECT_EQ(compare, true);
434+}
435+ 
436+TEST_F(TEST_SCALEANDTRANSLATE_UT, DATA_TYPE_UINT8_LANCZOS5_SUCC) {
437+ vector<DataType> data_types = {DT_UINT8, DT_INT32, DT_FLOAT, DT_FLOAT, DT_FLOAT};
438+ vector<int64_t> in_shape = {1, 2, 3, 1};
439+ vector<int64_t> out_shape = {1, 4, 6, 1};
440+ vector<vector<int64_t>> shapes = {in_shape, {2}, {2}, {2}, out_shape};
441+ 
442+ uint8_t image_data[6] = {10, 103, 236, 133, 134, 100};
443+ int32_t size_data[2] = {4, 6};
444+ float scale_data[2] = {1.300000f, 1.000000f};
445+ float translate_data[2] = {0.000000f, 0.100000f};
446+ 
447+ float output[24] = {0};
448+ float output_exp[24] = {
449+ -2.695577f, 76.776100f, 245.176254f, 0.000000f, 0.000000f, 0.000000f,
450+ 90.168655f, 118.175423f, 146.308121f, 0.000000f, 0.000000f, 0.000000f,
451+ 174.934570f, 155.964462f, 56.061882f, 0.000000f, 0.000000f, 0.000000f,
452+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f};
453+ 
454+ vector<void*> datas = {(void*)image_data, (void*)size_data, (void*)scale_data, (void*)translate_data, (void*)output};
455+ CREATE_NODEDEF(shapes, data_types, datas, "lanczos5", true);
456+ RUN_KERNEL(node_def, HOST, KERNEL_STATUS_OK);
457+ 
458+ bool compare = CompareResult(output, output_exp, 24);
459+ EXPECT_EQ(compare, true);
460+}
461+ 
462+TEST_F(TEST_SCALEANDTRANSLATE_UT, DATA_TYPE_DOUBLE_TRIANGLE_SUCC) {
463+ vector<DataType> data_types = {DT_DOUBLE, DT_INT32, DT_FLOAT, DT_FLOAT, DT_FLOAT};
464+ vector<int64_t> in_shape = {1, 2, 3, 1};
465+ vector<int64_t> out_shape = {1, 4, 6, 1};
466+ vector<vector<int64_t>> shapes = {in_shape, {2}, {2}, {2}, out_shape};
467+ 
468+ double image_data[6] = {199.2488598334, 176.6713594530, 247.2630374143, 8.2623258913, 249.9158586850, 76.1476041631};
469+ int32_t size_data[2] = {4, 6};
470+ float scale_data[2] = {1.000000f, 1.000000f};
471+ float translate_data[2] = {0.000000f, 0.000000f};
472+ 
473+ float output[24] = {0};
474+ float output_exp[24] = {
475+ 199.248856f, 176.671356f, 247.263031f, 0.000000f, 0.000000f, 0.000000f,
476+ 8.262326f, 249.915863f, 76.147606f, 0.000000f, 0.000000f, 0.000000f,
477+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
478+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f};
479+ 
480+ vector<void*> datas = {(void*)image_data, (void*)size_data, (void*)scale_data, (void*)translate_data, (void*)output};
481+ CREATE_NODEDEF(shapes, data_types, datas, "triangle", false);
482+ RUN_KERNEL(node_def, HOST, KERNEL_STATUS_OK);
483+ 
484+ bool compare = CompareResult(output, output_exp, 24);
485+ EXPECT_EQ(compare, true);
486+}
487+ 
488+TEST_F(TEST_SCALEANDTRANSLATE_UT, DATA_TYPE_FLOAT16_TRIANGLE_SUCC) {
489+ vector<DataType> data_types = {DT_FLOAT16, DT_INT32, DT_FLOAT, DT_FLOAT, DT_FLOAT};
490+ vector<int64_t> in_shape = {1, 2, 3, 1};
491+ vector<int64_t> out_shape = {1, 4, 6, 1};
492+ vector<vector<int64_t>> shapes = {in_shape, {2}, {2}, {2}, out_shape};
493+ 
494+ Eigen::half image_data[6] = {Eigen::half(59.3750f), Eigen::half(232.5000f), Eigen::half(13.0156f), Eigen::half(2.5527f), Eigen::half(79.8750f), Eigen::half(77.2500f)};
495+ int32_t size_data[2] = {4, 6};
496+ float scale_data[2] = {1.200000f, 1.200000f};
497+ float translate_data[2] = {0.100000f, 0.100000f};
498+ 
499+ float output[24] = {0};
500+ float output_exp[24] = {
501+ 59.375000f, 174.791656f, 122.757812f, 13.015625f, 0.000000f, 0.000000f,
502+ 21.493492f, 94.331161f, 93.294266f, 55.838539f, 0.000000f, 0.000000f,
503+ 2.552734f, 54.100910f, 78.562500f, 77.250000f, 0.000000f, 0.000000f,
504+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f};
505+ 
506+ vector<void*> datas = {(void*)image_data, (void*)size_data, (void*)scale_data, (void*)translate_data, (void*)output};
507+ CREATE_NODEDEF(shapes, data_types, datas, "triangle", false);
508+ RUN_KERNEL(node_def, HOST, KERNEL_STATUS_OK);
509+ 
510+ bool compare = CompareResult(output, output_exp, 24);
511+ EXPECT_EQ(compare, true);
512+}
513+ 
514+TEST_F(TEST_SCALEANDTRANSLATE_UT, DATA_TYPE_FLOAT_METHOD_BOX_SUCC) {
515+ std::vector<float> data;
516+ vector<DataType> data_types = {DT_FLOAT, DT_INT32, DT_FLOAT, DT_FLOAT, DT_FLOAT};
517+ int64_t kBatchSize_exp = 2;
518+ int64_t kNumRowSquares_exp = 16;
519+ int64_t kNumColSquares_exp = 13;
520+ int64_t kSquareSize_exp = 12;
521+ int64_t kNumChannels_exp = 3;
522+ 
523+ SetCheckerboardImageInput<float> (kBatchSize_exp, kNumRowSquares_exp, kNumColSquares_exp,
524+ kSquareSize_exp, kNumChannels_exp, data);
525+ vector<int64_t> datashape = {kBatchSize_exp, kNumRowSquares_exp * kSquareSize_exp,
526+ kNumColSquares_exp * kSquareSize_exp, kNumChannels_exp};
527+ 
528+ const int kOutputImageHeight_exp = kNumRowSquares_exp * kSquareSize_exp;
529+ const int kOutputImageWidth_exp = kNumColSquares_exp * kSquareSize_exp;
530+ 
531+ float scale_data[2] = {0.5, 0.5};
532+ 
533+ float translate_data[2] = {0.5, 0.5};
534+ int size_data[2] = {kOutputImageHeight_exp, kOutputImageWidth_exp};
535+ vector<int64_t> sizeshape ={2};
536+ const int outputshape= kBatchSize_exp* kOutputImageHeight_exp * kOutputImageWidth_exp * kNumChannels_exp;
537+ float* output = new float[outputshape];
538+ 
539+ vector<vector<int64_t>> shapes = {datashape, sizeshape, {2}, {2}, {kBatchSize_exp, kOutputImageHeight_exp, kOutputImageWidth_exp, kNumChannels_exp}};
540+ 
541+ float* data_arr = new float[data.size()];
542+ 
543+ std::copy(data.begin(), data.end(), data_arr);
544+ 
545+ vector<void *> datas = {(void *)data_arr, (void *)size_data, (void *)scale_data, (void *)translate_data, (void *)output};
546+ std::string kernel_type_str = "box";
547+ bool antialias = false;
548+ CREATE_NODEDEF(shapes, data_types, datas, kernel_type_str, antialias);
549+ RUN_KERNEL(node_def, HOST, KERNEL_STATUS_OK);
550+ delete [] data_arr;
551+ delete [] output;
552+}
553+ 
554+TEST_F(TEST_SCALEANDTRANSLATE_UT, DATA_TYPE_FLOAT_METHOD_LANCZOS1_SUCC) {
555+ std::vector<float> data;
556+ vector<DataType> data_types = {DT_FLOAT, DT_INT32, DT_FLOAT, DT_FLOAT, DT_FLOAT};
557+ int64_t kBatchSize_exp = 4;
558+ int64_t kNumRowSquares_exp = 20;
559+ int64_t kNumColSquares_exp = 15;
560+ int64_t kSquareSize_exp = 13;
561+ int64_t kNumChannels_exp = 3;
562+ 
563+ SetCheckerboardImageInput<float> (kBatchSize_exp, kNumRowSquares_exp, kNumColSquares_exp,
564+ kSquareSize_exp, kNumChannels_exp, data);
565+ vector<int64_t> datashape = {kBatchSize_exp, kNumRowSquares_exp * kSquareSize_exp,
566+ kNumColSquares_exp * kSquareSize_exp, kNumChannels_exp};
567+ 
568+ const int kOutputImageHeight_exp = kNumRowSquares_exp * kSquareSize_exp;
569+ const int kOutputImageWidth_exp = kNumColSquares_exp * kSquareSize_exp;
570+ 
571+ float scale_data[2] = {0.5, 0.5};
572+ 
573+ float translate_data[2] = {0.5, 0.5};
574+ int size_data[2] = {kOutputImageHeight_exp, kOutputImageWidth_exp};
575+ vector<int64_t> sizeshape ={2};
576+ const int outputshape= kBatchSize_exp* kOutputImageHeight_exp * kOutputImageWidth_exp * kNumChannels_exp;
577+ float* output = new float[outputshape];
578+ 
579+ vector<vector<int64_t>> shapes = {datashape, sizeshape, {2}, {2}, {kBatchSize_exp, kOutputImageHeight_exp, kOutputImageWidth_exp, kNumChannels_exp}};
580+ 
581+ float* data_arr = new float[data.size()];
582+ 
583+ std::copy(data.begin(), data.end(), data_arr);
584+ 
585+ vector<void *> datas = {(void *)data_arr, (void *)size_data, (void *)scale_data, (void *)translate_data, (void *)output};
586+ std::string kernel_type_str = "lanczos1";
587+ bool antialias = false;
588+ CREATE_NODEDEF(shapes, data_types, datas, kernel_type_str, antialias);
589+ RUN_KERNEL(node_def, HOST, KERNEL_STATUS_OK);
590+ delete [] data_arr;
591+ delete [] output;
592+}
593+ 
594+TEST_F(TEST_SCALEANDTRANSLATE_UT, DATA_TYPE_FLOAT_METHOD_LANCZOS3_SUCC) {
595+ std::vector<float> data;
596+ vector<DataType> data_types = {DT_FLOAT, DT_INT32, DT_FLOAT, DT_FLOAT, DT_FLOAT};
597+ int64_t kBatchSize_exp = 4;
598+ int64_t kNumRowSquares_exp = 20;
599+ int64_t kNumColSquares_exp = 15;
600+ int64_t kSquareSize_exp = 13;
601+ int64_t kNumChannels_exp = 3;
602+ 
603+ SetCheckerboardImageInput<float> (kBatchSize_exp, kNumRowSquares_exp, kNumColSquares_exp,
604+ kSquareSize_exp, kNumChannels_exp, data);
605+ vector<int64_t> datashape = {kBatchSize_exp, kNumRowSquares_exp * kSquareSize_exp,
606+ kNumColSquares_exp * kSquareSize_exp, kNumChannels_exp};
607+ 
608+ const int kOutputImageHeight_exp = kNumRowSquares_exp * kSquareSize_exp;
609+ const int kOutputImageWidth_exp = kNumColSquares_exp * kSquareSize_exp;
610+ 
611+ float scale_data[2] = {0.5, 0.5};
612+ 
613+ float translate_data[2] = {0.5, 0.5};
614+ int size_data[2] = {kOutputImageHeight_exp, kOutputImageWidth_exp};
615+ vector<int64_t> sizeshape ={2};
616+ const int outputshape= kBatchSize_exp* kOutputImageHeight_exp * kOutputImageWidth_exp * kNumChannels_exp;
617+ float* output = new float[outputshape];
618+ 
619+ vector<vector<int64_t>> shapes = {datashape, sizeshape, {2}, {2}, {kBatchSize_exp, kOutputImageHeight_exp, kOutputImageWidth_exp, kNumChannels_exp}};
620+ 
621+ float* data_arr = new float[data.size()];
622+ 
623+ std::copy(data.begin(), data.end(), data_arr);
624+ 
625+ vector<void *> datas = {(void *)data_arr, (void *)size_data, (void *)scale_data, (void *)translate_data, (void *)output};
626+ std::string kernel_type_str = "lanczos3";
627+ bool antialias = false;
628+ CREATE_NODEDEF(shapes, data_types, datas, kernel_type_str, antialias);
629+ RUN_KERNEL(node_def, HOST, KERNEL_STATUS_OK);
630+ delete [] data_arr;
631+ delete [] output;
632+}
633+ 
634+TEST_F(TEST_SCALEANDTRANSLATE_UT, DATA_TYPE_FLOAT_METHOD_LANCZOS5_SUCC) {
635+ std::vector<float> data;
636+ vector<DataType> data_types = {DT_FLOAT, DT_INT32, DT_FLOAT, DT_FLOAT, DT_FLOAT};
637+ int64_t kBatchSize_exp = 4;
638+ int64_t kNumRowSquares_exp = 20;
639+ int64_t kNumColSquares_exp = 15;
640+ int64_t kSquareSize_exp = 13;
641+ int64_t kNumChannels_exp = 3;
642+ 
643+ SetCheckerboardImageInput<float> (kBatchSize_exp, kNumRowSquares_exp, kNumColSquares_exp,
644+ kSquareSize_exp, kNumChannels_exp, data);
645+ vector<int64_t> datashape = {kBatchSize_exp, kNumRowSquares_exp * kSquareSize_exp,
646+ kNumColSquares_exp * kSquareSize_exp, kNumChannels_exp};
647+ 
648+ const int kOutputImageHeight_exp = kNumRowSquares_exp * kSquareSize_exp;
649+ const int kOutputImageWidth_exp = kNumColSquares_exp * kSquareSize_exp;
650+ 
651+ float scale_data[2] = {0.5, 0.5};
652+ 
653+ float translate_data[2] = {0.5, 0.5};
654+ int size_data[2] = {kOutputImageHeight_exp, kOutputImageWidth_exp};
655+ vector<int64_t> sizeshape ={2};
656+ const int outputshape= kBatchSize_exp* kOutputImageHeight_exp * kOutputImageWidth_exp * kNumChannels_exp;
657+ float* output = new float[outputshape];
658+ 
659+ vector<vector<int64_t>> shapes = {datashape, sizeshape, {2}, {2}, {kBatchSize_exp, kOutputImageHeight_exp, kOutputImageWidth_exp, kNumChannels_exp}};
660+ 
661+ float* data_arr = new float[data.size()];
662+ 
663+ std::copy(data.begin(), data.end(), data_arr);
664+ 
665+ vector<void *> datas = {(void *)data_arr, (void *)size_data, (void *)scale_data, (void *)translate_data, (void *)output};
666+ std::string kernel_type_str = "lanczos5";
667+ bool antialias = false;
668+ CREATE_NODEDEF(shapes, data_types, datas, kernel_type_str, antialias);
669+ RUN_KERNEL(node_def, HOST, KERNEL_STATUS_OK);
670+ delete [] data_arr;
671+ delete [] output;
672+}
673+ 
674+TEST_F(TEST_SCALEANDTRANSLATE_UT, DATA_TYPE_FLOAT_METHOD_GAUSSIAN_SUCC) {
675+ std::vector<float> data;
676+ vector<DataType> data_types = {DT_FLOAT, DT_INT32, DT_FLOAT, DT_FLOAT, DT_FLOAT};
677+ int64_t kBatchSize_exp = 4;
678+ int64_t kNumRowSquares_exp = 20;
679+ int64_t kNumColSquares_exp = 15;
680+ int64_t kSquareSize_exp = 13;
681+ int64_t kNumChannels_exp = 3;
682+ 
683+ SetCheckerboardImageInput<float> (kBatchSize_exp, kNumRowSquares_exp, kNumColSquares_exp,
684+ kSquareSize_exp, kNumChannels_exp, data);
685+ vector<int64_t> datashape = {kBatchSize_exp, kNumRowSquares_exp * kSquareSize_exp,
686+ kNumColSquares_exp * kSquareSize_exp, kNumChannels_exp};
687+ 
688+ const int kOutputImageHeight_exp = kNumRowSquares_exp * kSquareSize_exp;
689+ const int kOutputImageWidth_exp = kNumColSquares_exp * kSquareSize_exp;
690+ 
691+ float scale_data[2] = {0.5, 0.5};
692+ 
693+ float translate_data[2] = {0.5, 0.5};
694+ int size_data[2] = {kOutputImageHeight_exp, kOutputImageWidth_exp};
695+ vector<int64_t> sizeshape ={2};
696+ const int outputshape= kBatchSize_exp* kOutputImageHeight_exp * kOutputImageWidth_exp * kNumChannels_exp;
697+ float* output = new float[outputshape];
698+ 
699+ vector<vector<int64_t>> shapes = {datashape, sizeshape, {2}, {2}, {kBatchSize_exp, kOutputImageHeight_exp, kOutputImageWidth_exp, kNumChannels_exp}};
700+ 
701+ float* data_arr = new float[data.size()];
702+ 
703+ std::copy(data.begin(), data.end(), data_arr);
704+ 
705+ vector<void *> datas = {(void *)data_arr, (void *)size_data, (void *)scale_data, (void *)translate_data, (void *)output};
706+ std::string kernel_type_str = "gaussian";
707+ bool antialias = false;
708+ CREATE_NODEDEF(shapes, data_types, datas, kernel_type_str, antialias);
709+ RUN_KERNEL(node_def, HOST, KERNEL_STATUS_OK);
710+ delete [] data_arr;
711+ delete [] output;
712+}
713+ 
714+TEST_F(TEST_SCALEANDTRANSLATE_UT, DATA_TYPE_FLOAT_METHOD_TRIANGLE_SUCC) {
715+ std::vector<float> data;
716+ vector<DataType> data_types = {DT_FLOAT, DT_INT32, DT_FLOAT, DT_FLOAT, DT_FLOAT};
717+ int64_t kBatchSize_exp = 4;
718+ int64_t kNumRowSquares_exp = 20;
719+ int64_t kNumColSquares_exp = 15;
720+ int64_t kSquareSize_exp = 13;
721+ int64_t kNumChannels_exp = 3;
722+ 
723+ SetCheckerboardImageInput<float> (kBatchSize_exp, kNumRowSquares_exp, kNumColSquares_exp,
724+ kSquareSize_exp, kNumChannels_exp, data);
725+ vector<int64_t> datashape = {kBatchSize_exp, kNumRowSquares_exp * kSquareSize_exp,
726+ kNumColSquares_exp * kSquareSize_exp, kNumChannels_exp};
727+ 
728+ const int kOutputImageHeight_exp = kNumRowSquares_exp * kSquareSize_exp;
729+ const int kOutputImageWidth_exp = kNumColSquares_exp * kSquareSize_exp;
730+ 
731+ float scale_data[2] = {0.5, 0.5};
732+ 
733+ float translate_data[2] = {0.5, 0.5};
734+ int size_data[2] = {kOutputImageHeight_exp, kOutputImageWidth_exp};
735+ vector<int64_t> sizeshape ={2};
736+ const int outputshape= kBatchSize_exp* kOutputImageHeight_exp * kOutputImageWidth_exp * kNumChannels_exp;
737+ float* output = new float[outputshape];
738+ 
739+ vector<vector<int64_t>> shapes = {datashape, sizeshape, {2}, {2}, {kBatchSize_exp, kOutputImageHeight_exp, kOutputImageWidth_exp, kNumChannels_exp}};
740+ 
741+ float* data_arr = new float[data.size()];
742+ 
743+ std::copy(data.begin(), data.end(), data_arr);
744+ 
745+ vector<void *> datas = {(void *)data_arr, (void *)size_data, (void *)scale_data, (void *)translate_data, (void *)output};
746+ std::string kernel_type_str = "triangle";
747+ bool antialias = false;
748+ CREATE_NODEDEF(shapes, data_types, datas, kernel_type_str, antialias);
749+ RUN_KERNEL(node_def, HOST, KERNEL_STATUS_OK);
750+ delete [] data_arr;
751+ delete [] output;
752+}
753+TEST_F(TEST_SCALEANDTRANSLATE_UT, DATA_TYPE_FLOAT_METHOD_KEYSCUBIC_SUCC) {
754+ std::vector<float> data;
755+ vector<DataType> data_types = {DT_FLOAT, DT_INT32, DT_FLOAT, DT_FLOAT, DT_FLOAT};
756+ int64_t kBatchSize_exp = 4;
757+ int64_t kNumRowSquares_exp = 20;
758+ int64_t kNumColSquares_exp = 15;
759+ int64_t kSquareSize_exp = 13;
760+ int64_t kNumChannels_exp = 3;
761+ 
762+ SetCheckerboardImageInput<float> (kBatchSize_exp, kNumRowSquares_exp, kNumColSquares_exp,
763+ kSquareSize_exp, kNumChannels_exp, data);
764+ vector<int64_t> datashape = {kBatchSize_exp, kNumRowSquares_exp * kSquareSize_exp,
765+ kNumColSquares_exp * kSquareSize_exp, kNumChannels_exp};
766+ 
767+ const int kOutputImageHeight_exp = kNumRowSquares_exp * kSquareSize_exp;
768+ const int kOutputImageWidth_exp = kNumColSquares_exp * kSquareSize_exp;
769+ 
770+ float scale_data[2] = {0.5, 0.5};
771+ 
772+ float translate_data[2] = {0.5, 0.5};
773+ int size_data[2] = {kOutputImageHeight_exp, kOutputImageWidth_exp};
774+ vector<int64_t> sizeshape ={2};
775+ const int outputshape= kBatchSize_exp* kOutputImageHeight_exp * kOutputImageWidth_exp * kNumChannels_exp;
776+ float* output = new float[outputshape];
777+ 
778+ vector<vector<int64_t>> shapes = {datashape, sizeshape, {2}, {2}, {kBatchSize_exp, kOutputImageHeight_exp, kOutputImageWidth_exp, kNumChannels_exp}};
779+ 
780+ float* data_arr = new float[data.size()];
781+ 
782+ std::copy(data.begin(), data.end(), data_arr);
783+ 
784+ vector<void *> datas = {(void *)data_arr, (void *)size_data, (void *)scale_data, (void *)translate_data, (void *)output};
785+ std::string kernel_type_str = "keyscubic";
786+ bool antialias = false;
787+ CREATE_NODEDEF(shapes, data_types, datas, kernel_type_str, antialias);
788+ RUN_KERNEL(node_def, HOST, KERNEL_STATUS_OK);
789+ delete [] data_arr;
790+ delete [] output;
791+}
792+TEST_F(TEST_SCALEANDTRANSLATE_UT, DATA_TYPE_FLOAT_METHOD_MITCHELLCUBIC_SUCC) {
793+ std::vector<float> data;
794+ vector<DataType> data_types = {DT_FLOAT, DT_INT32, DT_FLOAT, DT_FLOAT, DT_FLOAT};
795+ int64_t kBatchSize_exp = 4;
796+ int64_t kNumRowSquares_exp = 20;
797+ int64_t kNumColSquares_exp = 15;
798+ int64_t kSquareSize_exp = 13;
799+ int64_t kNumChannels_exp = 3;
800+ 
801+ SetCheckerboardImageInput<float> (kBatchSize_exp, kNumRowSquares_exp, kNumColSquares_exp,
802+ kSquareSize_exp, kNumChannels_exp, data);
803+ vector<int64_t> datashape = {kBatchSize_exp, kNumRowSquares_exp * kSquareSize_exp,
804+ kNumColSquares_exp * kSquareSize_exp, kNumChannels_exp};
805+ 
806+ const int kOutputImageHeight_exp = kNumRowSquares_exp * kSquareSize_exp;
807+ const int kOutputImageWidth_exp = kNumColSquares_exp * kSquareSize_exp;
808+ 
809+ float scale_data[2] = {0.5, 0.5};
810+ 
811+ float translate_data[2] = {0.5, 0.5};
812+ int size_data[2] = {kOutputImageHeight_exp, kOutputImageWidth_exp};
813+ vector<int64_t> sizeshape ={2};
814+ const int outputshape= kBatchSize_exp* kOutputImageHeight_exp * kOutputImageWidth_exp * kNumChannels_exp;
815+ float* output = new float[outputshape];
816+ 
817+ vector<vector<int64_t>> shapes = {datashape, sizeshape, {2}, {2}, {kBatchSize_exp, kOutputImageHeight_exp, kOutputImageWidth_exp, kNumChannels_exp}};
818+ 
819+ float* data_arr = new float[data.size()];
820+ 
821+ std::copy(data.begin(), data.end(), data_arr);
822+ 
823+ vector<void *> datas = {(void *)data_arr, (void *)size_data, (void *)scale_data, (void *)translate_data, (void *)output};
824+ std::string kernel_type_str = "mitchellcubic";
825+ bool antialias = false;
826+ CREATE_NODEDEF(shapes, data_types, datas, kernel_type_str, antialias);
827+ RUN_KERNEL(node_def, HOST, KERNEL_STATUS_OK);
828+ delete [] data_arr;
829+ delete [] output;
830+}
831+ 
832+TEST_F(TEST_SCALEANDTRANSLATE_UT, DATA_TYPE_INT8_METHOD_BOX_SUCC) {
833+ std::vector<int8_t> data;
834+ vector<DataType> data_types = {DT_INT8, DT_INT32, DT_FLOAT, DT_FLOAT, DT_FLOAT};
835+ int64_t kBatchSize_exp = 2;
836+ int64_t kNumRowSquares_exp = 16;
837+ int64_t kNumColSquares_exp = 13;
838+ int64_t kSquareSize_exp = 12;
839+ int64_t kNumChannels_exp = 3;
840+ 
841+ SetCheckerboardImageInput<int8_t> (kBatchSize_exp, kNumRowSquares_exp, kNumColSquares_exp,
842+ kSquareSize_exp, kNumChannels_exp, data);
843+ vector<int64_t> datashape = {kBatchSize_exp, kNumRowSquares_exp * kSquareSize_exp,
844+ kNumColSquares_exp * kSquareSize_exp, kNumChannels_exp};
845+ 
846+ const int kOutputImageHeight_exp = kNumRowSquares_exp * kSquareSize_exp;
847+ const int kOutputImageWidth_exp = kNumColSquares_exp * kSquareSize_exp;
848+ 
849+ float scale_data[2] = {0.5, 0.5};
850+ 
851+ float translate_data[2] = {0.5, 0.5};
852+ int size_data[2] = {kOutputImageHeight_exp, kOutputImageWidth_exp};
853+ vector<int64_t> sizeshape ={2};
854+ const int outputshape= kBatchSize_exp* kOutputImageHeight_exp * kOutputImageWidth_exp * kNumChannels_exp;
855+ float* output = new float[outputshape];
856+ 
857+ vector<vector<int64_t>> shapes = {datashape, sizeshape, {2}, {2}, {kBatchSize_exp, kOutputImageHeight_exp, kOutputImageWidth_exp, kNumChannels_exp}};
858+ 
859+ int8_t* data_arr = new int8_t[data.size()];
860+ 
861+ std::copy(data.begin(), data.end(), data_arr);
862+ 
863+ vector<void *> datas = {(void *)data_arr, (void *)size_data, (void *)scale_data, (void *)translate_data, (void *)output};
864+ std::string kernel_type_str = "box";
865+ bool antialias = false;
866+ CREATE_NODEDEF(shapes, data_types, datas, kernel_type_str, antialias);
867+ RUN_KERNEL(node_def, HOST, KERNEL_STATUS_OK);
868+ delete [] data_arr;
869+ delete [] output;
870+}
871+ 
872+TEST_F(TEST_SCALEANDTRANSLATE_UT, DATA_TYPE_INT16_METHOD_BOX_SUCC) {
873+ std::vector<int16_t> data;
874+ vector<DataType> data_types = {DT_INT16, DT_INT32, DT_FLOAT, DT_FLOAT, DT_FLOAT};
875+ int64_t kBatchSize_exp = 2;
876+ int64_t kNumRowSquares_exp = 16;
877+ int64_t kNumColSquares_exp = 13;
878+ int64_t kSquareSize_exp = 12;
879+ int64_t kNumChannels_exp = 3;
880+ 
881+ SetCheckerboardImageInput<int16_t> (kBatchSize_exp, kNumRowSquares_exp, kNumColSquares_exp,
882+ kSquareSize_exp, kNumChannels_exp, data);
883+ vector<int64_t> datashape = {kBatchSize_exp, kNumRowSquares_exp * kSquareSize_exp,
884+ kNumColSquares_exp * kSquareSize_exp, kNumChannels_exp};
885+ 
886+ const int kOutputImageHeight_exp = kNumRowSquares_exp * kSquareSize_exp;
887+ const int kOutputImageWidth_exp = kNumColSquares_exp * kSquareSize_exp;
888+ 
889+ float scale_data[2] = {0.5, 0.5};
890+ 
891+ float translate_data[2] = {0.5, 0.5};
892+ int size_data[2] = {kOutputImageHeight_exp, kOutputImageWidth_exp};
893+ vector<int64_t> sizeshape ={2};
894+ const int outputshape= kBatchSize_exp* kOutputImageHeight_exp * kOutputImageWidth_exp * kNumChannels_exp;
895+ float* output = new float[outputshape];
896+ 
897+ vector<vector<int64_t>> shapes = {datashape, sizeshape, {2}, {2}, {kBatchSize_exp, kOutputImageHeight_exp, kOutputImageWidth_exp, kNumChannels_exp}};
898+ 
899+ int16_t* data_arr = new int16_t[data.size()];
900+ 
901+ std::copy(data.begin(), data.end(), data_arr);
902+ 
903+ vector<void *> datas = {(void *)data_arr, (void *)size_data, (void *)scale_data, (void *)translate_data, (void *)output};
904+ std::string kernel_type_str = "box";
905+ bool antialias = false;
906+ CREATE_NODEDEF(shapes, data_types, datas, kernel_type_str, antialias);
907+ RUN_KERNEL(node_def, HOST, KERNEL_STATUS_OK);
908+ delete [] data_arr;
909+ delete [] output;
910+}
911+ 
912+TEST_F(TEST_SCALEANDTRANSLATE_UT, DATA_TYPE_INT32_METHOD_BOX_SUCC) {
913+ std::vector<int32_t> data;
914+ vector<DataType> data_types = {DT_INT32, DT_INT32, DT_FLOAT, DT_FLOAT, DT_FLOAT};
915+ int64_t kBatchSize_exp = 2;
916+ int64_t kNumRowSquares_exp = 16;
917+ int64_t kNumColSquares_exp = 13;
918+ int64_t kSquareSize_exp = 12;
919+ int64_t kNumChannels_exp = 3;
920+ 
921+ SetCheckerboardImageInput<int32_t> (kBatchSize_exp, kNumRowSquares_exp, kNumColSquares_exp,
922+ kSquareSize_exp, kNumChannels_exp, data);
923+ vector<int64_t> datashape = {kBatchSize_exp, kNumRowSquares_exp * kSquareSize_exp,
924+ kNumColSquares_exp * kSquareSize_exp, kNumChannels_exp};
925+ 
926+ const int kOutputImageHeight_exp = kNumRowSquares_exp * kSquareSize_exp;
927+ const int kOutputImageWidth_exp = kNumColSquares_exp * kSquareSize_exp;
928+ 
929+ float scale_data[2] = {0.5, 0.5};
930+ 
931+ float translate_data[2] = {0.5, 0.5};
932+ int size_data[2] = {kOutputImageHeight_exp, kOutputImageWidth_exp};
933+ vector<int64_t> sizeshape ={2};
934+ const int outputshape= kBatchSize_exp* kOutputImageHeight_exp * kOutputImageWidth_exp * kNumChannels_exp;
935+ float* output = new float[outputshape];
936+ 
937+ vector<vector<int64_t>> shapes = {datashape, sizeshape, {2}, {2}, {kBatchSize_exp, kOutputImageHeight_exp, kOutputImageWidth_exp, kNumChannels_exp}};
938+ 
939+ int32_t* data_arr = new int32_t[data.size()];
940+ 
941+ std::copy(data.begin(), data.end(), data_arr);
942+ 
943+ vector<void *> datas = {(void *)data_arr, (void *)size_data, (void *)scale_data, (void *)translate_data, (void *)output};
944+ std::string kernel_type_str = "box";
945+ bool antialias = false;
946+ CREATE_NODEDEF(shapes, data_types, datas, kernel_type_str, antialias);
947+ RUN_KERNEL(node_def, HOST, KERNEL_STATUS_OK);
948+ delete [] data_arr;
949+ delete [] output;
950+ 
951+}
952+ 
953+TEST_F(TEST_SCALEANDTRANSLATE_UT, DATA_TYPE_UINT8_METHOD_BOX_SUCC) {
954+ std::vector<uint8_t> data;
955+ vector<DataType> data_types = {DT_UINT8, DT_INT32, DT_FLOAT, DT_FLOAT, DT_FLOAT};
956+ int64_t kBatchSize_exp = 2;
957+ int64_t kNumRowSquares_exp = 16;
958+ int64_t kNumColSquares_exp = 13;
959+ int64_t kSquareSize_exp = 12;
960+ int64_t kNumChannels_exp = 3;
961+ 
962+ SetCheckerboardImageInput<uint8_t> (kBatchSize_exp, kNumRowSquares_exp, kNumColSquares_exp,
963+ kSquareSize_exp, kNumChannels_exp, data);
964+ vector<int64_t> datashape = {kBatchSize_exp, kNumRowSquares_exp * kSquareSize_exp,
965+ kNumColSquares_exp * kSquareSize_exp, kNumChannels_exp};
966+ 
967+ const int kOutputImageHeight_exp = kNumRowSquares_exp * kSquareSize_exp;
968+ const int kOutputImageWidth_exp = kNumColSquares_exp * kSquareSize_exp;
969+ 
970+ float scale_data[2] = {0.5, 0.5};
971+ 
972+ float translate_data[2] = {0.5, 0.5};
973+ int size_data[2] = {kOutputImageHeight_exp, kOutputImageWidth_exp};
974+ vector<int64_t> sizeshape ={2};
975+ const int outputshape= kBatchSize_exp* kOutputImageHeight_exp * kOutputImageWidth_exp * kNumChannels_exp;
976+ float* output = new float[outputshape];
977+ 
978+ vector<vector<int64_t>> shapes = {datashape, sizeshape, {2}, {2}, {kBatchSize_exp, kOutputImageHeight_exp, kOutputImageWidth_exp, kNumChannels_exp}};
979+ 
980+ uint8_t* data_arr = new uint8_t[data.size()];
981+ 
982+ std::copy(data.begin(), data.end(), data_arr);
983+ 
984+ vector<void *> datas = {(void *)data_arr, (void *)size_data, (void *)scale_data, (void *)translate_data, (void *)output};
985+ std::string kernel_type_str = "box";
986+ bool antialias = false;
987+ CREATE_NODEDEF(shapes, data_types, datas, kernel_type_str, antialias);
988+ RUN_KERNEL(node_def, HOST, KERNEL_STATUS_OK);
989+ delete [] data_arr;
990+ delete [] output;
991+}
992+ 
993+TEST_F(TEST_SCALEANDTRANSLATE_UT, DATA_TYPE_UINT16_METHOD_BOX_SUCC) {
994+ std::vector<uint16_t> data;
995+ vector<DataType> data_types = {DT_UINT16, DT_INT32, DT_FLOAT, DT_FLOAT, DT_FLOAT};
996+ int64_t kBatchSize_exp = 2;
997+ int64_t kNumRowSquares_exp = 16;
998+ int64_t kNumColSquares_exp = 13;
999+ int64_t kSquareSize_exp = 12;
1000+ int64_t kNumChannels_exp = 3;
1001+ 
1002+ SetCheckerboardImageInput<uint16_t> (kBatchSize_exp, kNumRowSquares_exp, kNumColSquares_exp,
1003+ kSquareSize_exp, kNumChannels_exp, data);
1004+ vector<int64_t> datashape = {kBatchSize_exp, kNumRowSquares_exp * kSquareSize_exp,
1005+ kNumColSquares_exp * kSquareSize_exp, kNumChannels_exp};
1006+ 
1007+ const int kOutputImageHeight_exp = kNumRowSquares_exp * kSquareSize_exp;
1008+ const int kOutputImageWidth_exp = kNumColSquares_exp * kSquareSize_exp;
1009+ 
1010+ float scale_data[2] = {0.5, 0.5};
1011+ 
1012+ float translate_data[2] = {0.5, 0.5};
1013+ int size_data[2] = {kOutputImageHeight_exp, kOutputImageWidth_exp};
1014+ vector<int64_t> sizeshape ={2};
1015+ const int outputshape= kBatchSize_exp* kOutputImageHeight_exp * kOutputImageWidth_exp * kNumChannels_exp;
1016+ float* output = new float[outputshape];
1017+ 
1018+ vector<vector<int64_t>> shapes = {datashape, sizeshape, {2}, {2}, {kBatchSize_exp, kOutputImageHeight_exp, kOutputImageWidth_exp, kNumChannels_exp}};
1019+ 
1020+ uint16_t* data_arr = new uint16_t[data.size()];
1021+ 
1022+ std::copy(data.begin(), data.end(), data_arr);
1023+ 
1024+ vector<void *> datas = {(void *)data_arr, (void *)size_data, (void *)scale_data, (void *)translate_data, (void *)output};
1025+ std::string kernel_type_str = "box";
1026+ bool antialias = false;
1027+ CREATE_NODEDEF(shapes, data_types, datas, kernel_type_str, antialias);
1028+ RUN_KERNEL(node_def, HOST, KERNEL_STATUS_OK);
1029+ delete [] data_arr;
1030+ delete [] output;
1031+}
1032+ 
1033+TEST_F(TEST_SCALEANDTRANSLATE_UT, DATA_TYPE_INT64_METHOD_BOX_SUCC) {
1034+ std::vector<int64_t> data;
1035+ vector<DataType> data_types = {DT_INT64, DT_INT32, DT_FLOAT, DT_FLOAT, DT_FLOAT};
1036+ int64_t kBatchSize_exp = 2;
1037+ int64_t kNumRowSquares_exp = 16;
1038+ int64_t kNumColSquares_exp = 13;
1039+ int64_t kSquareSize_exp = 12;
1040+ int64_t kNumChannels_exp = 3;
1041+ 
1042+ SetCheckerboardImageInput<int64_t> (kBatchSize_exp, kNumRowSquares_exp, kNumColSquares_exp,
1043+ kSquareSize_exp, kNumChannels_exp, data);
1044+ vector<int64_t> datashape = {kBatchSize_exp, kNumRowSquares_exp * kSquareSize_exp,
1045+ kNumColSquares_exp * kSquareSize_exp, kNumChannels_exp};
1046+ 
1047+ const int kOutputImageHeight_exp = kNumRowSquares_exp * kSquareSize_exp;
1048+ const int kOutputImageWidth_exp = kNumColSquares_exp * kSquareSize_exp;
1049+ 
1050+ float scale_data[2] = {0.5, 0.5};
1051+ 
1052+ float translate_data[2] = {0.5, 0.5};
1053+ int size_data[2] = {kOutputImageHeight_exp, kOutputImageWidth_exp};
1054+ vector<int64_t> sizeshape ={2};
1055+ const int outputshape= kBatchSize_exp* kOutputImageHeight_exp * kOutputImageWidth_exp * kNumChannels_exp;
1056+ float* output = new float[outputshape];
1057+ 
1058+ vector<vector<int64_t>> shapes = {datashape, sizeshape, {2}, {2}, {kBatchSize_exp, kOutputImageHeight_exp, kOutputImageWidth_exp, kNumChannels_exp}};
1059+ 
1060+ int64_t* data_arr = new int64_t[data.size()];
1061+ 
1062+ std::copy(data.begin(), data.end(), data_arr);
1063+ 
1064+ vector<void *> datas = {(void *)data_arr, (void *)size_data, (void *)scale_data, (void *)translate_data, (void *)output};
1065+ std::string kernel_type_str = "box";
1066+ bool antialias = false;
1067+ CREATE_NODEDEF(shapes, data_types, datas, kernel_type_str, antialias);
1068+ RUN_KERNEL(node_def, HOST, KERNEL_STATUS_OK);
1069+ delete [] data_arr;
1070+ delete [] output;
1071+ 
1072+}
1073+ 
1074+TEST_F(TEST_SCALEANDTRANSLATE_UT, DATA_TYPE_FLOAT16_METHOD_BOX_SUCC) {
1075+ std::vector<Eigen::half> data;
1076+ vector<DataType> data_types = {DT_FLOAT16, DT_INT32, DT_FLOAT, DT_FLOAT, DT_FLOAT};
1077+ int64_t kBatchSize_exp = 2;
1078+ int64_t kNumRowSquares_exp = 16;
1079+ int64_t kNumColSquares_exp = 13;
1080+ int64_t kSquareSize_exp = 12;
1081+ int64_t kNumChannels_exp = 3;
1082+ 
1083+ SetCheckerboardImageInput<Eigen::half> (kBatchSize_exp, kNumRowSquares_exp, kNumColSquares_exp,
1084+ kSquareSize_exp, kNumChannels_exp, data);
1085+ vector<int64_t> datashape = {kBatchSize_exp, kNumRowSquares_exp * kSquareSize_exp,
1086+ kNumColSquares_exp * kSquareSize_exp, kNumChannels_exp};
1087+ 
1088+ const int kOutputImageHeight_exp = kNumRowSquares_exp * kSquareSize_exp;
1089+ const int kOutputImageWidth_exp = kNumColSquares_exp * kSquareSize_exp;
1090+ 
1091+ float scale_data[2] = {0.5, 0.5};
1092+ 
1093+ float translate_data[2] = {0.5, 0.5};
1094+ int size_data[2] = {kOutputImageHeight_exp, kOutputImageWidth_exp};
1095+ vector<int64_t> sizeshape ={2};
1096+ const int outputshape= kBatchSize_exp* kOutputImageHeight_exp * kOutputImageWidth_exp * kNumChannels_exp;
1097+ float* output = new float[outputshape];
1098+ 
1099+ vector<vector<int64_t>> shapes = {datashape, sizeshape, {2}, {2}, {kBatchSize_exp, kOutputImageHeight_exp, kOutputImageWidth_exp, kNumChannels_exp}};
1100+ 
1101+ Eigen::half* data_arr = new Eigen::half[data.size()];
1102+ 
1103+ std::copy(data.begin(), data.end(), data_arr);
1104+ 
1105+ vector<void *> datas = {(void *)data_arr, (void *)size_data, (void *)scale_data, (void *)translate_data, (void *)output};
1106+ std::string kernel_type_str = "box";
1107+ bool antialias = false;
1108+ CREATE_NODEDEF(shapes, data_types, datas, kernel_type_str, antialias);
1109+ RUN_KERNEL(node_def, HOST, KERNEL_STATUS_OK);
1110+ delete [] data_arr;
1111+ delete [] output;
1112+ 
1113+}
1114+ 
1115+TEST_F(TEST_SCALEANDTRANSLATE_UT, DATA_TYPE_DOUBLE_METHOD_BOX_SUCC) {
1116+ std::vector<double> data;
1117+ vector<DataType> data_types = {DT_DOUBLE, DT_INT32, DT_FLOAT, DT_FLOAT, DT_FLOAT};
1118+ int64_t kBatchSize_exp = 2;
1119+ int64_t kNumRowSquares_exp = 16;
1120+ int64_t kNumColSquares_exp = 13;
1121+ int64_t kSquareSize_exp = 12;
1122+ int64_t kNumChannels_exp = 3;
1123+ 
1124+ SetCheckerboardImageInput<double> (kBatchSize_exp, kNumRowSquares_exp, kNumColSquares_exp,
1125+ kSquareSize_exp, kNumChannels_exp, data);
1126+ vector<int64_t> datashape = {kBatchSize_exp, kNumRowSquares_exp * kSquareSize_exp,
1127+ kNumColSquares_exp * kSquareSize_exp, kNumChannels_exp};
1128+ 
1129+ const int kOutputImageHeight_exp = kNumRowSquares_exp * kSquareSize_exp;
1130+ const int kOutputImageWidth_exp = kNumColSquares_exp * kSquareSize_exp;
1131+ 
1132+ float scale_data[2] = {0.5, 0.5};
1133+ 
1134+ float translate_data[2] = {0.5, 0.5};
1135+ int size_data[2] = {kOutputImageHeight_exp, kOutputImageWidth_exp};
1136+ vector<int64_t> sizeshape ={2};
1137+ const int outputshape= kBatchSize_exp* kOutputImageHeight_exp * kOutputImageWidth_exp * kNumChannels_exp;
1138+ float* output = new float[outputshape];
1139+ 
1140+ vector<vector<int64_t>> shapes = {datashape, sizeshape, {2}, {2}, {kBatchSize_exp, kOutputImageHeight_exp, kOutputImageWidth_exp, kNumChannels_exp}};
1141+ 
1142+ double* data_arr = new double[data.size()];
1143+ 
1144+ std::copy(data.begin(), data.end(), data_arr);
1145+ 
1146+ vector<void *> datas = {(void *)data_arr, (void *)size_data, (void *)scale_data, (void *)translate_data, (void *)output};
1147+ std::string kernel_type_str = "box";
1148+ bool antialias = false;
1149+ CREATE_NODEDEF(shapes, data_types, datas, kernel_type_str, antialias);
1150+ RUN_KERNEL(node_def, HOST, KERNEL_STATUS_OK);
1151+ delete [] data_arr;
1152+ delete [] output;
1153+ 
1154+}
1155+ 
1156+// exception instance
1157+TEST_F(TEST_SCALEANDTRANSLATE_UT, INPUT_DATA_TYPE_EXCEPTION) {
1158+ std::vector<uint64_t> data;
1159+ vector<DataType> data_types = {DT_UINT64, DT_INT32, DT_FLOAT, DT_FLOAT, DT_FLOAT};
1160+ 
1161+ uint64_t data_arr[4] = {(uint64_t)1};
1162+ vector<int64_t> datashape = {1, 2 , 2 ,1};
1163+ float scale_data[2] = {0.5, 0.5};
1164+ 
1165+ float translate_data[2] = {0.5, 0.5};
1166+ int size_data[2] = {4, 4};
1167+ vector<int64_t> sizeshape ={2};
1168+ const int outputshape= 16;
1169+ float* output = new float[outputshape];
1170+ 
1171+ vector<vector<int64_t>> shapes = {datashape, sizeshape, {2}, {2}, {1, 4, 4, 1}};
1172+ 
1173+ vector<void *> datas = {(void *)data_arr, (void *)size_data, (void *)scale_data, (void *)translate_data, (void *)output};
1174+ std::string kernel_type_str = "box";
1175+ bool antialias = false;
1176+ CREATE_NODEDEF(shapes, data_types, datas, kernel_type_str, antialias);
1177+ RUN_KERNEL(node_def, HOST, KERNEL_STATUS_PARAM_INVALID);
1178+ delete [] output;
1179+}