1 /*
2  * Copyright (C) 2019 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include "fuzzing/operation_signatures/OperationSignatureUtils.h"
18 
19 namespace android {
20 namespace nn {
21 namespace fuzzing_test {
22 
resizeOpConstructor(TestOperandType,uint32_t rank,RandomOperation * op)23 static void resizeOpConstructor(TestOperandType, uint32_t rank, RandomOperation* op) {
24     NN_FUZZER_CHECK(rank == 4);
25     setFreeDimensions(op->inputs[0], rank);
26 
27     bool useNchw = op->inputs.size() > 3 ? static_cast<bool>(op->inputs[3]->value<bool8>()) : false;
28     int heightIndex = useNchw ? 2 : 1;
29     int widthIndex = useNchw ? 3 : 2;
30 
31     // Compute output height and width.
32     RandomVariable outHeight, outWidth;
33     switch (op->inputs[1]->dataType) {
34         // Resize by shape.
35         case TestOperandType::INT32:
36             outWidth = op->inputs[1]->value<RandomVariable>();
37             outHeight = op->inputs[2]->value<RandomVariable>();
38             break;
39         // Resize by scale.
40         case TestOperandType::FLOAT32:
41             outWidth = op->inputs[0]->dimensions[widthIndex] * op->inputs[1]->value<float>();
42             outHeight = op->inputs[0]->dimensions[heightIndex] * op->inputs[2]->value<float>();
43             break;
44         case TestOperandType::FLOAT16:
45             outWidth = op->inputs[0]->dimensions[widthIndex] *
46                        static_cast<float>(op->inputs[1]->value<_Float16>());
47             outHeight = op->inputs[0]->dimensions[heightIndex] *
48                         static_cast<float>(op->inputs[2]->value<_Float16>());
49             break;
50         default:
51             NN_FUZZER_CHECK(false) << "Unsupported data type.";
52     }
53 
54     if (useNchw) {
55         op->outputs[0]->dimensions = {op->inputs[0]->dimensions[0], op->inputs[0]->dimensions[1],
56                                       outHeight, outWidth};
57     } else {
58         op->outputs[0]->dimensions = {op->inputs[0]->dimensions[0], outHeight, outWidth,
59                                       op->inputs[0]->dimensions[3]};
60     }
61     setSameQuantization(op->outputs[0], op->inputs[0]);
62 
63     // If "half_pixel_center" is set to true, then "align_corners" must be false.
64     if (op->inputs.size() == 6) {
65         auto& alignCornerFlag = op->inputs[4];
66         const auto& halfPixelCenterFlag = op->inputs[5];
67         if (halfPixelCenterFlag->value<bool8>()) {
68             alignCornerFlag->setScalarValue<bool8>(false);
69         }
70     }
71 }
72 
73 #define DEFINE_RESIZE_WITHOUT_LAYOUT_SIGNATURE(op, ver, ...)             \
74     DEFINE_OPERATION_SIGNATURE(op##_no_layout_##ver){                    \
75             .opType = TestOperationType::op,                             \
76             .supportedDataTypes = {__VA_ARGS__},                         \
77             .supportedRanks = {4},                                       \
78             .version = TestHalVersion::ver,                              \
79             .inputs = {INPUT_DEFAULT, RANDOM_INT_FREE, RANDOM_INT_FREE}, \
80             .outputs = {OUTPUT_DEFAULT},                                 \
81             .constructor = resizeOpConstructor};
82 
83 DEFINE_RESIZE_WITHOUT_LAYOUT_SIGNATURE(RESIZE_BILINEAR, V1_0, TestOperandType::TENSOR_FLOAT32);
84 DEFINE_RESIZE_WITHOUT_LAYOUT_SIGNATURE(RESIZE_BILINEAR, V1_2, TestOperandType::TENSOR_QUANT8_ASYMM,
85                                        TestOperandType::TENSOR_FLOAT16);
86 DEFINE_RESIZE_WITHOUT_LAYOUT_SIGNATURE(RESIZE_BILINEAR, V1_3,
87                                        TestOperandType::TENSOR_QUANT8_ASYMM_SIGNED);
88 
89 #define DEFINE_RESIZE_OP_SIGNATURE(op, ver, ...)                              \
90     DEFINE_OPERATION_SIGNATURE(op##_shape_##ver){                             \
91             .opType = TestOperationType::op,                                  \
92             .supportedDataTypes = {__VA_ARGS__},                              \
93             .supportedRanks = {4},                                            \
94             .version = TestHalVersion::ver,                                   \
95             .inputs = {INPUT_DEFAULT, RANDOM_INT_FREE, RANDOM_INT_FREE,       \
96                        PARAMETER_CHOICE(TestOperandType::BOOL, false, true)}, \
97             .outputs = {OUTPUT_DEFAULT},                                      \
98             .constructor = resizeOpConstructor};                              \
99     DEFINE_OPERATION_SIGNATURE(op##_scale_##ver){                             \
100             .opType = TestOperationType::op,                                  \
101             .supportedDataTypes = {__VA_ARGS__},                              \
102             .supportedRanks = {4},                                            \
103             .version = TestHalVersion::ver,                                   \
104             .inputs = {INPUT_DEFAULT, PARAMETER_FLOAT_RANGE(0.2, 4.0),        \
105                        PARAMETER_FLOAT_RANGE(0.2, 4.0),                       \
106                        PARAMETER_CHOICE(TestOperandType::BOOL, false, true)}, \
107             .outputs = {OUTPUT_DEFAULT},                                      \
108             .constructor = resizeOpConstructor};
109 
110 DEFINE_RESIZE_OP_SIGNATURE(RESIZE_BILINEAR, V1_2, TestOperandType::TENSOR_FLOAT32,
111                            TestOperandType::TENSOR_QUANT8_ASYMM, TestOperandType::TENSOR_FLOAT16);
112 DEFINE_RESIZE_OP_SIGNATURE(RESIZE_NEAREST_NEIGHBOR, V1_2, TestOperandType::TENSOR_FLOAT32,
113                            TestOperandType::TENSOR_QUANT8_ASYMM, TestOperandType::TENSOR_FLOAT16);
114 DEFINE_RESIZE_OP_SIGNATURE(RESIZE_BILINEAR, V1_3, TestOperandType::TENSOR_QUANT8_ASYMM_SIGNED);
115 DEFINE_RESIZE_OP_SIGNATURE(RESIZE_NEAREST_NEIGHBOR, V1_3,
116                            TestOperandType::TENSOR_QUANT8_ASYMM_SIGNED);
117 
118 // Resize operations with optional flags of "align_corners" and "half_pixel_center".
119 #define DEFINE_RESIZE_OP_WITH_OPTIONAL_FLAGS_SIGNATURE(op, ver, ...)          \
120     DEFINE_OPERATION_SIGNATURE(op##_shape_with_optional_flags_##ver){         \
121             .opType = TestOperationType::op,                                  \
122             .supportedDataTypes = {__VA_ARGS__},                              \
123             .supportedRanks = {4},                                            \
124             .version = TestHalVersion::ver,                                   \
125             .inputs = {INPUT_DEFAULT, RANDOM_INT_FREE, RANDOM_INT_FREE,       \
126                        PARAMETER_CHOICE(TestOperandType::BOOL, false, true),  \
127                        PARAMETER_CHOICE(TestOperandType::BOOL, false, true),  \
128                        PARAMETER_CHOICE(TestOperandType::BOOL, false, true)}, \
129             .outputs = {OUTPUT_DEFAULT},                                      \
130             .constructor = resizeOpConstructor};                              \
131     DEFINE_OPERATION_SIGNATURE(op##_scale_with_optional_flags){               \
132             .opType = TestOperationType::op,                                  \
133             .supportedDataTypes = {__VA_ARGS__},                              \
134             .supportedRanks = {4},                                            \
135             .version = TestHalVersion::ver,                                   \
136             .inputs = {INPUT_DEFAULT, PARAMETER_FLOAT_RANGE(0.2, 4.0),        \
137                        PARAMETER_FLOAT_RANGE(0.2, 4.0),                       \
138                        PARAMETER_CHOICE(TestOperandType::BOOL, false, true),  \
139                        PARAMETER_CHOICE(TestOperandType::BOOL, false, true),  \
140                        PARAMETER_CHOICE(TestOperandType::BOOL, false, true)}, \
141             .outputs = {OUTPUT_DEFAULT},                                      \
142             .constructor = resizeOpConstructor};
143 
144 DEFINE_RESIZE_OP_WITH_OPTIONAL_FLAGS_SIGNATURE(RESIZE_BILINEAR, V1_3,
145                                                TestOperandType::TENSOR_FLOAT32,
146                                                TestOperandType::TENSOR_QUANT8_ASYMM,
147                                                TestOperandType::TENSOR_FLOAT16,
148                                                TestOperandType::TENSOR_QUANT8_ASYMM_SIGNED);
149 DEFINE_RESIZE_OP_WITH_OPTIONAL_FLAGS_SIGNATURE(RESIZE_NEAREST_NEIGHBOR, V1_3,
150                                                TestOperandType::TENSOR_FLOAT32,
151                                                TestOperandType::TENSOR_QUANT8_ASYMM,
152                                                TestOperandType::TENSOR_FLOAT16,
153                                                TestOperandType::TENSOR_QUANT8_ASYMM_SIGNED);
154 
155 }  // namespace fuzzing_test
156 }  // namespace nn
157 }  // namespace android
158