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 
23 // CONCATENATION with fixed number of input tensors.
concatConstructor(uint32_t numInputs,bool isV1_0,uint32_t rank,RandomOperation * op)24 static void concatConstructor(uint32_t numInputs, bool isV1_0, uint32_t rank, RandomOperation* op) {
25     for (uint32_t i = 0; i < numInputs; i++) {
26         op->inputs[i]->dimensions.resize(rank);
27         if (isV1_0) setSameQuantization(op->inputs[i], op->inputs[0]);
28     }
29     op->outputs[0]->dimensions.resize(rank);
30 
31     int32_t axis = getUniform<int32_t>(0, rank - 1);
32     op->inputs[numInputs]->setScalarValue<int32_t>(axis);
33     for (uint32_t i = 0; i < rank; i++) {
34         op->inputs[0]->dimensions[i] = RandomVariableType::FREE;
35         op->outputs[0]->dimensions[i] = op->inputs[0]->dimensions[i];
36         for (uint32_t j = 1; j < numInputs; j++) {
37             if (axis == static_cast<int32_t>(i)) {
38                 op->inputs[j]->dimensions[i] = RandomVariableType::FREE;
39                 op->outputs[0]->dimensions[i] =
40                         op->outputs[0]->dimensions[i] + op->inputs[j]->dimensions[i];
41             } else {
42                 op->inputs[j]->dimensions[i] = op->inputs[0]->dimensions[i];
43             }
44         }
45     }
46 }
47 
DEFINE_OPERATION_SIGNATURE(CONCAT_2_V1_0)48 DEFINE_OPERATION_SIGNATURE(CONCAT_2_V1_0){
49         .opType = ANEURALNETWORKS_CONCATENATION,
50         .supportedDataTypes = {Type::TENSOR_FLOAT32, Type::TENSOR_QUANT8_ASYMM},
51         .supportedRanks = {1, 2, 3, 4},
52         .version = HalVersion::V1_0,
53         .inputs = {INPUT_DEFAULT, INPUT_DEFAULT, PARAMETER_NONE(Type::INT32)},
54         .outputs = {OUTPUT_DEFAULT},
55         .constructor = [](Type, uint32_t rank, RandomOperation* op) {
56             concatConstructor(/*numInputs=*/2, /*isV1_0=*/true, rank, op);
57         }};
58 
DEFINE_OPERATION_SIGNATURE(CONCAT_3_V1_0)59 DEFINE_OPERATION_SIGNATURE(CONCAT_3_V1_0){
60         .opType = ANEURALNETWORKS_CONCATENATION,
61         .supportedDataTypes = {Type::TENSOR_FLOAT32, Type::TENSOR_QUANT8_ASYMM},
62         .supportedRanks = {1, 2, 3, 4},
63         .version = HalVersion::V1_0,
64         .inputs = {INPUT_DEFAULT, INPUT_DEFAULT, INPUT_DEFAULT, PARAMETER_NONE(Type::INT32)},
65         .outputs = {OUTPUT_DEFAULT},
66         .constructor = [](Type, uint32_t rank, RandomOperation* op) {
67             concatConstructor(/*numInputs=*/3, /*isV1_0=*/true, rank, op);
68         }};
69 
DEFINE_OPERATION_SIGNATURE(CONCAT_2_V1_2)70 DEFINE_OPERATION_SIGNATURE(CONCAT_2_V1_2){
71         .opType = ANEURALNETWORKS_CONCATENATION,
72         .supportedDataTypes = {Type::TENSOR_FLOAT16, Type::TENSOR_QUANT8_ASYMM},
73         .supportedRanks = {1, 2, 3, 4},
74         .version = HalVersion::V1_2,
75         .inputs = {INPUT_DEFAULT, INPUT_DEFAULT, PARAMETER_NONE(Type::INT32)},
76         .outputs = {OUTPUT_DEFAULT},
77         .constructor = [](Type, uint32_t rank, RandomOperation* op) {
78             concatConstructor(/*numInputs=*/2, /*isV1_0=*/false, rank, op);
79         }};
80 
DEFINE_OPERATION_SIGNATURE(CONCAT_3_V1_2)81 DEFINE_OPERATION_SIGNATURE(CONCAT_3_V1_2){
82         .opType = ANEURALNETWORKS_CONCATENATION,
83         .supportedDataTypes = {Type::TENSOR_FLOAT16, Type::TENSOR_QUANT8_ASYMM},
84         .supportedRanks = {1, 2, 3, 4},
85         .version = HalVersion::V1_2,
86         .inputs = {INPUT_DEFAULT, INPUT_DEFAULT, INPUT_DEFAULT, PARAMETER_NONE(Type::INT32)},
87         .outputs = {OUTPUT_DEFAULT},
88         .constructor = [](Type, uint32_t rank, RandomOperation* op) {
89             concatConstructor(/*numInputs=*/3, /*isV1_0=*/false, rank, op);
90         }};
91 
92 // SPLIT with fixed number of splits.
splitConstructor(uint32_t numSplits,uint32_t rank,RandomOperation * op)93 static void splitConstructor(uint32_t numSplits, uint32_t rank, RandomOperation* op) {
94     int32_t axis = getUniform<int32_t>(-rank, rank - 1);
95     op->inputs[1]->setScalarValue<int32_t>(axis);
96     if (axis < 0) axis += rank;
97 
98     op->inputs[0]->dimensions.resize(rank);
99     for (uint32_t i = 0; i < numSplits; i++) {
100         op->outputs[i]->dimensions.resize(rank);
101         setSameQuantization(op->outputs[i], op->inputs[0]);
102     }
103 
104     for (uint32_t i = 0; i < rank; i++) {
105         op->inputs[0]->dimensions[i] = RandomVariableType::FREE;
106         RandomVariable outDim;
107         if (axis == static_cast<int32_t>(i)) {
108             outDim = op->inputs[0]->dimensions[i].exactDiv(numSplits);
109         } else {
110             outDim = op->inputs[0]->dimensions[i];
111         }
112         for (uint32_t j = 0; j < numSplits; j++) op->outputs[j]->dimensions[i] = outDim;
113     }
114 }
115 
DEFINE_OPERATION_SIGNATURE(SPLIT_2_V1_2)116 DEFINE_OPERATION_SIGNATURE(SPLIT_2_V1_2){
117         .opType = ANEURALNETWORKS_SPLIT,
118         .supportedDataTypes = {Type::TENSOR_FLOAT32, Type::TENSOR_FLOAT16, Type::TENSOR_INT32,
119                                Type::TENSOR_QUANT8_ASYMM},
120         .supportedRanks = {1, 2, 3, 4},
121         .version = HalVersion::V1_2,
122         .inputs = {INPUT_DEFAULT, PARAMETER_NONE(Type::INT32), PARAMETER_CHOICE(Type::INT32, 2)},
123         .outputs = {OUTPUT_DEFAULT, OUTPUT_DEFAULT},
124         .constructor = [](Type, uint32_t rank, RandomOperation* op) {
125             splitConstructor(/*numSplits=*/2, rank, op);
126         }};
127 
DEFINE_OPERATION_SIGNATURE(SPLIT_3_V1_2)128 DEFINE_OPERATION_SIGNATURE(SPLIT_3_V1_2){
129         .opType = ANEURALNETWORKS_SPLIT,
130         .supportedDataTypes = {Type::TENSOR_FLOAT32, Type::TENSOR_FLOAT16, Type::TENSOR_INT32,
131                                Type::TENSOR_QUANT8_ASYMM},
132         .supportedRanks = {1, 2, 3, 4},
133         .version = HalVersion::V1_2,
134         .inputs = {INPUT_DEFAULT, PARAMETER_NONE(Type::INT32), PARAMETER_CHOICE(Type::INT32, 3)},
135         .outputs = {OUTPUT_DEFAULT, OUTPUT_DEFAULT, OUTPUT_DEFAULT},
136         .constructor = [](Type, uint32_t rank, RandomOperation* op) {
137             splitConstructor(/*numSplits=*/3, rank, op);
138         }};
139 
140 }  // namespace fuzzing_test
141 }  // namespace nn
142 }  // namespace android
143