1 /*
2 * Copyright (C) 2018 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 <gmock/gmock.h>
18 #include <gtest/gtest-death-test.h>
19 #include <gtest/gtest.h>
20
21 #include <algorithm>
22 #include <cstddef>
23 #include <cstdint>
24 #include <iterator>
25 #include <memory>
26 #include <optional>
27 #include <set>
28 #include <sstream>
29 #include <string>
30 #include <utility>
31 #include <vector>
32
33 #include "NeuralNetworks.h"
34 #include "NeuralNetworksOEM.h"
35 #include "NeuralNetworksWrapper.h"
36
37 using namespace android::nn::wrapper;
38
39 namespace {
40
41 static const int32_t kAvailableOperandCodes[] = {ANEURALNETWORKS_FLOAT32,
42 ANEURALNETWORKS_INT32,
43 ANEURALNETWORKS_UINT32,
44 ANEURALNETWORKS_TENSOR_FLOAT32,
45 ANEURALNETWORKS_TENSOR_INT32,
46 ANEURALNETWORKS_TENSOR_QUANT8_ASYMM,
47 ANEURALNETWORKS_BOOL,
48 ANEURALNETWORKS_TENSOR_QUANT16_SYMM,
49 ANEURALNETWORKS_TENSOR_FLOAT16,
50 ANEURALNETWORKS_TENSOR_BOOL8,
51 ANEURALNETWORKS_FLOAT16,
52 ANEURALNETWORKS_TENSOR_QUANT8_SYMM_PER_CHANNEL,
53 ANEURALNETWORKS_TENSOR_QUANT16_ASYMM,
54 ANEURALNETWORKS_TENSOR_OEM_BYTE};
55
getOpType(int32_t opcode,uint32_t dimCount=0,const uint32_t * dim=nullptr)56 ANeuralNetworksOperandType getOpType(int32_t opcode, uint32_t dimCount = 0,
57 const uint32_t* dim = nullptr) {
58 ANeuralNetworksOperandType opType = {.type = opcode,
59 .dimensionCount = dimCount,
60 .dimensions = dim,
61 .scale = 0.0,
62 .zeroPoint = 0};
63 if (opcode == ANEURALNETWORKS_TENSOR_QUANT8_ASYMM ||
64 opcode == ANEURALNETWORKS_TENSOR_QUANT8_ASYMM_SIGNED ||
65 opcode == ANEURALNETWORKS_TENSOR_QUANT8_SYMM ||
66 opcode == ANEURALNETWORKS_TENSOR_QUANT16_ASYMM ||
67 opcode == ANEURALNETWORKS_TENSOR_QUANT16_SYMM) {
68 opType.scale = 1. / 256.;
69 }
70 return opType;
71 }
72
73 struct OperandTypeWithExtraParams {
OperandTypeWithExtraParams__anon37b312a30111::OperandTypeWithExtraParams74 OperandTypeWithExtraParams(const ANeuralNetworksOperandType& operandType)
75 : operandType(operandType), channelQuant(std::nullopt), valueModel(std::nullopt) {}
76
77 ANeuralNetworksOperandType operandType;
78 std::optional<ANeuralNetworksSymmPerChannelQuantParams> channelQuant;
79 std::optional<const ANeuralNetworksModel*> valueModel;
80
operator ==__anon37b312a30111::OperandTypeWithExtraParams81 bool operator==(const OperandTypeWithExtraParams& that) const {
82 if (operandType.type != that.operandType.type ||
83 operandType.scale != that.operandType.scale ||
84 operandType.zeroPoint != that.operandType.zeroPoint ||
85 operandType.dimensionCount != that.operandType.dimensionCount) {
86 return false;
87 }
88
89 if (channelQuant.has_value() != that.channelQuant.has_value() ||
90 (channelQuant.has_value() &&
91 (channelQuant->channelDim != that.channelQuant->channelDim ||
92 channelQuant->scaleCount != that.channelQuant->scaleCount))) {
93 return false;
94 }
95
96 if (valueModel != that.valueModel) {
97 return false;
98 }
99
100 if (operandType.dimensions) {
101 if (!that.operandType.dimensions) {
102 return false;
103 }
104 if (!std::equal(operandType.dimensions,
105 operandType.dimensions + operandType.dimensionCount,
106 that.operandType.dimensions)) {
107 return false;
108 }
109 } else {
110 if (that.operandType.dimensions) {
111 return false;
112 }
113 }
114
115 if (channelQuant.has_value()) {
116 if (channelQuant->scales) {
117 return that.channelQuant->scales &&
118 std::equal(channelQuant->scales,
119 channelQuant->scales + channelQuant->scaleCount,
120 that.channelQuant->scales);
121 } else {
122 return that.channelQuant->scales == nullptr;
123 }
124 }
125 return true;
126 }
127
operator !=__anon37b312a30111::OperandTypeWithExtraParams128 bool operator!=(const OperandTypeWithExtraParams& that) const { return !(*this == that); }
129
operator <__anon37b312a30111::OperandTypeWithExtraParams130 bool operator<(const OperandTypeWithExtraParams& that) const {
131 if (operandType.type < that.operandType.type) return true;
132 if (operandType.dimensionCount < that.operandType.dimensionCount) return true;
133 return false;
134 }
135 }; // namespace
136
137 // Generates valid and invalid mutations of given OperandTypeWithParams
138 // instances.
139 // It is also responsible of freeing the memory allocated when creating
140 // mutations.
141 // Mutations shouldn't outlive the generating TensorRankConstraint instance.
142 class TensorRankConstraint {
143 public:
TensorRankConstraint(const TensorRankConstraint & copyFrom)144 TensorRankConstraint(const TensorRankConstraint& copyFrom) {
145 // ignoring the array of allocated dimension
146 this->mRangeMax = copyFrom.mRangeMax;
147 this->mRangeMin = copyFrom.mRangeMin;
148 }
149
operator =(const TensorRankConstraint & copyFrom)150 TensorRankConstraint& operator=(const TensorRankConstraint& copyFrom) {
151 // ignoring the array of allocated dimension
152 this->mRangeMax = copyFrom.mRangeMax;
153 this->mRangeMin = copyFrom.mRangeMin;
154 return *this;
155 }
156
Exactly(uint32_t rank)157 static TensorRankConstraint Exactly(uint32_t rank) {
158 return TensorRankConstraint(std::optional(rank), std::optional(rank));
159 }
160
AtLeast(uint32_t min)161 static TensorRankConstraint AtLeast(uint32_t min) {
162 return TensorRankConstraint(std::optional(min), std::nullopt);
163 }
164
UpTo(uint32_t max)165 static TensorRankConstraint UpTo(uint32_t max) {
166 return TensorRankConstraint(std::nullopt, std::optional(max));
167 }
168
Between(uint32_t min,uint32_t max)169 static TensorRankConstraint Between(uint32_t min, uint32_t max) {
170 if (min == 0) {
171 return UpTo(max);
172 }
173 return TensorRankConstraint(std::optional(min), std::optional(max));
174 }
175
MutationsWithValidRank(const std::vector<OperandTypeWithExtraParams> & operandsTypeWithParams)176 std::set<std::vector<OperandTypeWithExtraParams>> MutationsWithValidRank(
177 const std::vector<OperandTypeWithExtraParams>& operandsTypeWithParams) {
178 // can't be both nullopt
179 if (!mRangeMin) {
180 return {ModifyForRank(operandsTypeWithParams, 1),
181 ModifyForRank(operandsTypeWithParams, *mRangeMax)};
182 } else if (!mRangeMax) {
183 return {ModifyForRank(operandsTypeWithParams, *mRangeMin),
184 ModifyForRank(operandsTypeWithParams, *mRangeMin + 1)};
185 } else if (mRangeMax == mRangeMin) {
186 std::for_each(operandsTypeWithParams.begin(), operandsTypeWithParams.end(),
187 [this](const OperandTypeWithExtraParams& op) {
188 assert(op.operandType.dimensionCount == *mRangeMin);
189 });
190 return {operandsTypeWithParams};
191 } else {
192 return {ModifyForRank(operandsTypeWithParams, *mRangeMin),
193 ModifyForRank(operandsTypeWithParams, *mRangeMax)};
194 }
195 }
196
MutationsWithInvalidRank(const std::vector<OperandTypeWithExtraParams> & operandsTypeWithParams)197 std::set<std::vector<OperandTypeWithExtraParams>> MutationsWithInvalidRank(
198 const std::vector<OperandTypeWithExtraParams>& operandsTypeWithParams) {
199 std::set<std::vector<OperandTypeWithExtraParams>> result;
200 if (mRangeMax) {
201 result.insert(ModifyForRank(operandsTypeWithParams, *mRangeMax + 1));
202 }
203 if (mRangeMin.value_or(0) > 1) {
204 result.insert(ModifyForRank(operandsTypeWithParams, *mRangeMin - 1));
205 }
206 return result;
207 }
208
209 private:
ModifyForRank(const std::vector<OperandTypeWithExtraParams> & operandsTypeWithParams,uint32_t newRank)210 std::vector<OperandTypeWithExtraParams> ModifyForRank(
211 const std::vector<OperandTypeWithExtraParams>& operandsTypeWithParams,
212 uint32_t newRank) {
213 std::vector<OperandTypeWithExtraParams> result;
214 std::transform(operandsTypeWithParams.cbegin(), operandsTypeWithParams.cend(),
215 std::back_inserter(result),
216 [this, newRank](const OperandTypeWithExtraParams& operandTypeWithParams) {
217 return ModifyForRank(operandTypeWithParams, newRank);
218 });
219 return result;
220 }
221
ModifyForRank(const OperandTypeWithExtraParams & operandTypeWithParams,uint32_t newRank)222 OperandTypeWithExtraParams ModifyForRank(
223 const OperandTypeWithExtraParams& operandTypeWithParams, uint32_t newRank) {
224 if (operandTypeWithParams.operandType.dimensionCount == newRank) {
225 return operandTypeWithParams;
226 }
227
228 uint32_t* resultDimensions = nullptr;
229 if (newRank != 0) {
230 std::unique_ptr<uint32_t[]> dimensions = std::make_unique<uint32_t[]>(newRank);
231 resultDimensions = dimensions.get();
232 mAllocatedDimensions.insert(std::move(dimensions));
233 std::fill(resultDimensions, resultDimensions + newRank, 1);
234 const auto originDims = operandTypeWithParams.operandType.dimensions;
235 if (originDims != nullptr) {
236 const int dimsToCopy =
237 std::min(operandTypeWithParams.operandType.dimensionCount, newRank);
238 std::copy(originDims, originDims + dimsToCopy, resultDimensions);
239 }
240 }
241
242 OperandTypeWithExtraParams result = operandTypeWithParams;
243 result.operandType = {
244 .type = operandTypeWithParams.operandType.type,
245 .dimensionCount = newRank,
246 .dimensions = resultDimensions,
247 .scale = operandTypeWithParams.operandType.scale,
248 .zeroPoint = operandTypeWithParams.operandType.zeroPoint,
249 };
250
251 return result;
252 }
253
TensorRankConstraint(const std::optional<uint32_t> & min,const std::optional<uint32_t> & max)254 TensorRankConstraint(const std::optional<uint32_t>& min, const std::optional<uint32_t>& max)
255 : mRangeMin(min), mRangeMax(max) {
256 if (mRangeMax.has_value()) {
257 assert(*mRangeMax >= mRangeMin.value_or(0));
258 }
259
260 assert(mRangeMax.has_value() || mRangeMin.has_value());
261 }
262
263 std::optional<uint32_t> mRangeMin;
264 std::optional<uint32_t> mRangeMax;
265 std::set<std::unique_ptr<uint32_t[]>> mAllocatedDimensions;
266 };
267
268 // Mutates a set of inputs applying the same rank constraint.
269 class TensorRankMutator {
270 public:
TensorRankMutator(const TensorRankConstraint & constraint,const std::set<uint32_t> & applyToIndexes={0})271 TensorRankMutator(const TensorRankConstraint& constraint,
272 const std::set<uint32_t>& applyToIndexes = {0})
273 : mApplyToIndexes(applyToIndexes.begin(), applyToIndexes.end()), mConstraint(constraint) {}
274
ValidInputsMutations(const std::vector<OperandTypeWithExtraParams> & validInputs)275 std::set<std::vector<OperandTypeWithExtraParams>> ValidInputsMutations(
276 const std::vector<OperandTypeWithExtraParams>& validInputs) {
277 return InputsMutations(
278 validInputs, [this](const std::vector<OperandTypeWithExtraParams>& inputsToMutate) {
279 return mConstraint.MutationsWithValidRank(inputsToMutate);
280 });
281 }
282
InvalidInputsMutations(const std::vector<OperandTypeWithExtraParams> & validInputs)283 std::set<std::vector<OperandTypeWithExtraParams>> InvalidInputsMutations(
284 const std::vector<OperandTypeWithExtraParams>& validInputs) {
285 return InputsMutations(
286 validInputs, [this](const std::vector<OperandTypeWithExtraParams>& inputsToMutate) {
287 return mConstraint.MutationsWithInvalidRank(inputsToMutate);
288 });
289 }
290
291 private:
InputsMutations(const std::vector<OperandTypeWithExtraParams> & validInputs,std::function<std::set<std::vector<OperandTypeWithExtraParams>> (const std::vector<OperandTypeWithExtraParams> &)> operandMutator)292 std::set<std::vector<OperandTypeWithExtraParams>> InputsMutations(
293 const std::vector<OperandTypeWithExtraParams>& validInputs,
294 std::function<std::set<std::vector<OperandTypeWithExtraParams>>(
295 const std::vector<OperandTypeWithExtraParams>&)>
296 operandMutator) {
297 std::for_each(mApplyToIndexes.begin(), mApplyToIndexes.end(),
298 [&validInputs](uint32_t index) { assert(index < validInputs.size()); });
299
300 std::vector<OperandTypeWithExtraParams> toMutate;
301 std::transform(mApplyToIndexes.begin(), mApplyToIndexes.end(), std::back_inserter(toMutate),
302 [&validInputs](int input_index) { return validInputs[input_index]; });
303
304 // Get a series of mutation for the operands in toMutate
305 std::set<std::vector<OperandTypeWithExtraParams>> mutatedOps = operandMutator(toMutate);
306
307 // Generate a set of mutation by replacing the mutated ops in validInputs
308 // with all the mutations in mutatedOps
309 std::set<std::vector<OperandTypeWithExtraParams>> mutatedValidInputs;
310 std::transform(
311 mutatedOps.cbegin(), mutatedOps.cend(),
312 std::inserter(mutatedValidInputs, mutatedValidInputs.begin()),
313 [this, &validInputs](const std::vector<OperandTypeWithExtraParams>& opsMutation) {
314 std::vector<OperandTypeWithExtraParams> currInputMutation(validInputs.begin(),
315 validInputs.end());
316 for (size_t i = 0; i < mApplyToIndexes.size(); i++) {
317 currInputMutation[mApplyToIndexes[i]] = opsMutation[i];
318 }
319
320 return currInputMutation;
321 });
322
323 return mutatedValidInputs;
324 }
325
326 std::vector<uint32_t> mApplyToIndexes;
327 TensorRankConstraint mConstraint;
328 };
329
330 class OperationTestBase {
331 public:
OperationTestBase(ANeuralNetworksOperationType opCode,const std::vector<ANeuralNetworksOperandType> & validInputs,const std::vector<ANeuralNetworksOperandType> & validOutputs,const std::vector<TensorRankMutator> & inputRankMutators={})332 OperationTestBase(ANeuralNetworksOperationType opCode,
333 const std::vector<ANeuralNetworksOperandType>& validInputs,
334 const std::vector<ANeuralNetworksOperandType>& validOutputs,
335 const std::vector<TensorRankMutator>& inputRankMutators = {})
336 : mOpCode(opCode), mValidInputs(), mValidOutputs(), mInputRankMutators(inputRankMutators) {
337 for (ANeuralNetworksOperandType input : validInputs) {
338 mValidInputs.push_back(input);
339 }
340 for (ANeuralNetworksOperandType output : validOutputs) {
341 mValidOutputs.push_back(output);
342 }
343 }
344
setInputSymmPerChannelQuantParams(int32_t index,const ANeuralNetworksSymmPerChannelQuantParams & channelQuant)345 void setInputSymmPerChannelQuantParams(
346 int32_t index, const ANeuralNetworksSymmPerChannelQuantParams& channelQuant) {
347 mValidInputs[index].channelQuant = channelQuant;
348 }
349
setOutputSymmPerChannelQuantParams(int32_t index,const ANeuralNetworksSymmPerChannelQuantParams & channelQuant)350 void setOutputSymmPerChannelQuantParams(
351 int32_t index, const ANeuralNetworksSymmPerChannelQuantParams& channelQuant) {
352 mValidOutputs[index].channelQuant = channelQuant;
353 }
354
setInputOperandValueFromModel(int32_t index,const ANeuralNetworksModel * valueModel)355 void setInputOperandValueFromModel(int32_t index, const ANeuralNetworksModel* valueModel) {
356 mValidInputs[index].valueModel = valueModel;
357 }
358
359 // Add each operand separately and add the operation using these operands.
360 // This function does not cover the cases that an operand is used mutiple times.
addOperation(const std::vector<OperandTypeWithExtraParams> & inputs,const std::vector<OperandTypeWithExtraParams> & outputs)361 int32_t addOperation(const std::vector<OperandTypeWithExtraParams>& inputs,
362 const std::vector<OperandTypeWithExtraParams>& outputs) {
363 ANeuralNetworksModel* model = nullptr;
364 ANeuralNetworksModel_create(&model);
365
366 uint32_t opIdx = 0;
367 std::vector<uint32_t> inputIds;
368 std::vector<uint32_t> outputIds;
369 for (uint32_t i = 0; i < inputs.size(); i++) {
370 ANeuralNetworksModel_addOperand(model, &inputs[i].operandType);
371 if (inputs[i].channelQuant) {
372 ANeuralNetworksModel_setOperandSymmPerChannelQuantParams(
373 model, opIdx, &inputs[i].channelQuant.value());
374 }
375 if (inputs[i].valueModel) {
376 ANeuralNetworksModel_setOperandValueFromModel(model, opIdx,
377 inputs[i].valueModel.value());
378 }
379 inputIds.push_back(opIdx++);
380 }
381 for (uint32_t i = 0; i < outputs.size(); i++) {
382 ANeuralNetworksModel_addOperand(model, &outputs[i].operandType);
383 if (outputs[i].channelQuant) {
384 ANeuralNetworksModel_setOperandSymmPerChannelQuantParams(
385 model, opIdx, &outputs[i].channelQuant.value());
386 }
387 outputIds.push_back(opIdx++);
388 }
389
390 int32_t result = ANeuralNetworksModel_addOperation(
391 model, mOpCode, static_cast<uint32_t>(inputIds.size()), inputIds.data(),
392 static_cast<uint32_t>(outputIds.size()), outputIds.data());
393 ANeuralNetworksModel_free(model);
394 return result;
395 }
396
testOpsValidations()397 void testOpsValidations() {
398 EXPECT_TRUE(testSuccess());
399 EXPECT_TRUE(testMutatingInputOperandCode());
400 EXPECT_TRUE(testMutatingInputOperandCounts());
401 EXPECT_TRUE(testMutatingOutputOperandCode());
402 EXPECT_TRUE(testMutatingOutputOperandCounts());
403 EXPECT_TRUE(testMutatingInputRanks());
404 }
405
testFailure(int32_t expectedResult)406 void testFailure(int32_t expectedResult) {
407 int32_t result = addOperation(mValidInputs, mValidOutputs);
408 EXPECT_TRUE(expectedResult == result);
409 }
410
testSuccess()411 bool testSuccess() {
412 int32_t result = addOperation(mValidInputs, mValidOutputs);
413 return ANEURALNETWORKS_NO_ERROR == result;
414 }
415
testMutatingInputOperandCode()416 bool testMutatingInputOperandCode() {
417 for (uint32_t i = 0; i < mValidInputs.size(); i++) {
418 // LSH_PROJECTION's second argument is allowed to have any type.
419 // This is the only operation that currently has a type that can be
420 // anything independent from any other type. Changing the operand
421 // type to any other type will result in a valid model for
422 // LSH_PROJECTION. If this is the case, skip the test.
423 if (mOpCode == ANEURALNETWORKS_LSH_PROJECTION && i == 1) {
424 continue;
425 }
426 // RANK can have input of any type.
427 if (mOpCode == ANEURALNETWORKS_RANK) {
428 continue;
429 }
430 OperandTypeWithExtraParams newType = mValidInputs[i];
431 int32_t originalOperandCode = mValidInputs[i].operandType.type;
432 std::set<int32_t> operandTypesToSkip;
433 // Transposed conv can have either fully quantized or per-channel
434 // quantized filter for the quantized version of the op.
435 if ((mOpCode == ANEURALNETWORKS_TRANSPOSE_CONV_2D ||
436 mOpCode == ANEURALNETWORKS_DEPTHWISE_CONV_2D) &&
437 i == 1) {
438 if (originalOperandCode == ANEURALNETWORKS_TENSOR_QUANT8_ASYMM ||
439 originalOperandCode == ANEURALNETWORKS_TENSOR_QUANT8_ASYMM_SIGNED ||
440 originalOperandCode == ANEURALNETWORKS_TENSOR_QUANT8_SYMM_PER_CHANNEL) {
441 operandTypesToSkip.insert(ANEURALNETWORKS_TENSOR_QUANT8_ASYMM);
442 operandTypesToSkip.insert(ANEURALNETWORKS_TENSOR_QUANT8_ASYMM_SIGNED);
443 operandTypesToSkip.insert(ANEURALNETWORKS_TENSOR_QUANT8_SYMM_PER_CHANNEL);
444 }
445 }
446 // CAST accepts any of supported types for any of output types
447 if (mOpCode == ANEURALNETWORKS_CAST && i == 0) {
448 operandTypesToSkip.insert(ANEURALNETWORKS_TENSOR_FLOAT16);
449 operandTypesToSkip.insert(ANEURALNETWORKS_TENSOR_FLOAT32);
450 operandTypesToSkip.insert(ANEURALNETWORKS_TENSOR_INT32);
451 operandTypesToSkip.insert(ANEURALNETWORKS_TENSOR_QUANT8_ASYMM);
452 operandTypesToSkip.insert(ANEURALNETWORKS_TENSOR_QUANT8_ASYMM_SIGNED);
453 }
454 // RANDOM_MULTINOMIAL's first input can be either of float16 or
455 // float32 type while everything else has the same types.
456 if (mOpCode == ANEURALNETWORKS_RANDOM_MULTINOMIAL && i == 0) {
457 if (originalOperandCode == ANEURALNETWORKS_TENSOR_FLOAT16) {
458 operandTypesToSkip.insert(ANEURALNETWORKS_TENSOR_FLOAT32);
459 } else if (originalOperandCode == ANEURALNETWORKS_TENSOR_FLOAT32) {
460 operandTypesToSkip.insert(ANEURALNETWORKS_TENSOR_FLOAT16);
461 }
462 }
463 // DEQUANTIZE supports any of the inputs types below for any of the
464 // output types.
465 if (mOpCode == ANEURALNETWORKS_DEQUANTIZE && i == 0) {
466 operandTypesToSkip.insert(ANEURALNETWORKS_TENSOR_QUANT8_ASYMM);
467 operandTypesToSkip.insert(ANEURALNETWORKS_TENSOR_QUANT8_ASYMM_SIGNED);
468 operandTypesToSkip.insert(ANEURALNETWORKS_TENSOR_QUANT8_SYMM);
469 operandTypesToSkip.insert(ANEURALNETWORKS_TENSOR_QUANT8_SYMM_PER_CHANNEL);
470 }
471 // AXIS_ALIGNED_BBOX_TRANSFORM's second input cab be either QUANT8_ASYMM or
472 // QUANT8_ASYMM_SIGNED
473 if (mOpCode == ANEURALNETWORKS_AXIS_ALIGNED_BBOX_TRANSFORM && i == 1) {
474 operandTypesToSkip.insert(ANEURALNETWORKS_TENSOR_QUANT8_ASYMM);
475 operandTypesToSkip.insert(ANEURALNETWORKS_TENSOR_QUANT8_ASYMM_SIGNED);
476 }
477
478 for (int32_t newOperandCode : kAvailableOperandCodes) {
479 if (newOperandCode == originalOperandCode ||
480 operandTypesToSkip.find(newOperandCode) != operandTypesToSkip.end()) {
481 continue;
482 }
483 // Switch input 7 from bool to int for 10-input CONV_2d
484 // switch between valid "implicit padding with layout param"
485 // and valid "explicit padding without layout param"
486 if (mOpCode == ANEURALNETWORKS_CONV_2D && i == 7 && mValidInputs.size() == 10) {
487 if ((newOperandCode == ANEURALNETWORKS_INT32 &&
488 originalOperandCode == ANEURALNETWORKS_BOOL) ||
489 (newOperandCode == ANEURALNETWORKS_BOOL &&
490 originalOperandCode == ANEURALNETWORKS_INT32)) {
491 continue;
492 }
493 }
494 // QUANTIZE supports both types below and its output type does
495 // not depend on the input type.
496 if (mOpCode == ANEURALNETWORKS_QUANTIZE && i == 0 &&
497 (newOperandCode == ANEURALNETWORKS_TENSOR_FLOAT16 ||
498 newOperandCode == ANEURALNETWORKS_TENSOR_FLOAT32)) {
499 continue;
500 }
501
502 // ARGMIN/MAX supports four input types and has a fixed output type.
503 if ((mOpCode == ANEURALNETWORKS_ARGMIN || mOpCode == ANEURALNETWORKS_ARGMAX) &&
504 i == 0 &&
505 (newOperandCode == ANEURALNETWORKS_TENSOR_FLOAT16 ||
506 newOperandCode == ANEURALNETWORKS_TENSOR_FLOAT32 ||
507 newOperandCode == ANEURALNETWORKS_TENSOR_INT32 ||
508 newOperandCode == ANEURALNETWORKS_TENSOR_QUANT8_ASYMM ||
509 newOperandCode == ANEURALNETWORKS_TENSOR_QUANT8_ASYMM_SIGNED)) {
510 continue;
511 }
512
513 // Switch input 8 from bool to int for 11-input DEPTHWISE_CONV_2D
514 // switch between valid "implicit padding with layout param"
515 // and valid "explicit padding without layout param"
516 if (mOpCode == ANEURALNETWORKS_DEPTHWISE_CONV_2D && i == 8 &&
517 mValidInputs.size() == 11) {
518 if ((newOperandCode == ANEURALNETWORKS_INT32 &&
519 originalOperandCode == ANEURALNETWORKS_BOOL) ||
520 (newOperandCode == ANEURALNETWORKS_BOOL &&
521 originalOperandCode == ANEURALNETWORKS_INT32)) {
522 continue;
523 }
524 }
525
526 newType.operandType.type = newOperandCode;
527 std::vector<OperandTypeWithExtraParams> inputs = mValidInputs;
528 inputs[i] = newType;
529 int32_t result = addOperation(inputs, mValidOutputs);
530 if (ANEURALNETWORKS_NO_ERROR == result) {
531 return false;
532 }
533 }
534 }
535 return true;
536 }
537
testMutatingOutputOperandCode()538 bool testMutatingOutputOperandCode() {
539 for (uint32_t i = 0; i < mValidOutputs.size(); i++) {
540 // LSH_PROJECTION's second argument is allowed to have any type.
541 // This is the only operation that currently has a type that can be
542 // anything independent from any other type. Changing the operand
543 // type to any other type will result in a valid model for
544 // LSH_PROJECTION. If this is the case, skip the test.
545 if (mOpCode == ANEURALNETWORKS_LSH_PROJECTION && i == 1) {
546 continue;
547 }
548 OperandTypeWithExtraParams newType = mValidOutputs[i].operandType;
549 int32_t originalOperandCode = mValidOutputs[i].operandType.type;
550 for (int32_t newOperandCode : kAvailableOperandCodes) {
551 if (newOperandCode == originalOperandCode) {
552 continue;
553 }
554 // DEQUANTIZE's output can be either TENSOR_FLOAT16 or TENSOR_FLOAT32.
555 if (mOpCode == ANEURALNETWORKS_DEQUANTIZE &&
556 (newOperandCode == ANEURALNETWORKS_TENSOR_FLOAT16 ||
557 newOperandCode == ANEURALNETWORKS_TENSOR_FLOAT32)) {
558 continue;
559 }
560
561 // QUANTIZE's output can be either TENSOR_QUANT8_ASYMM or
562 // TENSOR_QUANT8_ASYMM_SIGNED.
563 if (mOpCode == ANEURALNETWORKS_QUANTIZE && i == 0 &&
564 (newOperandCode == ANEURALNETWORKS_TENSOR_QUANT8_ASYMM ||
565 newOperandCode == ANEURALNETWORKS_TENSOR_QUANT8_ASYMM_SIGNED)) {
566 continue;
567 }
568
569 // CAST accepts any of supported types for any of input types
570 if (mOpCode == ANEURALNETWORKS_CAST && i == 0 &&
571 (newOperandCode == ANEURALNETWORKS_TENSOR_FLOAT16 ||
572 newOperandCode == ANEURALNETWORKS_TENSOR_FLOAT32 ||
573 newOperandCode == ANEURALNETWORKS_TENSOR_INT32 ||
574 newOperandCode == ANEURALNETWORKS_TENSOR_QUANT8_ASYMM)) {
575 continue;
576 }
577 newType.operandType.type = newOperandCode;
578 std::vector<OperandTypeWithExtraParams> outputs = mValidOutputs;
579 outputs[i] = newType;
580 int32_t result = addOperation(mValidInputs, outputs);
581 if (ANEURALNETWORKS_NO_ERROR == result) {
582 return false;
583 }
584 }
585 }
586 return true;
587 }
588
testMutatingInputOperandCounts()589 bool testMutatingInputOperandCounts() {
590 uint32_t numToAdd = 5;
591 // LSTM since API 29 supports 23 and 27 outputs.
592 if (mOpCode == ANEURALNETWORKS_LSTM) {
593 numToAdd = 3;
594 }
595 std::vector<OperandTypeWithExtraParams> inputs = mValidInputs;
596 for (uint32_t i = 0; i < numToAdd; i++) {
597 inputs.push_back(inputs[0]);
598 if (ANEURALNETWORKS_NO_ERROR == addOperation(inputs, mValidOutputs)) {
599 return false;
600 }
601 }
602 return true;
603 }
604
testMutatingOutputOperandCounts()605 bool testMutatingOutputOperandCounts() {
606 // SPLIT's number of outputs depends on a value of one of its inputs and
607 // are not checked during validation.
608 if (mOpCode == ANEURALNETWORKS_SPLIT) {
609 return true;
610 }
611 std::vector<OperandTypeWithExtraParams> outputs = mValidOutputs;
612 for (int i = 0; i < 6; i++) {
613 outputs.push_back(outputs[0]);
614 if (ANEURALNETWORKS_NO_ERROR == addOperation(mValidInputs, outputs)) {
615 if (mOpCode == ANEURALNETWORKS_UNIDIRECTIONAL_SEQUENCE_RNN && i < 1) {
616 continue;
617 }
618 if (mOpCode == ANEURALNETWORKS_UNIDIRECTIONAL_SEQUENCE_LSTM && i < 3) {
619 continue;
620 }
621 if (mOpCode == ANEURALNETWORKS_BIDIRECTIONAL_SEQUENCE_RNN && i < 3) {
622 continue;
623 }
624 if (mOpCode == ANEURALNETWORKS_BIDIRECTIONAL_SEQUENCE_LSTM && i < 5) {
625 continue;
626 }
627 return false;
628 }
629 }
630 return true;
631 }
632
testMutatingInputRanks()633 bool testMutatingInputRanks() {
634 for (auto& rankMutator : mInputRankMutators) {
635 for (const auto& validMutation : rankMutator.ValidInputsMutations(mValidInputs)) {
636 int32_t result = addOperation(validMutation, mValidOutputs);
637 if (ANEURALNETWORKS_NO_ERROR != result) {
638 return false;
639 }
640 }
641
642 for (const auto& invalidMutation : rankMutator.InvalidInputsMutations(mValidInputs)) {
643 int32_t result = addOperation(invalidMutation, mValidOutputs);
644 if (ANEURALNETWORKS_NO_ERROR == result) {
645 return false;
646 }
647 }
648 }
649
650 return true;
651 }
652
653 private:
654 ANeuralNetworksOperationType mOpCode;
655 // The dimensions in the ANeuralNetworksOperandType must outlive the test object.
656 std::vector<OperandTypeWithExtraParams> mValidInputs;
657 std::vector<OperandTypeWithExtraParams> mValidOutputs;
658
659 std::vector<TensorRankMutator> mInputRankMutators;
660 };
661
operator <<(std::ostream & os,const OperandTypeWithExtraParams & operand)662 std::ostream& operator<<(std::ostream& os, const OperandTypeWithExtraParams& operand) {
663 const auto& operandType = operand.operandType;
664 os << "{ operand_type: { type: " << operandType.type << ", "
665 << "dimensionCount: " << operandType.dimensionCount << ", dimensions: [";
666 std::for_each(operandType.dimensions, operandType.dimensions + operandType.dimensionCount,
667 [&os](uint32_t dimension) { os << dimension << ", "; });
668 os << "], scale: " << operandType.scale << ", zeroPoint: " << operandType.zeroPoint << " }";
669
670 const auto& channelQuant = operand.channelQuant;
671 if (channelQuant.has_value()) {
672 os << ", channelQuant { channelDim: " << channelQuant->channelDim
673 << ", scaleCount: " << channelQuant->scaleCount << ", scales: [";
674 std::for_each(channelQuant->scales, channelQuant->scales + channelQuant->scaleCount,
675 [&os](float scale) { os << scale << ", "; });
676 os << "] }";
677 } else {
678 os << ", channelQuant: nullopt";
679 }
680
681 if (operand.valueModel.has_value()) {
682 os << ", valueModel: " << operand.valueModel.value();
683 } else {
684 os << ", valueModel: nullopt";
685 }
686 os << "}";
687 return os;
688 }
689
MutationWithDimensions(const OperandTypeWithExtraParams & origin,const std::vector<uint32_t> & expectedDims)690 inline OperandTypeWithExtraParams MutationWithDimensions(
691 const OperandTypeWithExtraParams& origin, const std::vector<uint32_t>& expectedDims) {
692 OperandTypeWithExtraParams expected = origin;
693 expected.operandType.dimensionCount = expectedDims.size();
694 if (expectedDims.size() == 0) {
695 expected.operandType.dimensions = nullptr;
696 } else {
697 expected.operandType.dimensions = expectedDims.data();
698 }
699 return expected;
700 }
DescribeMutationWithDimensions(const OperandTypeWithExtraParams & origin,const std::vector<uint32_t> & expectedDims)701 std::string DescribeMutationWithDimensions(const OperandTypeWithExtraParams& origin,
702 const std::vector<uint32_t>& expectedDims) {
703 std::ostringstream osstream;
704 osstream << MutationWithDimensions(origin, expectedDims);
705 return osstream.str();
706 }
707
MATCHER_P2(IsMutationWithDimensions,origin,expectedDims,DescribeMutationWithDimensions (origin,expectedDims))708 MATCHER_P2(IsMutationWithDimensions, origin, expectedDims,
709 DescribeMutationWithDimensions(origin, expectedDims)) {
710 return arg == MutationWithDimensions(origin, expectedDims);
711 }
712
TEST(TensorRankConstraint,ExactlyWillReturnSameInputAsValidMutation)713 TEST(TensorRankConstraint, ExactlyWillReturnSameInputAsValidMutation) {
714 uint32_t opDimensions[3] = {2, 2, 2};
715 OperandTypeWithExtraParams operand{ANeuralNetworksOperandType{
716 .type = ANEURALNETWORKS_TENSOR_INT32,
717 .dimensionCount = 3,
718 .dimensions = opDimensions,
719 }};
720
721 auto constraint = TensorRankConstraint::Exactly(3);
722 auto validMutationSet = constraint.MutationsWithValidRank({operand});
723 ASSERT_EQ(validMutationSet.size(), 1u);
724 auto validMutations = *validMutationSet.begin();
725 ASSERT_EQ(validMutations.size(), 1u);
726 EXPECT_THAT(validMutations[0],
727 IsMutationWithDimensions(operand, std::vector<uint32_t>({2, 2, 2})));
728 };
729
TEST(TensorRankConstraint,ExactlyWillFailIfValidInputHasInvalidSize)730 TEST(TensorRankConstraint, ExactlyWillFailIfValidInputHasInvalidSize) {
731 uint32_t opDimensions[2] = {2, 2};
732 OperandTypeWithExtraParams operand{ANeuralNetworksOperandType{
733 .type = ANEURALNETWORKS_TENSOR_INT32,
734 .dimensionCount = 2,
735 .dimensions = opDimensions,
736 }};
737 EXPECT_DEATH(TensorRankConstraint::Exactly(3).MutationsWithValidRank({operand}),
738 ".*assertion.+failed.*");
739 };
740
TEST(TensorRankConstraint,ExactlyWillReturnTwoInvalidMutationsWithLowerAndHigherRank)741 TEST(TensorRankConstraint, ExactlyWillReturnTwoInvalidMutationsWithLowerAndHigherRank) {
742 uint32_t opDimensions[3] = {2, 2, 2};
743 OperandTypeWithExtraParams operand{ANeuralNetworksOperandType{
744 .type = ANEURALNETWORKS_TENSOR_INT32,
745 .dimensionCount = 3,
746 .dimensions = opDimensions,
747 }};
748
749 auto constraint = TensorRankConstraint::Exactly(3);
750 auto invalidMutations = constraint.MutationsWithInvalidRank({operand});
751 ASSERT_EQ(invalidMutations.size(), 2u);
752 std::for_each(invalidMutations.begin(), invalidMutations.end(),
753 [&operand](const std::vector<OperandTypeWithExtraParams>& mutations) {
754 EXPECT_EQ(mutations.size(), 1u);
755 if (mutations.size() == 1) {
756 EXPECT_THAT(
757 mutations[0],
758 ::testing::AnyOf(
759 IsMutationWithDimensions(operand,
760 std::vector<uint32_t>({2, 2})),
761 IsMutationWithDimensions(
762 operand, std::vector<uint32_t>({2, 2, 2, 1}))));
763 }
764 });
765 };
766
TEST(TensorRankConstraint,AtLeastWillReturnTwoValidMutationsAboveThreshold)767 TEST(TensorRankConstraint, AtLeastWillReturnTwoValidMutationsAboveThreshold) {
768 uint32_t opDimensions[3] = {2, 2, 2};
769 OperandTypeWithExtraParams operand{ANeuralNetworksOperandType{
770 .type = ANEURALNETWORKS_TENSOR_INT32,
771 .dimensionCount = 2,
772 .dimensions = opDimensions,
773 }};
774
775 auto constraint = TensorRankConstraint::AtLeast(1);
776 auto invalidMutations =
777 constraint.MutationsWithValidRank({(OperandTypeWithExtraParams)operand});
778 ASSERT_EQ(invalidMutations.size(), 2u);
779 std::for_each(
780 invalidMutations.begin(), invalidMutations.end(),
781 [&operand](const std::vector<OperandTypeWithExtraParams>& mutations) {
782 EXPECT_EQ(mutations.size(), 1u);
783 if (mutations.size() == 1) {
784 EXPECT_THAT(mutations[0],
785 ::testing::AnyOf(IsMutationWithDimensions(
786 operand, std::vector<uint32_t>({2})),
787 IsMutationWithDimensions(
788 operand, std::vector<uint32_t>({2, 2}))));
789 }
790 });
791 }
792
TEST(TensorRankConstraint,AtLeastWillReturnOneInvalidMutationsBelowThreshold)793 TEST(TensorRankConstraint, AtLeastWillReturnOneInvalidMutationsBelowThreshold) {
794 uint32_t opDimensions[2] = {2, 2};
795 OperandTypeWithExtraParams operand{ANeuralNetworksOperandType{
796 .type = ANEURALNETWORKS_TENSOR_INT32,
797 .dimensionCount = 2,
798 .dimensions = opDimensions,
799 }};
800
801 auto constraint = TensorRankConstraint::AtLeast(2);
802 auto invalidMutations =
803 constraint.MutationsWithInvalidRank({(OperandTypeWithExtraParams)operand});
804 ASSERT_EQ(invalidMutations.size(), 1u);
805 auto invalidMutationVector = *invalidMutations.begin();
806 ASSERT_EQ(invalidMutationVector.size(), 1u);
807 ASSERT_THAT(invalidMutationVector[0],
808 IsMutationWithDimensions(operand, std::vector<uint32_t>({2})));
809 }
810
TEST(TensorRankConstraint,AtLeastWillReturnNoInvalidMutationsIfThresholdIs1)811 TEST(TensorRankConstraint, AtLeastWillReturnNoInvalidMutationsIfThresholdIs1) {
812 uint32_t opDimensions[1] = {2};
813 OperandTypeWithExtraParams operand{ANeuralNetworksOperandType{
814 .type = ANEURALNETWORKS_TENSOR_INT32,
815 .dimensionCount = 1,
816 .dimensions = opDimensions,
817 }};
818
819 auto constraint = TensorRankConstraint::AtLeast(1);
820 auto invalidMutations =
821 constraint.MutationsWithInvalidRank({(OperandTypeWithExtraParams)operand});
822 ASSERT_EQ(invalidMutations.size(), 0u);
823 }
824
TEST(TensorRankConstraint,UpToWillReturnUpToTwoValidMutationsBelowThreshold)825 TEST(TensorRankConstraint, UpToWillReturnUpToTwoValidMutationsBelowThreshold) {
826 uint32_t opDimensions[3] = {2, 2, 2};
827 OperandTypeWithExtraParams operand{ANeuralNetworksOperandType{
828 .type = ANEURALNETWORKS_TENSOR_INT32,
829 .dimensionCount = 2,
830 .dimensions = opDimensions,
831 }};
832
833 auto constraint = TensorRankConstraint::UpTo(3);
834 auto invalidMutations =
835 constraint.MutationsWithValidRank({(OperandTypeWithExtraParams)operand});
836
837 auto expected = std::vector<uint32_t>({7, 7});
838 ASSERT_EQ(invalidMutations.size(), 2u);
839 std::for_each(invalidMutations.begin(), invalidMutations.end(),
840 [&operand](const std::vector<OperandTypeWithExtraParams>& mutations) {
841 EXPECT_EQ(mutations.size(), 1u);
842 if (mutations.size() == 1) {
843 EXPECT_THAT(mutations[0],
844 ::testing::AnyOf(
845 IsMutationWithDimensions(operand,
846 std::vector<uint32_t>({2})),
847 IsMutationWithDimensions(
848 operand, std::vector<uint32_t>({2, 2, 1}))));
849 }
850 });
851 }
852
TEST(TensorRankConstraint,UpToWillReturnOneInvalidMutationsAboveThreshold)853 TEST(TensorRankConstraint, UpToWillReturnOneInvalidMutationsAboveThreshold) {
854 uint32_t opDimensions[3] = {2, 2, 2};
855 OperandTypeWithExtraParams operand{ANeuralNetworksOperandType{
856 .type = ANEURALNETWORKS_TENSOR_INT32,
857 .dimensionCount = 3,
858 .dimensions = opDimensions,
859 }};
860
861 auto constraint = TensorRankConstraint::UpTo(3);
862 auto invalidMutations =
863 constraint.MutationsWithInvalidRank({(OperandTypeWithExtraParams)operand});
864 ASSERT_EQ(invalidMutations.size(), 1u);
865 auto invalidMutationVector = *invalidMutations.begin();
866 ASSERT_EQ(invalidMutationVector.size(), 1u);
867 ASSERT_THAT(invalidMutationVector[0],
868 IsMutationWithDimensions(operand, std::vector<uint32_t>({2, 2, 2, 1})));
869 }
870
TEST(TensorRankConstraint,BetweenWillReturnTwoValidMutationsOnRangeBoundaries)871 TEST(TensorRankConstraint, BetweenWillReturnTwoValidMutationsOnRangeBoundaries) {
872 uint32_t opDimensions[3] = {2, 2, 2};
873 OperandTypeWithExtraParams operand{ANeuralNetworksOperandType{
874 .type = ANEURALNETWORKS_TENSOR_INT32,
875 .dimensionCount = 3,
876 .dimensions = opDimensions,
877 }};
878
879 auto constraint = TensorRankConstraint::Between(2, 4);
880 auto validMutations = constraint.MutationsWithValidRank({(OperandTypeWithExtraParams)operand});
881 ASSERT_EQ(validMutations.size(), 2u);
882 std::for_each(validMutations.begin(), validMutations.end(),
883 [&operand](const std::vector<OperandTypeWithExtraParams>& mutations) {
884 EXPECT_EQ(mutations.size(), 1u);
885 if (mutations.size() == 1) {
886 EXPECT_THAT(
887 mutations[0],
888 ::testing::AnyOf(
889 IsMutationWithDimensions(operand,
890 std::vector<uint32_t>({2, 2})),
891 IsMutationWithDimensions(
892 operand, std::vector<uint32_t>({2, 2, 2, 1}))));
893 }
894 });
895 }
896
TEST(TensorRankConstraint,BetweenWillReturnTwoInvValidMutationsAdjacentToRangeBoundaries)897 TEST(TensorRankConstraint, BetweenWillReturnTwoInvValidMutationsAdjacentToRangeBoundaries) {
898 uint32_t opDimensions[3] = {2, 2, 2};
899 OperandTypeWithExtraParams operand{ANeuralNetworksOperandType{
900 .type = ANEURALNETWORKS_TENSOR_INT32,
901 .dimensionCount = 3,
902 .dimensions = opDimensions,
903 }};
904
905 auto constraint = TensorRankConstraint::Between(2, 4);
906 auto validMutations =
907 constraint.MutationsWithInvalidRank({(OperandTypeWithExtraParams)operand});
908 ASSERT_EQ(validMutations.size(), 2u);
909 std::for_each(
910 validMutations.begin(), validMutations.end(),
911 [&operand](const std::vector<OperandTypeWithExtraParams>& mutations) {
912 EXPECT_EQ(mutations.size(), 1u);
913 if (mutations.size() == 1) {
914 EXPECT_THAT(
915 mutations[0],
916 ::testing::AnyOf(
917 IsMutationWithDimensions(operand, std::vector<uint32_t>({2})),
918 IsMutationWithDimensions(
919 operand, std::vector<uint32_t>({2, 2, 2, 1, 1}))));
920 }
921 });
922 }
923
TEST(TensorRankConstraint,BetweenWillReturnOneInvalidMutationsOnlyIfLowerBoundIs1)924 TEST(TensorRankConstraint, BetweenWillReturnOneInvalidMutationsOnlyIfLowerBoundIs1) {
925 uint32_t opDimensions[3] = {2, 2, 2};
926 OperandTypeWithExtraParams operand{ANeuralNetworksOperandType{
927 .type = ANEURALNETWORKS_TENSOR_INT32,
928 .dimensionCount = 3,
929 .dimensions = opDimensions,
930 }};
931
932 auto constraint = TensorRankConstraint::Between(1, 4);
933 auto invalidMutations =
934 constraint.MutationsWithInvalidRank({(OperandTypeWithExtraParams)operand});
935 ASSERT_EQ(invalidMutations.size(), 1u);
936 auto invalidMutationVector = *invalidMutations.begin();
937 ASSERT_EQ(invalidMutationVector.size(), 1u);
938 ASSERT_THAT(invalidMutationVector[0],
939 IsMutationWithDimensions(operand, std::vector<uint32_t>({2, 2, 2, 1, 1})));
940 }
941
TEST(TensorRankMutator,AppliesConstraintToInputsAtGivenInputsToGenerateValidMutations)942 TEST(TensorRankMutator, AppliesConstraintToInputsAtGivenInputsToGenerateValidMutations) {
943 uint32_t opDimensions0[2] = {0, 0};
944 OperandTypeWithExtraParams operand0{ANeuralNetworksOperandType{
945 .type = ANEURALNETWORKS_TENSOR_INT32,
946 .dimensionCount = 2,
947 .dimensions = opDimensions0,
948 }};
949 uint32_t opDimensions1[1] = {1};
950 OperandTypeWithExtraParams operand1{ANeuralNetworksOperandType{
951 .type = ANEURALNETWORKS_TENSOR_INT32,
952 .dimensionCount = 1,
953 .dimensions = opDimensions1,
954 }};
955 uint32_t opDimensions2[2] = {2, 2};
956 OperandTypeWithExtraParams operand2{ANeuralNetworksOperandType{
957 .type = ANEURALNETWORKS_TENSOR_INT32,
958 .dimensionCount = 2,
959 .dimensions = opDimensions2,
960 }};
961 TensorRankMutator mutator{TensorRankConstraint::AtLeast(2), {0, 2}};
962
963 const auto mutationSet = mutator.ValidInputsMutations({operand0, operand1, operand2});
964 ASSERT_EQ(mutationSet.size(), 2u);
965 std::for_each(mutationSet.begin(), mutationSet.end(),
966 [&](const std::vector<OperandTypeWithExtraParams>& mutatedInputs) {
967 EXPECT_EQ(mutatedInputs.size(), 3u);
968 if (mutatedInputs.size() == 3) {
969 EXPECT_EQ(mutatedInputs[0].operandType.dimensionCount,
970 mutatedInputs[2].operandType.dimensionCount);
971 EXPECT_THAT(mutatedInputs[0],
972 ::testing::AnyOf(
973 IsMutationWithDimensions(
974 operand0, std::vector<uint32_t>({0, 0})),
975 IsMutationWithDimensions(
976 operand0, std::vector<uint32_t>({0, 0, 1}))));
977
978 EXPECT_EQ(mutatedInputs[1], operand1);
979
980 EXPECT_THAT(mutatedInputs[2],
981 ::testing::AnyOf(
982 IsMutationWithDimensions(
983 operand2, std::vector<uint32_t>({2, 2})),
984 IsMutationWithDimensions(
985 operand2, std::vector<uint32_t>({2, 2, 1}))));
986 }
987 });
988 }
989
TEST(TensorRankMutator,AppliesConstraintToInputsAtGivenInputsToGenerateInvalidMutations)990 TEST(TensorRankMutator, AppliesConstraintToInputsAtGivenInputsToGenerateInvalidMutations) {
991 uint32_t opDimensions0[2] = {0, 0};
992 OperandTypeWithExtraParams operand0{ANeuralNetworksOperandType{
993 .type = ANEURALNETWORKS_TENSOR_INT32,
994 .dimensionCount = 2,
995 .dimensions = opDimensions0,
996 }};
997 uint32_t opDimensions1[1] = {1};
998 OperandTypeWithExtraParams operand1{ANeuralNetworksOperandType{
999 .type = ANEURALNETWORKS_TENSOR_INT32,
1000 .dimensionCount = 1,
1001 .dimensions = opDimensions1,
1002 }};
1003 uint32_t opDimensions2[2] = {2, 2};
1004 OperandTypeWithExtraParams operand2{ANeuralNetworksOperandType{
1005 .type = ANEURALNETWORKS_TENSOR_INT32,
1006 .dimensionCount = 2,
1007 .dimensions = opDimensions2,
1008 }};
1009 TensorRankMutator mutator{TensorRankConstraint::AtLeast(2), {0, 2}};
1010
1011 const auto mutationSet = mutator.InvalidInputsMutations({operand0, operand1, operand2});
1012 ASSERT_EQ(mutationSet.size(), 1u);
1013 std::for_each(
1014 mutationSet.begin(), mutationSet.end(),
1015 [&](const std::vector<OperandTypeWithExtraParams>& mutatedInputs) {
1016 EXPECT_EQ(mutatedInputs.size(), 3u);
1017 if (mutatedInputs.size() == 3) {
1018 EXPECT_THAT(mutatedInputs[0],
1019 IsMutationWithDimensions(operand0, std::vector<uint32_t>({0})));
1020
1021 EXPECT_EQ(mutatedInputs[1], operand1);
1022
1023 EXPECT_THAT(mutatedInputs[2],
1024 IsMutationWithDimensions(operand2, std::vector<uint32_t>({2})));
1025 }
1026 });
1027 }
1028
argMinMaxTest(ANeuralNetworksOperationType operationCode,int32_t inputOperandType)1029 void argMinMaxTest(ANeuralNetworksOperationType operationCode, int32_t inputOperandType) {
1030 SCOPED_TRACE(inputOperandType);
1031 uint32_t inputDimensions[4] = {2, 2, 2, 2};
1032 ANeuralNetworksOperandType input0 = getOpType(inputOperandType, 4, inputDimensions);
1033 ANeuralNetworksOperandType axis = {
1034 .type = ANEURALNETWORKS_INT32,
1035 .dimensionCount = 0,
1036 .dimensions = nullptr,
1037 };
1038 uint32_t outputDimensions[3] = {2, 2, 2};
1039 ANeuralNetworksOperandType output = {
1040 .type = ANEURALNETWORKS_TENSOR_INT32,
1041 .dimensionCount = 3,
1042 .dimensions = outputDimensions,
1043 };
1044 OperationTestBase test(operationCode, {input0, axis}, {output});
1045 test.testOpsValidations();
1046 }
1047
TEST(OperationValidationTest,ARGMIN)1048 TEST(OperationValidationTest, ARGMIN) {
1049 argMinMaxTest(ANEURALNETWORKS_ARGMIN, ANEURALNETWORKS_TENSOR_FLOAT16);
1050 argMinMaxTest(ANEURALNETWORKS_ARGMIN, ANEURALNETWORKS_TENSOR_FLOAT32);
1051 argMinMaxTest(ANEURALNETWORKS_ARGMIN, ANEURALNETWORKS_TENSOR_INT32);
1052 argMinMaxTest(ANEURALNETWORKS_ARGMIN, ANEURALNETWORKS_TENSOR_QUANT8_ASYMM);
1053 argMinMaxTest(ANEURALNETWORKS_ARGMIN, ANEURALNETWORKS_TENSOR_QUANT8_ASYMM_SIGNED);
1054 }
1055
TEST(OperationValidationTest,ARGMAX)1056 TEST(OperationValidationTest, ARGMAX) {
1057 argMinMaxTest(ANEURALNETWORKS_ARGMAX, ANEURALNETWORKS_TENSOR_FLOAT16);
1058 argMinMaxTest(ANEURALNETWORKS_ARGMAX, ANEURALNETWORKS_TENSOR_FLOAT32);
1059 argMinMaxTest(ANEURALNETWORKS_ARGMAX, ANEURALNETWORKS_TENSOR_INT32);
1060 argMinMaxTest(ANEURALNETWORKS_ARGMAX, ANEURALNETWORKS_TENSOR_QUANT8_ASYMM);
1061 argMinMaxTest(ANEURALNETWORKS_ARGMAX, ANEURALNETWORKS_TENSOR_QUANT8_ASYMM_SIGNED);
1062 }
1063
dequantizeOpTest(int32_t inputOperandType,int32_t outputOperandType)1064 void dequantizeOpTest(int32_t inputOperandType, int32_t outputOperandType) {
1065 SCOPED_TRACE(testing::Message()
1066 << "inputType: " << inputOperandType << ", outputType: " << outputOperandType);
1067 uint32_t inputDimensions[4] = {2, 2, 2, 2};
1068 ANeuralNetworksOperandType input = getOpType(inputOperandType, 4, inputDimensions);
1069 ANeuralNetworksOperandType output = getOpType(outputOperandType, 4, inputDimensions);
1070 OperationTestBase dequantizeTest(ANEURALNETWORKS_DEQUANTIZE, {input}, {output},
1071 {{TensorRankConstraint::UpTo(4)}});
1072 dequantizeTest.testOpsValidations();
1073 }
1074
TEST(OperationValidationTest,DEQUANTIZE)1075 TEST(OperationValidationTest, DEQUANTIZE) {
1076 dequantizeOpTest(ANEURALNETWORKS_TENSOR_QUANT8_ASYMM, ANEURALNETWORKS_TENSOR_FLOAT16);
1077 dequantizeOpTest(ANEURALNETWORKS_TENSOR_QUANT8_ASYMM, ANEURALNETWORKS_TENSOR_FLOAT32);
1078 dequantizeOpTest(ANEURALNETWORKS_TENSOR_QUANT8_SYMM, ANEURALNETWORKS_TENSOR_FLOAT16);
1079 dequantizeOpTest(ANEURALNETWORKS_TENSOR_QUANT8_SYMM, ANEURALNETWORKS_TENSOR_FLOAT32);
1080 dequantizeOpTest(ANEURALNETWORKS_TENSOR_QUANT8_SYMM_PER_CHANNEL,
1081 ANEURALNETWORKS_TENSOR_FLOAT16);
1082 dequantizeOpTest(ANEURALNETWORKS_TENSOR_QUANT8_SYMM_PER_CHANNEL,
1083 ANEURALNETWORKS_TENSOR_FLOAT32);
1084 dequantizeOpTest(ANEURALNETWORKS_TENSOR_QUANT8_ASYMM_SIGNED, ANEURALNETWORKS_TENSOR_FLOAT16);
1085 dequantizeOpTest(ANEURALNETWORKS_TENSOR_QUANT8_ASYMM_SIGNED, ANEURALNETWORKS_TENSOR_FLOAT32);
1086 }
1087
expandDimsTest(int32_t inputOperandType)1088 void expandDimsTest(int32_t inputOperandType) {
1089 SCOPED_TRACE(inputOperandType);
1090 uint32_t inputDimensions[4] = {2, 2, 2, 2};
1091 ANeuralNetworksOperandType input0 = getOpType(inputOperandType, 4, inputDimensions);
1092 ANeuralNetworksOperandType axis = {
1093 .type = ANEURALNETWORKS_INT32,
1094 .dimensionCount = 0,
1095 .dimensions = nullptr,
1096 };
1097 uint32_t outputDimensions[5] = {2, 2, 2, 2, 2};
1098 ANeuralNetworksOperandType output = getOpType(inputOperandType, 5, outputDimensions);
1099 OperationTestBase test(ANEURALNETWORKS_EXPAND_DIMS, {input0, axis}, {output});
1100 test.testOpsValidations();
1101 }
1102
TEST(OperationValidationTest,EXPAND_DIMS)1103 TEST(OperationValidationTest, EXPAND_DIMS) {
1104 expandDimsTest(ANEURALNETWORKS_TENSOR_FLOAT16);
1105 expandDimsTest(ANEURALNETWORKS_TENSOR_FLOAT32);
1106 expandDimsTest(ANEURALNETWORKS_TENSOR_INT32);
1107 expandDimsTest(ANEURALNETWORKS_TENSOR_QUANT8_ASYMM);
1108 expandDimsTest(ANEURALNETWORKS_TENSOR_QUANT8_ASYMM_SIGNED);
1109 }
1110
gatherTest(int32_t inputOperandType)1111 void gatherTest(int32_t inputOperandType) {
1112 SCOPED_TRACE(inputOperandType);
1113 uint32_t inputDimensions[4] = {2, 2, 2, 2};
1114 ANeuralNetworksOperandType input0 = getOpType(inputOperandType, 4, inputDimensions);
1115 ANeuralNetworksOperandType axis = {
1116 .type = ANEURALNETWORKS_INT32,
1117 .dimensionCount = 0,
1118 .dimensions = nullptr,
1119 };
1120 ANeuralNetworksOperandType input2 = {
1121 .type = ANEURALNETWORKS_TENSOR_INT32,
1122 .dimensionCount = 4,
1123 .dimensions = inputDimensions,
1124 };
1125 uint32_t outputDimensions[7] = {2, 2, 2, 2, 2, 2, 2};
1126 ANeuralNetworksOperandType output = getOpType(inputOperandType, 7, outputDimensions);
1127 OperationTestBase test(ANEURALNETWORKS_GATHER, {input0, axis, input2}, {output});
1128 test.testOpsValidations();
1129 }
1130
TEST(OperationValidationTest,GATHER)1131 TEST(OperationValidationTest, GATHER) {
1132 gatherTest(ANEURALNETWORKS_TENSOR_FLOAT16);
1133 gatherTest(ANEURALNETWORKS_TENSOR_FLOAT32);
1134 gatherTest(ANEURALNETWORKS_TENSOR_INT32);
1135 gatherTest(ANEURALNETWORKS_TENSOR_QUANT8_ASYMM);
1136 gatherTest(ANEURALNETWORKS_TENSOR_QUANT8_ASYMM_SIGNED);
1137 }
1138
quantizeOpTest(int32_t inputOperandCode,int32_t outputOperandCode)1139 void quantizeOpTest(int32_t inputOperandCode, int32_t outputOperandCode) {
1140 uint32_t inputDimensions[4] = {2, 2, 2, 2};
1141 ANeuralNetworksOperandType input = {
1142 .type = inputOperandCode, .dimensionCount = 4, .dimensions = inputDimensions};
1143 ANeuralNetworksOperandType output = {.type = outputOperandCode,
1144 .dimensionCount = 4,
1145 .dimensions = inputDimensions,
1146 .scale = 1.0f,
1147 .zeroPoint = 0};
1148 OperationTestBase test(ANEURALNETWORKS_QUANTIZE, {input}, {output});
1149 test.testOpsValidations();
1150 }
1151
TEST(OperationValidationTest,QUANTIZE_float16)1152 TEST(OperationValidationTest, QUANTIZE_float16) {
1153 quantizeOpTest(ANEURALNETWORKS_TENSOR_FLOAT16, ANEURALNETWORKS_TENSOR_QUANT8_ASYMM);
1154 quantizeOpTest(ANEURALNETWORKS_TENSOR_FLOAT16, ANEURALNETWORKS_TENSOR_QUANT8_ASYMM_SIGNED);
1155 }
1156
TEST(OperationValidationTest,QUANTIZE_float32)1157 TEST(OperationValidationTest, QUANTIZE_float32) {
1158 quantizeOpTest(ANEURALNETWORKS_TENSOR_FLOAT32, ANEURALNETWORKS_TENSOR_QUANT8_ASYMM);
1159 quantizeOpTest(ANEURALNETWORKS_TENSOR_FLOAT32, ANEURALNETWORKS_TENSOR_QUANT8_ASYMM_SIGNED);
1160 }
1161
TEST(OperationValidationTest,QUANTIZED_16BIT_LSTM)1162 TEST(OperationValidationTest, QUANTIZED_16BIT_LSTM) {
1163 uint32_t oneDimensional[1] = {5};
1164 uint32_t twoDimensional[2] = {5, 5};
1165
1166 ANeuralNetworksOperandType int32Tensor1D = {
1167 .type = ANEURALNETWORKS_TENSOR_INT32,
1168 .dimensionCount = 1,
1169 .dimensions = oneDimensional,
1170 .scale = 0.0000318,
1171 .zeroPoint = 0,
1172 };
1173 ANeuralNetworksOperandType quant8Tensor2D = {
1174 .type = ANEURALNETWORKS_TENSOR_QUANT8_ASYMM,
1175 .dimensionCount = 2,
1176 .dimensions = twoDimensional,
1177 .scale = 0.00408021,
1178 .zeroPoint = 100,
1179 };
1180 ANeuralNetworksOperandType quant16Tensor2D = {
1181 .type = ANEURALNETWORKS_TENSOR_QUANT16_SYMM,
1182 .dimensionCount = 2,
1183 .dimensions = twoDimensional,
1184 .scale = 1.0 / 2048,
1185 .zeroPoint = 0,
1186 };
1187
1188 ANeuralNetworksOperandType input = quant8Tensor2D;
1189 ANeuralNetworksOperandType input_to_input_weights = quant8Tensor2D;
1190 ANeuralNetworksOperandType input_to_forget_weights = quant8Tensor2D;
1191 ANeuralNetworksOperandType input_to_cell_weights = quant8Tensor2D;
1192 ANeuralNetworksOperandType input_to_output_weights = quant8Tensor2D;
1193 ANeuralNetworksOperandType recurrent_to_input_weights = quant8Tensor2D;
1194 ANeuralNetworksOperandType recurrent_to_forget_weights = quant8Tensor2D;
1195 ANeuralNetworksOperandType recurrent_to_cell_weights = quant8Tensor2D;
1196 ANeuralNetworksOperandType recurrent_to_output_weights = quant8Tensor2D;
1197 ANeuralNetworksOperandType input_gate_bias = int32Tensor1D;
1198 ANeuralNetworksOperandType forget_gate_bias = int32Tensor1D;
1199 ANeuralNetworksOperandType cell_gate_bias = int32Tensor1D;
1200 ANeuralNetworksOperandType output_gate_bias = int32Tensor1D;
1201 ANeuralNetworksOperandType prev_cell_state = quant16Tensor2D;
1202 ANeuralNetworksOperandType prev_output = quant8Tensor2D;
1203
1204 ANeuralNetworksOperandType cell_state_out = quant16Tensor2D;
1205 ANeuralNetworksOperandType output = quant8Tensor2D;
1206
1207 OperationTestBase test(
1208 ANEURALNETWORKS_QUANTIZED_16BIT_LSTM,
1209 {input, input_to_input_weights, input_to_forget_weights, input_to_cell_weights,
1210 input_to_output_weights, recurrent_to_input_weights, recurrent_to_forget_weights,
1211 recurrent_to_cell_weights, recurrent_to_output_weights, input_gate_bias,
1212 forget_gate_bias, cell_gate_bias, output_gate_bias, prev_cell_state, prev_output},
1213 {cell_state_out, output});
1214 test.testOpsValidations();
1215 }
1216
splitTest(int32_t inputOperandType)1217 void splitTest(int32_t inputOperandType) {
1218 SCOPED_TRACE(inputOperandType);
1219 uint32_t inputDimensions[4] = {2, 2, 2, 2};
1220 ANeuralNetworksOperandType input0 = getOpType(inputOperandType, 4, inputDimensions);
1221 ANeuralNetworksOperandType axis = {
1222 .type = ANEURALNETWORKS_INT32,
1223 .dimensionCount = 0,
1224 .dimensions = nullptr,
1225 };
1226 ANeuralNetworksOperandType count = {
1227 .type = ANEURALNETWORKS_INT32,
1228 .dimensionCount = 0,
1229 .dimensions = nullptr,
1230 };
1231 uint32_t outputDimensions[2] = {2, 2};
1232 ANeuralNetworksOperandType output0 = getOpType(inputOperandType, 2, outputDimensions);
1233 ANeuralNetworksOperandType output1 = getOpType(inputOperandType, 2, outputDimensions);
1234 OperationTestBase test(ANEURALNETWORKS_SPLIT, {input0, axis, count}, {output0, output1});
1235 test.testOpsValidations();
1236 }
1237
TEST(OperationValidationTest,SPLIT)1238 TEST(OperationValidationTest, SPLIT) {
1239 splitTest(ANEURALNETWORKS_TENSOR_FLOAT16);
1240 splitTest(ANEURALNETWORKS_TENSOR_FLOAT32);
1241 splitTest(ANEURALNETWORKS_TENSOR_INT32);
1242 splitTest(ANEURALNETWORKS_TENSOR_QUANT8_ASYMM);
1243 splitTest(ANEURALNETWORKS_TENSOR_QUANT8_ASYMM_SIGNED);
1244 }
1245
tileTest(int32_t inputOperandType)1246 void tileTest(int32_t inputOperandType) {
1247 SCOPED_TRACE(inputOperandType);
1248 uint32_t inputDimensions[4] = {2, 2, 2, 2};
1249 ANeuralNetworksOperandType input0 = getOpType(inputOperandType, 4, inputDimensions);
1250 uint32_t multiplesDimensions[1] = {4};
1251 ANeuralNetworksOperandType multiples = {
1252 .type = ANEURALNETWORKS_TENSOR_INT32,
1253 .dimensionCount = 1,
1254 .dimensions = multiplesDimensions,
1255 };
1256 uint32_t outputDimensions[8] = {2, 2, 2, 2, 2, 2, 2, 2};
1257 ANeuralNetworksOperandType output0 = getOpType(inputOperandType, 8, outputDimensions);
1258 OperationTestBase test(ANEURALNETWORKS_TILE, {input0, multiples}, {output0});
1259 test.testOpsValidations();
1260 }
1261
TEST(OperationValidationTest,TILE)1262 TEST(OperationValidationTest, TILE) {
1263 tileTest(ANEURALNETWORKS_TENSOR_FLOAT16);
1264 tileTest(ANEURALNETWORKS_TENSOR_FLOAT32);
1265 tileTest(ANEURALNETWORKS_TENSOR_INT32);
1266 tileTest(ANEURALNETWORKS_TENSOR_QUANT8_ASYMM);
1267 tileTest(ANEURALNETWORKS_TENSOR_QUANT8_ASYMM_SIGNED);
1268 }
1269
topkV2Test(int32_t inputOperandType)1270 void topkV2Test(int32_t inputOperandType) {
1271 SCOPED_TRACE(inputOperandType);
1272 uint32_t inputDimensions[4] = {4, 5, 6, 7};
1273 ANeuralNetworksOperandType input = getOpType(inputOperandType, 4, inputDimensions);
1274 ANeuralNetworksOperandType k = getOpType(ANEURALNETWORKS_INT32);
1275 uint32_t outputDimensions[4] = {4, 5, 6, 3};
1276 ANeuralNetworksOperandType outputValues = getOpType(inputOperandType, 4, outputDimensions);
1277 ANeuralNetworksOperandType outputIndices =
1278 getOpType(ANEURALNETWORKS_TENSOR_INT32, 4, outputDimensions);
1279 OperationTestBase test(ANEURALNETWORKS_TOPK_V2, {input, k}, {outputValues, outputIndices});
1280 test.testOpsValidations();
1281 }
1282
TEST(OperationValidationTest,TOPK_V2)1283 TEST(OperationValidationTest, TOPK_V2) {
1284 topkV2Test(ANEURALNETWORKS_TENSOR_FLOAT16);
1285 topkV2Test(ANEURALNETWORKS_TENSOR_FLOAT32);
1286 topkV2Test(ANEURALNETWORKS_TENSOR_INT32);
1287 topkV2Test(ANEURALNETWORKS_TENSOR_QUANT8_ASYMM);
1288 topkV2Test(ANEURALNETWORKS_TENSOR_QUANT8_ASYMM_SIGNED);
1289 }
1290
simpleMathOpTest(ANeuralNetworksOperationType operationCode,int32_t operandCode)1291 void simpleMathOpTest(ANeuralNetworksOperationType operationCode, int32_t operandCode) {
1292 uint32_t inputDimensions[4] = {2, 2, 2, 2};
1293 ANeuralNetworksOperandType input1 = getOpType(operandCode, 4, inputDimensions);
1294
1295 ANeuralNetworksOperandType input2 = input1;
1296 ANeuralNetworksOperandType output = input1;
1297 ANeuralNetworksOperandType activation = {.type = ANEURALNETWORKS_INT32,
1298 .dimensionCount = 0,
1299 .dimensions = nullptr,
1300 .scale = 0.0f,
1301 .zeroPoint = 0};
1302
1303 OperationTestBase simpleMathTest(
1304 operationCode, {input1, input2, activation}, {output},
1305 {{TensorRankConstraint::UpTo(4), {0}}, {TensorRankConstraint::UpTo(4), {1}}});
1306 simpleMathTest.testOpsValidations();
1307 }
1308
TEST(OperationValidationTest,ADD_float16)1309 TEST(OperationValidationTest, ADD_float16) {
1310 simpleMathOpTest(ANEURALNETWORKS_ADD, ANEURALNETWORKS_TENSOR_FLOAT16);
1311 }
1312
TEST(OperationValidationTest,ADD_float32)1313 TEST(OperationValidationTest, ADD_float32) {
1314 simpleMathOpTest(ANEURALNETWORKS_ADD, ANEURALNETWORKS_TENSOR_FLOAT32);
1315 }
1316
TEST(OperationValidationTest,ADD_quant8)1317 TEST(OperationValidationTest, ADD_quant8) {
1318 simpleMathOpTest(ANEURALNETWORKS_ADD, ANEURALNETWORKS_TENSOR_QUANT8_ASYMM);
1319 }
1320
TEST(OperationValidationTest,ADD_quant8_signed)1321 TEST(OperationValidationTest, ADD_quant8_signed) {
1322 simpleMathOpTest(ANEURALNETWORKS_ADD, ANEURALNETWORKS_TENSOR_QUANT8_ASYMM_SIGNED);
1323 }
1324
TEST(OperationValidationTest,ADD_int32)1325 TEST(OperationValidationTest, ADD_int32) {
1326 simpleMathOpTest(ANEURALNETWORKS_ADD, ANEURALNETWORKS_TENSOR_INT32);
1327 }
1328
TEST(OperationValidationTest,MUL_float16)1329 TEST(OperationValidationTest, MUL_float16) {
1330 simpleMathOpTest(ANEURALNETWORKS_MUL, ANEURALNETWORKS_TENSOR_FLOAT16);
1331 }
1332
TEST(OperationValidationTest,MUL_float32)1333 TEST(OperationValidationTest, MUL_float32) {
1334 simpleMathOpTest(ANEURALNETWORKS_MUL, ANEURALNETWORKS_TENSOR_FLOAT32);
1335 }
1336
TEST(OperationValidationTest,MUL_quant8)1337 TEST(OperationValidationTest, MUL_quant8) {
1338 simpleMathOpTest(ANEURALNETWORKS_MUL, ANEURALNETWORKS_TENSOR_QUANT8_ASYMM);
1339 }
1340
TEST(OperationValidationTest,MUL_quant8_signed)1341 TEST(OperationValidationTest, MUL_quant8_signed) {
1342 simpleMathOpTest(ANEURALNETWORKS_MUL, ANEURALNETWORKS_TENSOR_QUANT8_ASYMM_SIGNED);
1343 }
1344
TEST(OperationValidationTest,MUL_int32)1345 TEST(OperationValidationTest, MUL_int32) {
1346 simpleMathOpTest(ANEURALNETWORKS_MUL, ANEURALNETWORKS_TENSOR_INT32);
1347 }
1348
TEST(OperationValidationTest,SUB_float16)1349 TEST(OperationValidationTest, SUB_float16) {
1350 simpleMathOpTest(ANEURALNETWORKS_SUB, ANEURALNETWORKS_TENSOR_FLOAT16);
1351 }
1352
TEST(OperationValidationTest,SUB_float32)1353 TEST(OperationValidationTest, SUB_float32) {
1354 simpleMathOpTest(ANEURALNETWORKS_SUB, ANEURALNETWORKS_TENSOR_FLOAT32);
1355 }
1356
TEST(OperationValidationTest,SUB_quant8)1357 TEST(OperationValidationTest, SUB_quant8) {
1358 simpleMathOpTest(ANEURALNETWORKS_SUB, ANEURALNETWORKS_TENSOR_QUANT8_ASYMM);
1359 }
1360
TEST(OperationValidationTest,SUB_quant8_signed)1361 TEST(OperationValidationTest, SUB_quant8_signed) {
1362 simpleMathOpTest(ANEURALNETWORKS_SUB, ANEURALNETWORKS_TENSOR_QUANT8_ASYMM_SIGNED);
1363 }
1364
TEST(OperationValidationTest,SUB_int32)1365 TEST(OperationValidationTest, SUB_int32) {
1366 simpleMathOpTest(ANEURALNETWORKS_SUB, ANEURALNETWORKS_TENSOR_INT32);
1367 }
1368
TEST(OperationValidationTest,DIV_float16)1369 TEST(OperationValidationTest, DIV_float16) {
1370 simpleMathOpTest(ANEURALNETWORKS_DIV, ANEURALNETWORKS_TENSOR_FLOAT16);
1371 }
1372
TEST(OperationValidationTest,DIV_float32)1373 TEST(OperationValidationTest, DIV_float32) {
1374 simpleMathOpTest(ANEURALNETWORKS_DIV, ANEURALNETWORKS_TENSOR_FLOAT32);
1375 }
1376
TEST(OperationValidationTest,DIV_int32)1377 TEST(OperationValidationTest, DIV_int32) {
1378 simpleMathOpTest(ANEURALNETWORKS_DIV, ANEURALNETWORKS_TENSOR_INT32);
1379 }
1380
TEST(OperationValidationTest,MUL_quant8_bad_output_scale)1381 TEST(OperationValidationTest, MUL_quant8_bad_output_scale) {
1382 uint32_t inputDimensions[4] = {2, 2, 2, 2};
1383 ANeuralNetworksOperandType input1 =
1384 getOpType(ANEURALNETWORKS_TENSOR_QUANT8_ASYMM, 4, inputDimensions);
1385 ANeuralNetworksOperandType input2 = input1;
1386 ANeuralNetworksOperandType output = input1;
1387 input1.scale = 1.0f;
1388 input2.scale = 1.0f;
1389 output.scale = 0.5f;
1390 ANeuralNetworksOperandType activation = {.type = ANEURALNETWORKS_INT32,
1391 .dimensionCount = 0,
1392 .dimensions = nullptr,
1393 .scale = 0.0f,
1394 .zeroPoint = 0};
1395
1396 OperationTestBase mulTest(ANEURALNETWORKS_MUL, {input1, input2, activation}, {output});
1397 mulTest.testFailure(ANEURALNETWORKS_BAD_DATA);
1398 }
1399
binaryOpTest(ANeuralNetworksOperationType operationCode,int32_t operandCode)1400 void binaryOpTest(ANeuralNetworksOperationType operationCode, int32_t operandCode) {
1401 uint32_t inputDimensions[] = {2, 2, 2, 2, 2};
1402 ANeuralNetworksOperandType input1 = getOpType(operandCode, 5, inputDimensions);
1403
1404 ANeuralNetworksOperandType input2 = input1;
1405 ANeuralNetworksOperandType output = input1;
1406
1407 OperationTestBase test(operationCode, {input1, input2}, {output});
1408 test.testOpsValidations();
1409 }
1410
TEST(OperationValidationTest,MAXIMUM_float16)1411 TEST(OperationValidationTest, MAXIMUM_float16) {
1412 binaryOpTest(ANEURALNETWORKS_MAXIMUM, ANEURALNETWORKS_TENSOR_FLOAT16);
1413 }
1414
TEST(OperationValidationTest,MAXIMUM_float32)1415 TEST(OperationValidationTest, MAXIMUM_float32) {
1416 binaryOpTest(ANEURALNETWORKS_MAXIMUM, ANEURALNETWORKS_TENSOR_FLOAT32);
1417 }
1418
TEST(OperationValidationTest,MAXIMUM_int32)1419 TEST(OperationValidationTest, MAXIMUM_int32) {
1420 binaryOpTest(ANEURALNETWORKS_MAXIMUM, ANEURALNETWORKS_TENSOR_INT32);
1421 }
1422
TEST(OperationValidationTest,MAXIMUM_quant8)1423 TEST(OperationValidationTest, MAXIMUM_quant8) {
1424 binaryOpTest(ANEURALNETWORKS_MAXIMUM, ANEURALNETWORKS_TENSOR_QUANT8_ASYMM);
1425 }
1426
TEST(OperationValidationTest,MAXIMUM_quant8signed)1427 TEST(OperationValidationTest, MAXIMUM_quant8signed) {
1428 binaryOpTest(ANEURALNETWORKS_MAXIMUM, ANEURALNETWORKS_TENSOR_QUANT8_ASYMM_SIGNED);
1429 }
1430
TEST(OperationValidationTest,MINIMUM_float16)1431 TEST(OperationValidationTest, MINIMUM_float16) {
1432 binaryOpTest(ANEURALNETWORKS_MINIMUM, ANEURALNETWORKS_TENSOR_FLOAT16);
1433 }
1434
TEST(OperationValidationTest,MINIMUM_float32)1435 TEST(OperationValidationTest, MINIMUM_float32) {
1436 binaryOpTest(ANEURALNETWORKS_MINIMUM, ANEURALNETWORKS_TENSOR_FLOAT32);
1437 }
1438
TEST(OperationValidationTest,MINIMUM_int32)1439 TEST(OperationValidationTest, MINIMUM_int32) {
1440 binaryOpTest(ANEURALNETWORKS_MINIMUM, ANEURALNETWORKS_TENSOR_INT32);
1441 }
1442
TEST(OperationValidationTest,MINIMUM_quant8)1443 TEST(OperationValidationTest, MINIMUM_quant8) {
1444 binaryOpTest(ANEURALNETWORKS_MINIMUM, ANEURALNETWORKS_TENSOR_QUANT8_ASYMM);
1445 }
1446
TEST(OperationValidationTest,MINIMUM_quant8signed)1447 TEST(OperationValidationTest, MINIMUM_quant8signed) {
1448 binaryOpTest(ANEURALNETWORKS_MINIMUM, ANEURALNETWORKS_TENSOR_QUANT8_ASYMM_SIGNED);
1449 }
1450
activationOpTest(ANeuralNetworksOperationType operationCode,int32_t operandCode)1451 void activationOpTest(ANeuralNetworksOperationType operationCode, int32_t operandCode) {
1452 uint32_t inputDimensions[4] = {2, 2, 2, 2};
1453 ANeuralNetworksOperandType input = getOpType(operandCode, 4, inputDimensions);
1454
1455 ANeuralNetworksOperandType output = input;
1456 std::vector<TensorRankMutator> inputRankMutators;
1457 if (operationCode == ANEURALNETWORKS_FLOOR || operationCode == ANEURALNETWORKS_LOGISTIC ||
1458 operationCode == ANEURALNETWORKS_RELU || operationCode == ANEURALNETWORKS_RELU1 ||
1459 operationCode == ANEURALNETWORKS_RELU6 || operationCode == ANEURALNETWORKS_TANH) {
1460 inputRankMutators.push_back({TensorRankConstraint::UpTo(4)});
1461 }
1462 OperationTestBase test(operationCode, {input}, {output}, inputRankMutators);
1463 test.testOpsValidations();
1464 }
1465
TEST(OperationValidationTest,ABS_float16)1466 TEST(OperationValidationTest, ABS_float16) {
1467 activationOpTest(ANEURALNETWORKS_ABS, ANEURALNETWORKS_TENSOR_FLOAT16);
1468 }
1469
TEST(OperationValidationTest,ABS_float32)1470 TEST(OperationValidationTest, ABS_float32) {
1471 activationOpTest(ANEURALNETWORKS_ABS, ANEURALNETWORKS_TENSOR_FLOAT32);
1472 }
1473
TEST(OperationValidationTest,ABS_int32)1474 TEST(OperationValidationTest, ABS_int32) {
1475 activationOpTest(ANEURALNETWORKS_ABS, ANEURALNETWORKS_TENSOR_INT32);
1476 }
1477
TEST(OperationValidationTest,EXP_float16)1478 TEST(OperationValidationTest, EXP_float16) {
1479 activationOpTest(ANEURALNETWORKS_EXP, ANEURALNETWORKS_TENSOR_FLOAT16);
1480 }
1481
TEST(OperationValidationTest,EXP_float32)1482 TEST(OperationValidationTest, EXP_float32) {
1483 activationOpTest(ANEURALNETWORKS_EXP, ANEURALNETWORKS_TENSOR_FLOAT32);
1484 }
1485
TEST(OperationValidationTest,LOG_float16)1486 TEST(OperationValidationTest, LOG_float16) {
1487 activationOpTest(ANEURALNETWORKS_LOG, ANEURALNETWORKS_TENSOR_FLOAT16);
1488 }
1489
TEST(OperationValidationTest,LOG_float32)1490 TEST(OperationValidationTest, LOG_float32) {
1491 activationOpTest(ANEURALNETWORKS_LOG, ANEURALNETWORKS_TENSOR_FLOAT32);
1492 }
1493
TEST(OperationValidationTest,RSQRT_float16)1494 TEST(OperationValidationTest, RSQRT_float16) {
1495 activationOpTest(ANEURALNETWORKS_RSQRT, ANEURALNETWORKS_TENSOR_FLOAT16);
1496 }
1497
TEST(OperationValidationTest,RSQRT_float32)1498 TEST(OperationValidationTest, RSQRT_float32) {
1499 activationOpTest(ANEURALNETWORKS_RSQRT, ANEURALNETWORKS_TENSOR_FLOAT32);
1500 }
1501
TEST(OperationValidationTest,SIN_float16)1502 TEST(OperationValidationTest, SIN_float16) {
1503 activationOpTest(ANEURALNETWORKS_SIN, ANEURALNETWORKS_TENSOR_FLOAT16);
1504 }
1505
TEST(OperationValidationTest,SIN_float32)1506 TEST(OperationValidationTest, SIN_float32) {
1507 activationOpTest(ANEURALNETWORKS_SIN, ANEURALNETWORKS_TENSOR_FLOAT32);
1508 }
1509
TEST(OperationValidationTest,SQRT_float16)1510 TEST(OperationValidationTest, SQRT_float16) {
1511 activationOpTest(ANEURALNETWORKS_SQRT, ANEURALNETWORKS_TENSOR_FLOAT16);
1512 }
1513
TEST(OperationValidationTest,SQRT_float32)1514 TEST(OperationValidationTest, SQRT_float32) {
1515 activationOpTest(ANEURALNETWORKS_SQRT, ANEURALNETWORKS_TENSOR_FLOAT32);
1516 }
1517
TEST(OperationValidationTest,NEG_float16)1518 TEST(OperationValidationTest, NEG_float16) {
1519 activationOpTest(ANEURALNETWORKS_NEG, ANEURALNETWORKS_TENSOR_FLOAT16);
1520 }
1521
TEST(OperationValidationTest,NEG_float32)1522 TEST(OperationValidationTest, NEG_float32) {
1523 activationOpTest(ANEURALNETWORKS_NEG, ANEURALNETWORKS_TENSOR_FLOAT32);
1524 }
1525
TEST(OperationValidationTest,NEG_int32)1526 TEST(OperationValidationTest, NEG_int32) {
1527 activationOpTest(ANEURALNETWORKS_NEG, ANEURALNETWORKS_TENSOR_INT32);
1528 }
1529
TEST(OperationValidationTest,FLOOR_float16)1530 TEST(OperationValidationTest, FLOOR_float16) {
1531 activationOpTest(ANEURALNETWORKS_FLOOR, ANEURALNETWORKS_TENSOR_FLOAT16);
1532 }
1533
TEST(OperationValidationTest,FLOOR_float32)1534 TEST(OperationValidationTest, FLOOR_float32) {
1535 activationOpTest(ANEURALNETWORKS_FLOOR, ANEURALNETWORKS_TENSOR_FLOAT32);
1536 }
1537
TEST(OperationValidationTest,LOGICAL_NOT_bool)1538 TEST(OperationValidationTest, LOGICAL_NOT_bool) {
1539 activationOpTest(ANEURALNETWORKS_LOGICAL_NOT, ANEURALNETWORKS_TENSOR_BOOL8);
1540 }
1541
TEST(OperationValidationTest,TANH_float16)1542 TEST(OperationValidationTest, TANH_float16) {
1543 activationOpTest(ANEURALNETWORKS_TANH, ANEURALNETWORKS_TENSOR_FLOAT16);
1544 }
1545
TEST(OperationValidationTest,TANH_float32)1546 TEST(OperationValidationTest, TANH_float32) {
1547 activationOpTest(ANEURALNETWORKS_TANH, ANEURALNETWORKS_TENSOR_FLOAT32);
1548 }
1549
TEST(OperationValidationTest,TANH_quant8)1550 TEST(OperationValidationTest, TANH_quant8) {
1551 activationOpTest(ANEURALNETWORKS_TANH, ANEURALNETWORKS_TENSOR_QUANT8_ASYMM);
1552 }
1553
TEST(OperationValidationTest,TANH_quant8_signed)1554 TEST(OperationValidationTest, TANH_quant8_signed) {
1555 activationOpTest(ANEURALNETWORKS_TANH, ANEURALNETWORKS_TENSOR_QUANT8_ASYMM_SIGNED);
1556 }
1557
TEST(OperationValidationTest,RELU_float16)1558 TEST(OperationValidationTest, RELU_float16) {
1559 activationOpTest(ANEURALNETWORKS_RELU, ANEURALNETWORKS_TENSOR_FLOAT16);
1560 }
1561
TEST(OperationValidationTest,RELU1_float16)1562 TEST(OperationValidationTest, RELU1_float16) {
1563 activationOpTest(ANEURALNETWORKS_RELU, ANEURALNETWORKS_TENSOR_FLOAT16);
1564 }
1565
TEST(OperationValidationTest,RELU6_float16)1566 TEST(OperationValidationTest, RELU6_float16) {
1567 activationOpTest(ANEURALNETWORKS_RELU, ANEURALNETWORKS_TENSOR_FLOAT16);
1568 }
1569
TEST(OperationValidationTest,RELU_float32)1570 TEST(OperationValidationTest, RELU_float32) {
1571 activationOpTest(ANEURALNETWORKS_RELU, ANEURALNETWORKS_TENSOR_FLOAT32);
1572 }
1573
TEST(OperationValidationTest,RELU1_float32)1574 TEST(OperationValidationTest, RELU1_float32) {
1575 activationOpTest(ANEURALNETWORKS_RELU, ANEURALNETWORKS_TENSOR_FLOAT32);
1576 }
1577
TEST(OperationValidationTest,RELU6_float32)1578 TEST(OperationValidationTest, RELU6_float32) {
1579 activationOpTest(ANEURALNETWORKS_RELU, ANEURALNETWORKS_TENSOR_FLOAT32);
1580 }
1581
TEST(OperationValidationTest,RELU_quant8)1582 TEST(OperationValidationTest, RELU_quant8) {
1583 activationOpTest(ANEURALNETWORKS_RELU, ANEURALNETWORKS_TENSOR_QUANT8_ASYMM);
1584 }
1585
TEST(OperationValidationTest,RELU1_quant8)1586 TEST(OperationValidationTest, RELU1_quant8) {
1587 activationOpTest(ANEURALNETWORKS_RELU, ANEURALNETWORKS_TENSOR_QUANT8_ASYMM);
1588 }
1589
TEST(OperationValidationTest,RELU6_quant8)1590 TEST(OperationValidationTest, RELU6_quant8) {
1591 activationOpTest(ANEURALNETWORKS_RELU, ANEURALNETWORKS_TENSOR_QUANT8_ASYMM);
1592 }
1593
TEST(OperationValidationTest,RELU_quant8_signed)1594 TEST(OperationValidationTest, RELU_quant8_signed) {
1595 activationOpTest(ANEURALNETWORKS_RELU, ANEURALNETWORKS_TENSOR_QUANT8_ASYMM_SIGNED);
1596 }
1597
TEST(OperationValidationTest,RELU1_quant8_signed)1598 TEST(OperationValidationTest, RELU1_quant8_signed) {
1599 activationOpTest(ANEURALNETWORKS_RELU, ANEURALNETWORKS_TENSOR_QUANT8_ASYMM_SIGNED);
1600 }
1601
TEST(OperationValidationTest,RELU6_quant8_signed)1602 TEST(OperationValidationTest, RELU6_quant8_signed) {
1603 activationOpTest(ANEURALNETWORKS_RELU, ANEURALNETWORKS_TENSOR_QUANT8_ASYMM_SIGNED);
1604 }
1605
TEST(OperationValidationTest,LOGISTIC_float16)1606 TEST(OperationValidationTest, LOGISTIC_float16) {
1607 activationOpTest(ANEURALNETWORKS_LOGISTIC, ANEURALNETWORKS_TENSOR_FLOAT16);
1608 }
1609
TEST(OperationValidationTest,LOGISTIC_float32)1610 TEST(OperationValidationTest, LOGISTIC_float32) {
1611 activationOpTest(ANEURALNETWORKS_LOGISTIC, ANEURALNETWORKS_TENSOR_FLOAT32);
1612 }
1613
TEST(OperationValidationTest,LOGISTIC_quant8)1614 TEST(OperationValidationTest, LOGISTIC_quant8) {
1615 activationOpTest(ANEURALNETWORKS_LOGISTIC, ANEURALNETWORKS_TENSOR_QUANT8_ASYMM);
1616 }
1617
TEST(OperationValidationTest,LOGISTIC_quant8_signed)1618 TEST(OperationValidationTest, LOGISTIC_quant8_signed) {
1619 activationOpTest(ANEURALNETWORKS_LOGISTIC, ANEURALNETWORKS_TENSOR_QUANT8_ASYMM_SIGNED);
1620 }
1621
TEST(OperationValidationTest,HARD_SWISH_float16)1622 TEST(OperationValidationTest, HARD_SWISH_float16) {
1623 activationOpTest(ANEURALNETWORKS_HARD_SWISH, ANEURALNETWORKS_TENSOR_FLOAT16);
1624 }
1625
TEST(OperationValidationTest,HARD_SWISH_float32)1626 TEST(OperationValidationTest, HARD_SWISH_float32) {
1627 activationOpTest(ANEURALNETWORKS_HARD_SWISH, ANEURALNETWORKS_TENSOR_FLOAT32);
1628 }
1629
TEST(OperationValidationTest,HARD_SWISH_quant8)1630 TEST(OperationValidationTest, HARD_SWISH_quant8) {
1631 activationOpTest(ANEURALNETWORKS_HARD_SWISH, ANEURALNETWORKS_TENSOR_QUANT8_ASYMM);
1632 }
1633
TEST(OperationValidationTest,HARD_SWISH_quant8_signed)1634 TEST(OperationValidationTest, HARD_SWISH_quant8_signed) {
1635 activationOpTest(ANEURALNETWORKS_HARD_SWISH, ANEURALNETWORKS_TENSOR_QUANT8_ASYMM_SIGNED);
1636 }
1637
eluOpTest(int32_t operandCode)1638 void eluOpTest(int32_t operandCode) {
1639 uint32_t inputDimensions[4] = {2, 2, 2, 2};
1640 ANeuralNetworksOperandType input = getOpType(operandCode, 4, inputDimensions);
1641 ANeuralNetworksOperandType alpha = (operandCode == ANEURALNETWORKS_TENSOR_FLOAT32)
1642 ? getOpType(ANEURALNETWORKS_FLOAT32)
1643 : getOpType(ANEURALNETWORKS_FLOAT16);
1644
1645 ANeuralNetworksOperandType output = input;
1646 OperationTestBase test(ANEURALNETWORKS_ELU, {input, alpha}, {output});
1647 test.testOpsValidations();
1648 }
1649
TEST(OperationValidationTest,ELU_float16)1650 TEST(OperationValidationTest, ELU_float16) {
1651 eluOpTest(ANEURALNETWORKS_TENSOR_FLOAT16);
1652 }
1653
TEST(OperationValidationTest,ELU_float32)1654 TEST(OperationValidationTest, ELU_float32) {
1655 eluOpTest(ANEURALNETWORKS_TENSOR_FLOAT32);
1656 }
1657
reshapeOpTest(int32_t inputOperandCode)1658 void reshapeOpTest(int32_t inputOperandCode) {
1659 SCOPED_TRACE(inputOperandCode);
1660 uint32_t inputDimensions[3] = {2, 3, 4};
1661 ANeuralNetworksOperandType input = getOpType(inputOperandCode, 3, inputDimensions);
1662 uint32_t shapeDims[1] = {2};
1663 ANeuralNetworksOperandType shape = getOpType(ANEURALNETWORKS_TENSOR_INT32, 1, shapeDims);
1664 uint32_t outputDimensions[2] = {4, 6};
1665 ANeuralNetworksOperandType output = getOpType(inputOperandCode, 2, outputDimensions);
1666 OperationTestBase test(ANEURALNETWORKS_RESHAPE, {input, shape}, {output},
1667 {{TensorRankConstraint::UpTo(4)}});
1668 test.testOpsValidations();
1669 }
1670
TEST(OperationValidationTest,RESHAPE)1671 TEST(OperationValidationTest, RESHAPE) {
1672 reshapeOpTest(ANEURALNETWORKS_TENSOR_FLOAT16);
1673 reshapeOpTest(ANEURALNETWORKS_TENSOR_FLOAT32);
1674 reshapeOpTest(ANEURALNETWORKS_TENSOR_QUANT8_ASYMM);
1675 reshapeOpTest(ANEURALNETWORKS_TENSOR_QUANT8_ASYMM_SIGNED);
1676 }
1677
logSoftmaxOpTest(int32_t inputOperandCode)1678 void logSoftmaxOpTest(int32_t inputOperandCode) {
1679 uint32_t inputDimensions[3] = {2, 2, 2};
1680 ANeuralNetworksOperandType input = {.type = inputOperandCode,
1681 .dimensionCount = 3,
1682 .dimensions = inputDimensions,
1683 .scale = 0.0f,
1684 .zeroPoint = 0};
1685 ANeuralNetworksOperandType beta = {.type = (inputOperandCode == ANEURALNETWORKS_TENSOR_FLOAT32)
1686 ? ANEURALNETWORKS_FLOAT32
1687 : ANEURALNETWORKS_FLOAT16,
1688 .dimensionCount = 0,
1689 .dimensions = nullptr,
1690 .scale = 0.0f,
1691 .zeroPoint = 0};
1692 ANeuralNetworksOperandType axis = {.type = ANEURALNETWORKS_INT32,
1693 .dimensionCount = 0,
1694 .dimensions = nullptr,
1695 .scale = 0.0f,
1696 .zeroPoint = 0};
1697
1698 ANeuralNetworksOperandType output = {.type = inputOperandCode,
1699 .dimensionCount = 3,
1700 .dimensions = inputDimensions,
1701 .scale = 0.0f,
1702 .zeroPoint = 0};
1703
1704 OperationTestBase test(ANEURALNETWORKS_LOG_SOFTMAX, {input, beta, axis}, {output});
1705 test.testOpsValidations();
1706 }
1707
TEST(OperationValidationTest,LOG_SOFTMAX_float16)1708 TEST(OperationValidationTest, LOG_SOFTMAX_float16) {
1709 logSoftmaxOpTest(ANEURALNETWORKS_TENSOR_FLOAT16);
1710 }
1711
TEST(OperationValidationTest,LOG_SOFTMAX_float32)1712 TEST(OperationValidationTest, LOG_SOFTMAX_float32) {
1713 logSoftmaxOpTest(ANEURALNETWORKS_TENSOR_FLOAT32);
1714 }
1715
meanOpTest(int32_t inputOperandCode)1716 void meanOpTest(int32_t inputOperandCode) {
1717 uint32_t inputDimensions[3] = {2, 2, 2};
1718 ANeuralNetworksOperandType input = getOpType(inputOperandCode, 3, inputDimensions);
1719 ANeuralNetworksOperandType dims = getOpType(ANEURALNETWORKS_TENSOR_INT32, 1, inputDimensions);
1720 ANeuralNetworksOperandType keepDims = getOpType(ANEURALNETWORKS_INT32);
1721 ANeuralNetworksOperandType output = getOpType(inputOperandCode, 3, inputDimensions);
1722
1723 OperationTestBase test(ANEURALNETWORKS_MEAN, {input, dims, keepDims}, {output},
1724 {{TensorRankConstraint::UpTo(4)}});
1725 test.testOpsValidations();
1726 }
1727
TEST(OperationValidationTest,MEAN_float16)1728 TEST(OperationValidationTest, MEAN_float16) {
1729 meanOpTest(ANEURALNETWORKS_TENSOR_FLOAT16);
1730 }
1731
TEST(OperationValidationTest,MEAN_float32)1732 TEST(OperationValidationTest, MEAN_float32) {
1733 meanOpTest(ANEURALNETWORKS_TENSOR_FLOAT32);
1734 }
1735
TEST(OperationValidationTest,MEAN_quant8)1736 TEST(OperationValidationTest, MEAN_quant8) {
1737 meanOpTest(ANEURALNETWORKS_TENSOR_QUANT8_ASYMM);
1738 }
1739
TEST(OperationValidationTest,MEAN_quant8_signed)1740 TEST(OperationValidationTest, MEAN_quant8_signed) {
1741 meanOpTest(ANEURALNETWORKS_TENSOR_QUANT8_ASYMM_SIGNED);
1742 }
1743
padOpTest(int32_t inputOperandCode)1744 void padOpTest(int32_t inputOperandCode) {
1745 SCOPED_TRACE(inputOperandCode);
1746 uint32_t inputDimensions[4] = {2, 2, 2, 2};
1747 ANeuralNetworksOperandType input = getOpType(inputOperandCode, 4, inputDimensions);
1748 uint32_t padSizeDimensions[1] = {4};
1749 ANeuralNetworksOperandType padSize =
1750 getOpType(ANEURALNETWORKS_TENSOR_INT32, 1, padSizeDimensions);
1751 uint32_t outputDimensions[4] = {4, 3, 4, 3};
1752 ANeuralNetworksOperandType output = getOpType(inputOperandCode, 4, outputDimensions);
1753 OperationTestBase test(ANEURALNETWORKS_PAD, {input, padSize}, {output},
1754 {{TensorRankConstraint::UpTo(4)}});
1755 test.testOpsValidations();
1756 }
1757
TEST(OperationValidationTest,PAD)1758 TEST(OperationValidationTest, PAD) {
1759 padOpTest(ANEURALNETWORKS_TENSOR_FLOAT16);
1760 padOpTest(ANEURALNETWORKS_TENSOR_FLOAT32);
1761 padOpTest(ANEURALNETWORKS_TENSOR_QUANT8_ASYMM);
1762 padOpTest(ANEURALNETWORKS_TENSOR_QUANT8_ASYMM_SIGNED);
1763 }
1764
padV2OpTest(int32_t inputOperandCode)1765 void padV2OpTest(int32_t inputOperandCode) {
1766 SCOPED_TRACE(inputOperandCode);
1767 uint32_t inputDimensions[4] = {2, 2, 2, 2};
1768 ANeuralNetworksOperandType input = getOpType(inputOperandCode, 4, inputDimensions);
1769 uint32_t padSizeDimensions[1] = {4};
1770 ANeuralNetworksOperandType padSize =
1771 getOpType(ANEURALNETWORKS_TENSOR_INT32, 1, padSizeDimensions);
1772 ANeuralNetworksOperandType padValue = getOpType(ANEURALNETWORKS_FLOAT32);
1773 if (inputOperandCode == ANEURALNETWORKS_TENSOR_FLOAT16) {
1774 padValue = getOpType(ANEURALNETWORKS_FLOAT16);
1775 } else if (inputOperandCode == ANEURALNETWORKS_TENSOR_QUANT8_ASYMM ||
1776 inputOperandCode == ANEURALNETWORKS_TENSOR_QUANT8_ASYMM_SIGNED) {
1777 padValue = getOpType(ANEURALNETWORKS_INT32);
1778 }
1779 uint32_t outputDimensions[4] = {4, 3, 4, 3};
1780 ANeuralNetworksOperandType output = getOpType(inputOperandCode, 4, outputDimensions);
1781 OperationTestBase test(ANEURALNETWORKS_PAD_V2, {input, padSize, padValue}, {output},
1782 {{TensorRankConstraint::UpTo(4)}});
1783 test.testOpsValidations();
1784 }
1785
TEST(OperationValidationTest,PAD_V2)1786 TEST(OperationValidationTest, PAD_V2) {
1787 padV2OpTest(ANEURALNETWORKS_TENSOR_FLOAT16);
1788 padV2OpTest(ANEURALNETWORKS_TENSOR_FLOAT32);
1789 padV2OpTest(ANEURALNETWORKS_TENSOR_QUANT8_ASYMM);
1790 padV2OpTest(ANEURALNETWORKS_TENSOR_QUANT8_ASYMM_SIGNED);
1791 }
1792
softmaxOpTest(int32_t operandCode)1793 void softmaxOpTest(int32_t operandCode) {
1794 uint32_t inputDimensions[4] = {2, 2, 2, 2};
1795 ANeuralNetworksOperandType input = getOpType(operandCode, 4, inputDimensions);
1796
1797 ANeuralNetworksOperandType output = input;
1798 ANeuralNetworksOperandType beta = getOpType(ANEURALNETWORKS_FLOAT32);
1799 if (operandCode == ANEURALNETWORKS_TENSOR_FLOAT16) {
1800 beta = getOpType(ANEURALNETWORKS_FLOAT16);
1801 }
1802
1803 OperationTestBase softmaxTest(ANEURALNETWORKS_SOFTMAX, {input, beta}, {output},
1804 {{TensorRankConstraint::UpTo(4)}});
1805 softmaxTest.testOpsValidations();
1806
1807 ANeuralNetworksOperandType axis = getOpType(ANEURALNETWORKS_INT32);
1808 OperationTestBase softmaxAxisTest(ANEURALNETWORKS_SOFTMAX, {input, beta, axis}, {output},
1809 {{TensorRankConstraint::UpTo(4)}});
1810 softmaxAxisTest.testOpsValidations();
1811 }
1812
TEST(OperationValidationTest,SOFTMAX_float16)1813 TEST(OperationValidationTest, SOFTMAX_float16) {
1814 softmaxOpTest(ANEURALNETWORKS_TENSOR_FLOAT16);
1815 }
1816
TEST(OperationValidationTest,SOFTMAX_float32)1817 TEST(OperationValidationTest, SOFTMAX_float32) {
1818 softmaxOpTest(ANEURALNETWORKS_TENSOR_FLOAT32);
1819 }
1820
TEST(OperationValidationTest,SOFTMAX_quant8)1821 TEST(OperationValidationTest, SOFTMAX_quant8) {
1822 softmaxOpTest(ANEURALNETWORKS_TENSOR_QUANT8_ASYMM);
1823 }
1824
TEST(OperationValidationTest,SOFTMAX_quant8_signed)1825 TEST(OperationValidationTest, SOFTMAX_quant8_signed) {
1826 softmaxOpTest(ANEURALNETWORKS_TENSOR_QUANT8_ASYMM_SIGNED);
1827 }
1828
poolingOpTest(ANeuralNetworksOperationType operationCode,int32_t operandCode)1829 void poolingOpTest(ANeuralNetworksOperationType operationCode, int32_t operandCode) {
1830 uint32_t inputDimensions[4] = {2, 4, 4, 2};
1831 ANeuralNetworksOperandType input = getOpType(operandCode, 4, inputDimensions);
1832 ANeuralNetworksOperandType output = input;
1833
1834 ANeuralNetworksOperandType scalar = {.type = ANEURALNETWORKS_INT32,
1835 .dimensionCount = 0,
1836 .dimensions = nullptr,
1837 .scale = 0.0f,
1838 .zeroPoint = 0};
1839 ANeuralNetworksOperandType padLeft = scalar;
1840 ANeuralNetworksOperandType padRight = scalar;
1841 ANeuralNetworksOperandType padTop = scalar;
1842 ANeuralNetworksOperandType padBottom = scalar;
1843 ANeuralNetworksOperandType strideWidth = scalar;
1844 ANeuralNetworksOperandType strideHeight = scalar;
1845 ANeuralNetworksOperandType filterWidth = scalar;
1846 ANeuralNetworksOperandType filterHeight = scalar;
1847 ANeuralNetworksOperandType activation = scalar;
1848
1849 OperationTestBase explicitPoolingTest(operationCode,
1850 {input, padLeft, padRight, padTop, padBottom, strideWidth,
1851 strideHeight, filterWidth, filterHeight, activation},
1852 {output});
1853 explicitPoolingTest.testOpsValidations();
1854
1855 ANeuralNetworksOperandType padImplicit = scalar;
1856 OperationTestBase implicitPoolingTest(
1857 operationCode,
1858 {input, padImplicit, strideWidth, strideHeight, filterWidth, filterHeight, activation},
1859 {output});
1860 implicitPoolingTest.testOpsValidations();
1861
1862 ANeuralNetworksOperandType layout = {.type = ANEURALNETWORKS_BOOL,
1863 .dimensionCount = 0,
1864 .dimensions = nullptr,
1865 .scale = 0.0f,
1866 .zeroPoint = 0};
1867
1868 OperationTestBase explicitNchwPoolingTest(
1869 operationCode,
1870 {input, padLeft, padRight, padTop, padBottom, strideWidth, strideHeight, filterWidth,
1871 filterHeight, activation, layout},
1872 {output});
1873 explicitNchwPoolingTest.testOpsValidations();
1874
1875 OperationTestBase implicitNchwPoolingTest(operationCode,
1876 {input, padImplicit, strideWidth, strideHeight,
1877 filterWidth, filterHeight, activation, layout},
1878 {output});
1879 implicitNchwPoolingTest.testOpsValidations();
1880 }
1881
TEST(OperationValidationTest,AVERAGE_POOL_2D_float16)1882 TEST(OperationValidationTest, AVERAGE_POOL_2D_float16) {
1883 poolingOpTest(ANEURALNETWORKS_AVERAGE_POOL_2D, ANEURALNETWORKS_TENSOR_FLOAT16);
1884 }
1885
TEST(OperationValidationTest,AVERAGE_POOL_2D_float32)1886 TEST(OperationValidationTest, AVERAGE_POOL_2D_float32) {
1887 poolingOpTest(ANEURALNETWORKS_AVERAGE_POOL_2D, ANEURALNETWORKS_TENSOR_FLOAT32);
1888 }
1889
TEST(OperationValidationTest,AVERAGE_POOL_2D_quant8)1890 TEST(OperationValidationTest, AVERAGE_POOL_2D_quant8) {
1891 poolingOpTest(ANEURALNETWORKS_AVERAGE_POOL_2D, ANEURALNETWORKS_TENSOR_QUANT8_ASYMM);
1892 }
1893
TEST(OperationValidationTest,AVERAGE_POOL_2D_quant8_signed)1894 TEST(OperationValidationTest, AVERAGE_POOL_2D_quant8_signed) {
1895 poolingOpTest(ANEURALNETWORKS_AVERAGE_POOL_2D, ANEURALNETWORKS_TENSOR_QUANT8_ASYMM_SIGNED);
1896 }
1897
TEST(OperationValidationTest,MAX_POOL_2D_float32)1898 TEST(OperationValidationTest, MAX_POOL_2D_float32) {
1899 poolingOpTest(ANEURALNETWORKS_MAX_POOL_2D, ANEURALNETWORKS_TENSOR_FLOAT32);
1900 }
1901
TEST(OperationValidationTest,MAX_POOL_2D_float16)1902 TEST(OperationValidationTest, MAX_POOL_2D_float16) {
1903 poolingOpTest(ANEURALNETWORKS_MAX_POOL_2D, ANEURALNETWORKS_TENSOR_FLOAT16);
1904 }
1905
TEST(OperationValidationTest,MAX_POOL_2D_quant8)1906 TEST(OperationValidationTest, MAX_POOL_2D_quant8) {
1907 poolingOpTest(ANEURALNETWORKS_MAX_POOL_2D, ANEURALNETWORKS_TENSOR_QUANT8_ASYMM);
1908 }
1909
TEST(OperationValidationTest,MAX_POOL_2D_quant8_signed)1910 TEST(OperationValidationTest, MAX_POOL_2D_quant8_signed) {
1911 poolingOpTest(ANEURALNETWORKS_MAX_POOL_2D, ANEURALNETWORKS_TENSOR_QUANT8_ASYMM_SIGNED);
1912 }
1913
TEST(OperationValidationTest,L2_POOL_2D_float16)1914 TEST(OperationValidationTest, L2_POOL_2D_float16) {
1915 poolingOpTest(ANEURALNETWORKS_L2_POOL_2D, ANEURALNETWORKS_TENSOR_FLOAT16);
1916 }
1917
TEST(OperationValidationTest,L2_POOL_2D_float32)1918 TEST(OperationValidationTest, L2_POOL_2D_float32) {
1919 poolingOpTest(ANEURALNETWORKS_L2_POOL_2D, ANEURALNETWORKS_TENSOR_FLOAT32);
1920 }
1921
spaceDepthOpTest(ANeuralNetworksOperationType operationCode,int32_t operandCode)1922 void spaceDepthOpTest(ANeuralNetworksOperationType operationCode, int32_t operandCode) {
1923 uint32_t inputDimensions[4] = {2, 2, 2, 2};
1924 ANeuralNetworksOperandType input = getOpType(operandCode, 4, inputDimensions);
1925
1926 ANeuralNetworksOperandType block_size = {.type = ANEURALNETWORKS_INT32,
1927 .dimensionCount = 0,
1928 .dimensions = nullptr,
1929 .scale = 0.0f,
1930 .zeroPoint = 0};
1931 ANeuralNetworksOperandType output = input;
1932
1933 OperationTestBase spaceDepthTest(operationCode, {input, block_size}, {output});
1934 spaceDepthTest.testOpsValidations();
1935
1936 ANeuralNetworksOperandType layout = {.type = ANEURALNETWORKS_BOOL,
1937 .dimensionCount = 0,
1938 .dimensions = nullptr,
1939 .scale = 0.0f,
1940 .zeroPoint = 0};
1941 OperationTestBase spaceDepthNchwTest(operationCode, {input, block_size, layout}, {output});
1942 spaceDepthNchwTest.testOpsValidations();
1943 }
1944
TEST(OperationValidationTest,SPACE_TO_DEPTH_float16)1945 TEST(OperationValidationTest, SPACE_TO_DEPTH_float16) {
1946 spaceDepthOpTest(ANEURALNETWORKS_SPACE_TO_DEPTH, ANEURALNETWORKS_TENSOR_FLOAT16);
1947 }
1948
TEST(OperationValidationTest,DEPTH_TO_SPACE_float16)1949 TEST(OperationValidationTest, DEPTH_TO_SPACE_float16) {
1950 spaceDepthOpTest(ANEURALNETWORKS_DEPTH_TO_SPACE, ANEURALNETWORKS_TENSOR_FLOAT16);
1951 }
1952
TEST(OperationValidationTest,SPACE_TO_DEPTH_float32)1953 TEST(OperationValidationTest, SPACE_TO_DEPTH_float32) {
1954 spaceDepthOpTest(ANEURALNETWORKS_SPACE_TO_DEPTH, ANEURALNETWORKS_TENSOR_FLOAT32);
1955 }
1956
TEST(OperationValidationTest,DEPTH_TO_SPACE_float32)1957 TEST(OperationValidationTest, DEPTH_TO_SPACE_float32) {
1958 spaceDepthOpTest(ANEURALNETWORKS_DEPTH_TO_SPACE, ANEURALNETWORKS_TENSOR_FLOAT32);
1959 }
1960
TEST(OperationValidationTest,SPACE_TO_DEPTH_quant8)1961 TEST(OperationValidationTest, SPACE_TO_DEPTH_quant8) {
1962 spaceDepthOpTest(ANEURALNETWORKS_SPACE_TO_DEPTH, ANEURALNETWORKS_TENSOR_QUANT8_ASYMM);
1963 }
1964
TEST(OperationValidationTest,DEPTH_TO_SPACE_quant8)1965 TEST(OperationValidationTest, DEPTH_TO_SPACE_quant8) {
1966 spaceDepthOpTest(ANEURALNETWORKS_DEPTH_TO_SPACE, ANEURALNETWORKS_TENSOR_QUANT8_ASYMM);
1967 }
1968
TEST(OperationValidationTest,SPACE_TO_DEPTH_quant8signed)1969 TEST(OperationValidationTest, SPACE_TO_DEPTH_quant8signed) {
1970 spaceDepthOpTest(ANEURALNETWORKS_SPACE_TO_DEPTH, ANEURALNETWORKS_TENSOR_QUANT8_ASYMM_SIGNED);
1971 }
1972
TEST(OperationValidationTest,DEPTH_TO_SPACE_quant8signed)1973 TEST(OperationValidationTest, DEPTH_TO_SPACE_quant8signed) {
1974 spaceDepthOpTest(ANEURALNETWORKS_DEPTH_TO_SPACE, ANEURALNETWORKS_TENSOR_QUANT8_ASYMM_SIGNED);
1975 }
1976
spaceBatchOpTest(ANeuralNetworksOperationType operationCode,int32_t operandCode)1977 void spaceBatchOpTest(ANeuralNetworksOperationType operationCode, int32_t operandCode) {
1978 uint32_t inputDimensions[4] = {2, 2, 2, 2};
1979 ANeuralNetworksOperandType input = getOpType(operandCode, 4, inputDimensions);
1980
1981 uint32_t blockDimensions[1] = {2};
1982 ANeuralNetworksOperandType blockShape = {.type = ANEURALNETWORKS_TENSOR_INT32,
1983 .dimensionCount = 1,
1984 .dimensions = blockDimensions,
1985 .scale = 0.0f,
1986 .zeroPoint = 0};
1987 ANeuralNetworksOperandType layout = {.type = ANEURALNETWORKS_BOOL,
1988 .dimensionCount = 0,
1989 .dimensions = nullptr,
1990 .scale = 0.0f,
1991 .zeroPoint = 0};
1992
1993 ANeuralNetworksOperandType padding = blockShape;
1994 ANeuralNetworksOperandType output = input;
1995 if (operationCode == ANEURALNETWORKS_SPACE_TO_BATCH_ND) {
1996 OperationTestBase spaceBatchTest(operationCode, {input, blockShape, padding}, {output});
1997 spaceBatchTest.testOpsValidations();
1998
1999 OperationTestBase spaceBatchNchwTest(operationCode, {input, blockShape, padding, layout},
2000 {output});
2001 spaceBatchNchwTest.testOpsValidations();
2002 } else {
2003 OperationTestBase spaceBatchTest(operationCode, {input, blockShape}, {output});
2004 spaceBatchTest.testOpsValidations();
2005
2006 OperationTestBase spaceBatchNchwTest(operationCode, {input, blockShape, layout}, {output});
2007 spaceBatchNchwTest.testOpsValidations();
2008 }
2009 }
2010
TEST(OperationValidationTest,SPACE_TO_BATCH_ND_float16)2011 TEST(OperationValidationTest, SPACE_TO_BATCH_ND_float16) {
2012 spaceBatchOpTest(ANEURALNETWORKS_SPACE_TO_BATCH_ND, ANEURALNETWORKS_TENSOR_FLOAT16);
2013 }
2014
TEST(OperationValidationTest,BATCH_TO_SPACE_ND_float16)2015 TEST(OperationValidationTest, BATCH_TO_SPACE_ND_float16) {
2016 spaceBatchOpTest(ANEURALNETWORKS_BATCH_TO_SPACE_ND, ANEURALNETWORKS_TENSOR_FLOAT16);
2017 }
2018
TEST(OperationValidationTest,SPACE_TO_BATCH_ND_float32)2019 TEST(OperationValidationTest, SPACE_TO_BATCH_ND_float32) {
2020 spaceBatchOpTest(ANEURALNETWORKS_SPACE_TO_BATCH_ND, ANEURALNETWORKS_TENSOR_FLOAT32);
2021 }
2022
TEST(OperationValidationTest,BATCH_TO_SPACE_ND_float32)2023 TEST(OperationValidationTest, BATCH_TO_SPACE_ND_float32) {
2024 spaceBatchOpTest(ANEURALNETWORKS_BATCH_TO_SPACE_ND, ANEURALNETWORKS_TENSOR_FLOAT32);
2025 }
2026
TEST(OperationValidationTest,SPACE_TO_BATCH_ND_quant8)2027 TEST(OperationValidationTest, SPACE_TO_BATCH_ND_quant8) {
2028 spaceBatchOpTest(ANEURALNETWORKS_SPACE_TO_BATCH_ND, ANEURALNETWORKS_TENSOR_QUANT8_ASYMM);
2029 }
2030
TEST(OperationValidationTest,BATCH_TO_SPACE_ND_quant8)2031 TEST(OperationValidationTest, BATCH_TO_SPACE_ND_quant8) {
2032 spaceBatchOpTest(ANEURALNETWORKS_BATCH_TO_SPACE_ND, ANEURALNETWORKS_TENSOR_QUANT8_ASYMM);
2033 }
2034
TEST(OperationValidationTest,SPACE_TO_BATCH_ND_quant8signed)2035 TEST(OperationValidationTest, SPACE_TO_BATCH_ND_quant8signed) {
2036 spaceBatchOpTest(ANEURALNETWORKS_SPACE_TO_BATCH_ND, ANEURALNETWORKS_TENSOR_QUANT8_ASYMM_SIGNED);
2037 }
2038
TEST(OperationValidationTest,BATCH_TO_SPACE_ND_quant8signed)2039 TEST(OperationValidationTest, BATCH_TO_SPACE_ND_quant8signed) {
2040 spaceBatchOpTest(ANEURALNETWORKS_BATCH_TO_SPACE_ND, ANEURALNETWORKS_TENSOR_QUANT8_ASYMM_SIGNED);
2041 }
2042
transposeAndSqueezeOpTest(ANeuralNetworksOperationType operationCode,int32_t operandCode)2043 void transposeAndSqueezeOpTest(ANeuralNetworksOperationType operationCode, int32_t operandCode) {
2044 uint32_t inputDimensions[4] = {2, 2, 2, 2};
2045 ANeuralNetworksOperandType input = getOpType(operandCode, 4, inputDimensions);
2046
2047 uint32_t blockDimensions[1] = {4};
2048 ANeuralNetworksOperandType dims = {.type = ANEURALNETWORKS_TENSOR_INT32,
2049 .dimensionCount = 1,
2050 .dimensions = blockDimensions,
2051 .scale = 0.0f,
2052 .zeroPoint = 0};
2053
2054 ANeuralNetworksOperandType output = input;
2055 OperationTestBase transposeAndSqueezeTest(operationCode, {input, dims}, {output},
2056 {{TensorRankConstraint::UpTo(4)}});
2057 transposeAndSqueezeTest.testOpsValidations();
2058 }
2059
TEST(OperationValidationTest,TRANSPOSE_float16)2060 TEST(OperationValidationTest, TRANSPOSE_float16) {
2061 transposeAndSqueezeOpTest(ANEURALNETWORKS_TRANSPOSE, ANEURALNETWORKS_TENSOR_FLOAT16);
2062 }
2063
TEST(OperationValidationTest,SQUEEZE_float16)2064 TEST(OperationValidationTest, SQUEEZE_float16) {
2065 transposeAndSqueezeOpTest(ANEURALNETWORKS_SQUEEZE, ANEURALNETWORKS_TENSOR_FLOAT16);
2066 }
2067
TEST(OperationValidationTest,TRANSPOSE_float32)2068 TEST(OperationValidationTest, TRANSPOSE_float32) {
2069 transposeAndSqueezeOpTest(ANEURALNETWORKS_TRANSPOSE, ANEURALNETWORKS_TENSOR_FLOAT32);
2070 }
2071
TEST(OperationValidationTest,SQUEEZE_float32)2072 TEST(OperationValidationTest, SQUEEZE_float32) {
2073 transposeAndSqueezeOpTest(ANEURALNETWORKS_SQUEEZE, ANEURALNETWORKS_TENSOR_FLOAT32);
2074 }
2075
TEST(OperationValidationTest,TRANSPOSE_quant8)2076 TEST(OperationValidationTest, TRANSPOSE_quant8) {
2077 transposeAndSqueezeOpTest(ANEURALNETWORKS_TRANSPOSE, ANEURALNETWORKS_TENSOR_QUANT8_ASYMM);
2078 }
2079
TEST(OperationValidationTest,TRANSPOSE_quant8signed)2080 TEST(OperationValidationTest, TRANSPOSE_quant8signed) {
2081 transposeAndSqueezeOpTest(ANEURALNETWORKS_TRANSPOSE,
2082 ANEURALNETWORKS_TENSOR_QUANT8_ASYMM_SIGNED);
2083 }
2084
TEST(OperationValidationTest,SQUEEZE_quant8)2085 TEST(OperationValidationTest, SQUEEZE_quant8) {
2086 transposeAndSqueezeOpTest(ANEURALNETWORKS_SQUEEZE, ANEURALNETWORKS_TENSOR_QUANT8_ASYMM);
2087 }
2088
TEST(OperationValidationTest,SQUEEZE_quant8_signed)2089 TEST(OperationValidationTest, SQUEEZE_quant8_signed) {
2090 transposeAndSqueezeOpTest(ANEURALNETWORKS_SQUEEZE, ANEURALNETWORKS_TENSOR_QUANT8_ASYMM_SIGNED);
2091 }
2092
convOpTest(int32_t inputOperandCode,int32_t filterOperandCode)2093 void convOpTest(int32_t inputOperandCode, int32_t filterOperandCode) {
2094 uint32_t inputDimensions[4] = {2, 4, 4, 2};
2095 ANeuralNetworksOperandType input = getOpType(inputOperandCode, 4, inputDimensions);
2096 ANeuralNetworksOperandType output = input;
2097
2098 float filterScales[2] = {0.5f, 1.0f};
2099 ANeuralNetworksOperandType filter = getOpType(filterOperandCode, 4, inputDimensions);
2100 ANeuralNetworksSymmPerChannelQuantParams filterChannelQuantParams = {
2101 .channelDim = 0,
2102 .scaleCount = 2,
2103 .scales = filterScales,
2104 };
2105
2106 uint32_t biasDimensions[1] = {2};
2107 ANeuralNetworksOperandType bias = {.type = inputOperandCode,
2108 .dimensionCount = 1,
2109 .dimensions = biasDimensions,
2110 .scale = 0.0f,
2111 .zeroPoint = 0};
2112 if (filterOperandCode == ANEURALNETWORKS_TENSOR_QUANT8_ASYMM) {
2113 bias.type = ANEURALNETWORKS_TENSOR_INT32;
2114 bias.scale = 0.25f;
2115 }
2116 if (filterOperandCode == ANEURALNETWORKS_TENSOR_QUANT8_ASYMM_SIGNED) {
2117 bias.type = ANEURALNETWORKS_TENSOR_INT32;
2118 bias.scale = 0.25f;
2119 }
2120 if (filterOperandCode == ANEURALNETWORKS_TENSOR_QUANT8_SYMM_PER_CHANNEL) {
2121 bias.type = ANEURALNETWORKS_TENSOR_INT32;
2122 bias.scale = 0.0f;
2123 }
2124
2125 ANeuralNetworksOperandType scalar = {.type = ANEURALNETWORKS_INT32,
2126 .dimensionCount = 0,
2127 .dimensions = nullptr,
2128 .scale = 0.0f,
2129 .zeroPoint = 0};
2130 ANeuralNetworksOperandType padLeft = scalar;
2131 ANeuralNetworksOperandType padRight = scalar;
2132 ANeuralNetworksOperandType padTop = scalar;
2133 ANeuralNetworksOperandType padBottom = scalar;
2134 ANeuralNetworksOperandType strideWidth = scalar;
2135 ANeuralNetworksOperandType strideHeight = scalar;
2136 ANeuralNetworksOperandType dilationHeightFactor = scalar;
2137 ANeuralNetworksOperandType dilationWidthFactor = scalar;
2138 ANeuralNetworksOperandType activation = scalar;
2139
2140 OperationTestBase explicitConvTest(ANEURALNETWORKS_CONV_2D,
2141 {input, filter, bias, padLeft, padRight, padTop, padBottom,
2142 strideWidth, strideHeight, activation},
2143 {output});
2144 if (filterOperandCode == ANEURALNETWORKS_TENSOR_QUANT8_SYMM_PER_CHANNEL) {
2145 explicitConvTest.setInputSymmPerChannelQuantParams(1, filterChannelQuantParams);
2146 }
2147 explicitConvTest.testOpsValidations();
2148
2149 ANeuralNetworksOperandType padImplicit = scalar;
2150 OperationTestBase implicitConvTest(
2151 ANEURALNETWORKS_CONV_2D,
2152 {input, filter, bias, padImplicit, strideWidth, strideHeight, activation}, {output},
2153 {{TensorRankConstraint::Exactly(4), {0, 1}}});
2154 if (filterOperandCode == ANEURALNETWORKS_TENSOR_QUANT8_SYMM_PER_CHANNEL) {
2155 implicitConvTest.setInputSymmPerChannelQuantParams(1, filterChannelQuantParams);
2156 }
2157 implicitConvTest.testOpsValidations();
2158
2159 ANeuralNetworksOperandType layout = {.type = ANEURALNETWORKS_BOOL,
2160 .dimensionCount = 0,
2161 .dimensions = nullptr,
2162 .scale = 0.0f,
2163 .zeroPoint = 0};
2164
2165 OperationTestBase explicitNchwConvTest(
2166 ANEURALNETWORKS_CONV_2D,
2167 {input, filter, bias, padLeft, padRight, padTop, padBottom, strideWidth, strideHeight,
2168 activation, layout},
2169 {output});
2170 if (filterOperandCode == ANEURALNETWORKS_TENSOR_QUANT8_SYMM_PER_CHANNEL) {
2171 explicitNchwConvTest.setInputSymmPerChannelQuantParams(1, filterChannelQuantParams);
2172 }
2173 explicitNchwConvTest.testOpsValidations();
2174
2175 OperationTestBase implicitNchwConvTest(
2176 ANEURALNETWORKS_CONV_2D,
2177 {input, filter, bias, padImplicit, strideWidth, strideHeight, activation, layout},
2178 {output});
2179 if (filterOperandCode == ANEURALNETWORKS_TENSOR_QUANT8_SYMM_PER_CHANNEL) {
2180 implicitNchwConvTest.setInputSymmPerChannelQuantParams(1, filterChannelQuantParams);
2181 }
2182 implicitNchwConvTest.testOpsValidations();
2183
2184 OperationTestBase explicitDilateConvTest(
2185 ANEURALNETWORKS_CONV_2D,
2186 {input, filter, bias, padLeft, padRight, padTop, padBottom, strideWidth, strideHeight,
2187 activation, layout, dilationWidthFactor, dilationHeightFactor},
2188 {output});
2189 if (filterOperandCode == ANEURALNETWORKS_TENSOR_QUANT8_SYMM_PER_CHANNEL) {
2190 explicitDilateConvTest.setInputSymmPerChannelQuantParams(1, filterChannelQuantParams);
2191 }
2192 explicitDilateConvTest.testOpsValidations();
2193
2194 OperationTestBase implicitDilateConvTest(
2195 ANEURALNETWORKS_CONV_2D,
2196 {input, filter, bias, padImplicit, strideWidth, strideHeight, activation, layout,
2197 dilationWidthFactor, dilationHeightFactor},
2198 {output});
2199 if (filterOperandCode == ANEURALNETWORKS_TENSOR_QUANT8_SYMM_PER_CHANNEL) {
2200 implicitDilateConvTest.setInputSymmPerChannelQuantParams(1, filterChannelQuantParams);
2201 }
2202 implicitDilateConvTest.testOpsValidations();
2203 }
2204
TEST(OperationValidationTest,CONV_2D_float16)2205 TEST(OperationValidationTest, CONV_2D_float16) {
2206 convOpTest(ANEURALNETWORKS_TENSOR_FLOAT16, ANEURALNETWORKS_TENSOR_FLOAT16);
2207 }
2208
TEST(OperationValidationTest,CONV_2D_float32)2209 TEST(OperationValidationTest, CONV_2D_float32) {
2210 convOpTest(ANEURALNETWORKS_TENSOR_FLOAT32, ANEURALNETWORKS_TENSOR_FLOAT32);
2211 }
2212
TEST(OperationValidationTest,CONV_2D_quant8)2213 TEST(OperationValidationTest, CONV_2D_quant8) {
2214 convOpTest(ANEURALNETWORKS_TENSOR_QUANT8_ASYMM, ANEURALNETWORKS_TENSOR_QUANT8_ASYMM);
2215 }
2216
TEST(OperationValidationTest,CONV_2D_quant8_per_channel)2217 TEST(OperationValidationTest, CONV_2D_quant8_per_channel) {
2218 convOpTest(ANEURALNETWORKS_TENSOR_QUANT8_ASYMM, ANEURALNETWORKS_TENSOR_QUANT8_SYMM_PER_CHANNEL);
2219 }
2220
TEST(OperationValidationTest,CONV_2D_quant8_signed)2221 TEST(OperationValidationTest, CONV_2D_quant8_signed) {
2222 convOpTest(ANEURALNETWORKS_TENSOR_QUANT8_ASYMM_SIGNED,
2223 ANEURALNETWORKS_TENSOR_QUANT8_ASYMM_SIGNED);
2224 }
2225
TEST(OperationValidationTest,CONV_2D_quant8_signed_per_channel)2226 TEST(OperationValidationTest, CONV_2D_quant8_signed_per_channel) {
2227 convOpTest(ANEURALNETWORKS_TENSOR_QUANT8_ASYMM_SIGNED,
2228 ANEURALNETWORKS_TENSOR_QUANT8_SYMM_PER_CHANNEL);
2229 }
2230
depthwiseConvOpTest(int32_t inputOperandCode,int32_t filterOperandCode)2231 void depthwiseConvOpTest(int32_t inputOperandCode, int32_t filterOperandCode) {
2232 uint32_t inputDimensions[4] = {1, 2, 2, 2};
2233 ANeuralNetworksOperandType input = getOpType(inputOperandCode, 4, inputDimensions);
2234 ANeuralNetworksOperandType output = input;
2235
2236 float filterScales[2] = {0.5f, 1.0f};
2237 ANeuralNetworksOperandType filter = getOpType(filterOperandCode, 4, inputDimensions);
2238 ANeuralNetworksSymmPerChannelQuantParams filterChannelQuantParams = {
2239 .channelDim = 3,
2240 .scaleCount = 2,
2241 .scales = filterScales,
2242 };
2243
2244 uint32_t biasDimensions[1] = {2};
2245 ANeuralNetworksOperandType bias = {.type = inputOperandCode,
2246 .dimensionCount = 1,
2247 .dimensions = biasDimensions,
2248 .scale = 0.0f,
2249 .zeroPoint = 0};
2250 if (filterOperandCode == ANEURALNETWORKS_TENSOR_QUANT8_ASYMM ||
2251 filterOperandCode == ANEURALNETWORKS_TENSOR_QUANT8_ASYMM_SIGNED) {
2252 bias.type = ANEURALNETWORKS_TENSOR_INT32;
2253 bias.scale = 0.25f;
2254 }
2255 if (filterOperandCode == ANEURALNETWORKS_TENSOR_QUANT8_SYMM_PER_CHANNEL) {
2256 bias.type = ANEURALNETWORKS_TENSOR_INT32;
2257 bias.scale = 0.0f;
2258 }
2259
2260 ANeuralNetworksOperandType scalar = {.type = ANEURALNETWORKS_INT32,
2261 .dimensionCount = 0,
2262 .dimensions = nullptr,
2263 .scale = 0.0f,
2264 .zeroPoint = 0};
2265 ANeuralNetworksOperandType padLeft = scalar;
2266 ANeuralNetworksOperandType padRight = scalar;
2267 ANeuralNetworksOperandType padTop = scalar;
2268 ANeuralNetworksOperandType padBottom = scalar;
2269 ANeuralNetworksOperandType strideWidth = scalar;
2270 ANeuralNetworksOperandType strideHeight = scalar;
2271 ANeuralNetworksOperandType multiplier = scalar;
2272 ANeuralNetworksOperandType activation = scalar;
2273
2274 OperationTestBase explicitDepthwiseConvTest(
2275 ANEURALNETWORKS_DEPTHWISE_CONV_2D,
2276 {input, filter, bias, padLeft, padRight, padTop, padBottom, strideWidth, strideHeight,
2277 multiplier, activation},
2278 {output});
2279 if (filterOperandCode == ANEURALNETWORKS_TENSOR_QUANT8_SYMM_PER_CHANNEL) {
2280 explicitDepthwiseConvTest.setInputSymmPerChannelQuantParams(1, filterChannelQuantParams);
2281 }
2282 explicitDepthwiseConvTest.testOpsValidations();
2283
2284 ANeuralNetworksOperandType padImplicit = scalar;
2285 OperationTestBase implicitDepthwiseConvTest(
2286 ANEURALNETWORKS_DEPTHWISE_CONV_2D,
2287 {input, filter, bias, padImplicit, strideWidth, strideHeight, multiplier, activation},
2288 {output});
2289 if (filterOperandCode == ANEURALNETWORKS_TENSOR_QUANT8_SYMM_PER_CHANNEL) {
2290 implicitDepthwiseConvTest.setInputSymmPerChannelQuantParams(1, filterChannelQuantParams);
2291 }
2292 implicitDepthwiseConvTest.testOpsValidations();
2293
2294 ANeuralNetworksOperandType layout = {.type = ANEURALNETWORKS_BOOL,
2295 .dimensionCount = 0,
2296 .dimensions = nullptr,
2297 .scale = 0.0f,
2298 .zeroPoint = 0};
2299
2300 OperationTestBase explicitNchwDepthwiseConvTest(
2301 ANEURALNETWORKS_DEPTHWISE_CONV_2D,
2302 {input, filter, bias, padLeft, padRight, padTop, padBottom, strideWidth, strideHeight,
2303 multiplier, activation, layout},
2304 {output});
2305 if (filterOperandCode == ANEURALNETWORKS_TENSOR_QUANT8_SYMM_PER_CHANNEL) {
2306 explicitNchwDepthwiseConvTest.setInputSymmPerChannelQuantParams(1,
2307 filterChannelQuantParams);
2308 }
2309 explicitNchwDepthwiseConvTest.testOpsValidations();
2310
2311 OperationTestBase implicitNchwDepthwiseConvTest(ANEURALNETWORKS_DEPTHWISE_CONV_2D,
2312 {input, filter, bias, padImplicit, strideWidth,
2313 strideHeight, multiplier, activation, layout},
2314 {output});
2315 if (filterOperandCode == ANEURALNETWORKS_TENSOR_QUANT8_SYMM_PER_CHANNEL) {
2316 implicitNchwDepthwiseConvTest.setInputSymmPerChannelQuantParams(1,
2317 filterChannelQuantParams);
2318 }
2319 implicitNchwDepthwiseConvTest.testOpsValidations();
2320
2321 ANeuralNetworksOperandType dilationHeightFactor = scalar;
2322 ANeuralNetworksOperandType dilationWidthFactor = scalar;
2323
2324 OperationTestBase explicitDilationDepthwiseConvTest(
2325 ANEURALNETWORKS_DEPTHWISE_CONV_2D,
2326 {input, filter, bias, padLeft, padRight, padTop, padBottom, strideWidth, strideHeight,
2327 multiplier, activation, layout, dilationWidthFactor, dilationHeightFactor},
2328 {output});
2329 if (filterOperandCode == ANEURALNETWORKS_TENSOR_QUANT8_SYMM_PER_CHANNEL) {
2330 explicitDilationDepthwiseConvTest.setInputSymmPerChannelQuantParams(
2331 1, filterChannelQuantParams);
2332 }
2333 explicitDilationDepthwiseConvTest.testOpsValidations();
2334
2335 OperationTestBase implicitDilationDepthwiseConvTest(
2336 ANEURALNETWORKS_DEPTHWISE_CONV_2D,
2337 {input, filter, bias, padImplicit, strideWidth, strideHeight, multiplier, activation,
2338 layout, dilationWidthFactor, dilationHeightFactor},
2339 {output});
2340 if (filterOperandCode == ANEURALNETWORKS_TENSOR_QUANT8_SYMM_PER_CHANNEL) {
2341 implicitDilationDepthwiseConvTest.setInputSymmPerChannelQuantParams(
2342 1, filterChannelQuantParams);
2343 }
2344 implicitDilationDepthwiseConvTest.testOpsValidations();
2345 }
2346
TEST(OperationValidationTest,DEPTHWISE_CONV_2D_float32)2347 TEST(OperationValidationTest, DEPTHWISE_CONV_2D_float32) {
2348 depthwiseConvOpTest(ANEURALNETWORKS_TENSOR_FLOAT32, ANEURALNETWORKS_TENSOR_FLOAT32);
2349 }
2350
TEST(OperationValidationTest,DEPTHWISE_CONV_2D_float16)2351 TEST(OperationValidationTest, DEPTHWISE_CONV_2D_float16) {
2352 depthwiseConvOpTest(ANEURALNETWORKS_TENSOR_FLOAT16, ANEURALNETWORKS_TENSOR_FLOAT16);
2353 }
2354
TEST(OperationValidationTest,DEPTHWISE_CONV_2D_quant8)2355 TEST(OperationValidationTest, DEPTHWISE_CONV_2D_quant8) {
2356 depthwiseConvOpTest(ANEURALNETWORKS_TENSOR_QUANT8_ASYMM, ANEURALNETWORKS_TENSOR_QUANT8_ASYMM);
2357 }
2358
TEST(OperationValidationTest,DEPTHWISE_CONV_2D_quant8_per_channel)2359 TEST(OperationValidationTest, DEPTHWISE_CONV_2D_quant8_per_channel) {
2360 depthwiseConvOpTest(ANEURALNETWORKS_TENSOR_QUANT8_ASYMM,
2361 ANEURALNETWORKS_TENSOR_QUANT8_SYMM_PER_CHANNEL);
2362 }
2363
TEST(OperationValidationTest,DEPTHWISE_CONV_2D_quant8_signed)2364 TEST(OperationValidationTest, DEPTHWISE_CONV_2D_quant8_signed) {
2365 depthwiseConvOpTest(ANEURALNETWORKS_TENSOR_QUANT8_ASYMM_SIGNED,
2366 ANEURALNETWORKS_TENSOR_QUANT8_ASYMM_SIGNED);
2367 }
2368
TEST(OperationValidationTest,DEPTHWISE_CONV_2D_quant8_signed_per_channel)2369 TEST(OperationValidationTest, DEPTHWISE_CONV_2D_quant8_signed_per_channel) {
2370 depthwiseConvOpTest(ANEURALNETWORKS_TENSOR_QUANT8_ASYMM_SIGNED,
2371 ANEURALNETWORKS_TENSOR_QUANT8_SYMM_PER_CHANNEL);
2372 }
2373
fullyConnectedOpTest(int32_t operandCode)2374 void fullyConnectedOpTest(int32_t operandCode) {
2375 uint32_t inputDimensions[2] = {5, 5};
2376 ANeuralNetworksOperandType input = getOpType(operandCode, 2, inputDimensions);
2377
2378 ANeuralNetworksOperandType weights = input;
2379 ANeuralNetworksOperandType output = input;
2380
2381 uint32_t biasDimensions[1] = {5};
2382 ANeuralNetworksOperandType bias = {.type = operandCode,
2383 .dimensionCount = 1,
2384 .dimensions = biasDimensions,
2385 .scale = 0.0f,
2386 .zeroPoint = 0};
2387 if (operandCode == ANEURALNETWORKS_TENSOR_QUANT8_ASYMM ||
2388 operandCode == ANEURALNETWORKS_TENSOR_QUANT8_ASYMM_SIGNED) {
2389 bias.type = ANEURALNETWORKS_TENSOR_INT32;
2390 bias.scale = 0.25f;
2391 }
2392
2393 ANeuralNetworksOperandType activation = {.type = ANEURALNETWORKS_INT32,
2394 .dimensionCount = 0,
2395 .dimensions = nullptr,
2396 .scale = 0.0f,
2397 .zeroPoint = 0};
2398
2399 OperationTestBase fullyConnectedTest(ANEURALNETWORKS_FULLY_CONNECTED,
2400 {input, weights, bias, activation}, {output},
2401 {{TensorRankConstraint::Between(2, 4), {0}},
2402 {TensorRankConstraint::Exactly(2), {1}},
2403 {TensorRankConstraint::Exactly(1), {2}}});
2404 fullyConnectedTest.testOpsValidations();
2405 }
2406
TEST(OperationValidationTest,FULLY_CONNECTED_float16)2407 TEST(OperationValidationTest, FULLY_CONNECTED_float16) {
2408 fullyConnectedOpTest(ANEURALNETWORKS_TENSOR_FLOAT16);
2409 }
2410
TEST(OperationValidationTest,FULLY_CONNECTED_float32)2411 TEST(OperationValidationTest, FULLY_CONNECTED_float32) {
2412 fullyConnectedOpTest(ANEURALNETWORKS_TENSOR_FLOAT32);
2413 }
2414
TEST(OperationValidationTest,FULLY_CONNECTED_quant8)2415 TEST(OperationValidationTest, FULLY_CONNECTED_quant8) {
2416 fullyConnectedOpTest(ANEURALNETWORKS_TENSOR_QUANT8_ASYMM);
2417 }
2418
TEST(OperationValidationTest,FULLY_CONNECTED_quant8_signed)2419 TEST(OperationValidationTest, FULLY_CONNECTED_quant8_signed) {
2420 fullyConnectedOpTest(ANEURALNETWORKS_TENSOR_QUANT8_ASYMM_SIGNED);
2421 }
2422
concatenationTest(int32_t operandCode)2423 void concatenationTest(int32_t operandCode) {
2424 uint32_t inputDimensions[2] = {5, 5};
2425 ANeuralNetworksOperandType input1 = getOpType(operandCode, 2, inputDimensions);
2426 ANeuralNetworksOperandType input2 = input1;
2427 ANeuralNetworksOperandType output = input1;
2428
2429 ANeuralNetworksOperandType activation = {.type = ANEURALNETWORKS_INT32,
2430 .dimensionCount = 0,
2431 .dimensions = nullptr,
2432 .scale = 0.0f,
2433 .zeroPoint = 0};
2434
2435 OperationTestBase concat2Test(ANEURALNETWORKS_CONCATENATION, {input1, input2, activation},
2436 {output}, {{TensorRankConstraint::UpTo(4), {0, 1}}});
2437 concat2Test.testOpsValidations();
2438
2439 OperationTestBase concat1Test(ANEURALNETWORKS_CONCATENATION, {input1, activation}, {output},
2440 {{TensorRankConstraint::UpTo(4)}});
2441 concat1Test.testOpsValidations();
2442 }
2443
TEST(OperationValidationTest,CONCATENATION_float16)2444 TEST(OperationValidationTest, CONCATENATION_float16) {
2445 concatenationTest(ANEURALNETWORKS_TENSOR_FLOAT16);
2446 }
2447
TEST(OperationValidationTest,CONCATENATION_float32)2448 TEST(OperationValidationTest, CONCATENATION_float32) {
2449 concatenationTest(ANEURALNETWORKS_TENSOR_FLOAT32);
2450 }
2451
TEST(OperationValidationTest,CONCATENATION_quant8)2452 TEST(OperationValidationTest, CONCATENATION_quant8) {
2453 concatenationTest(ANEURALNETWORKS_TENSOR_QUANT8_ASYMM);
2454 }
2455
TEST(OperationValidationTest,CONCATENATION_quant8_signed)2456 TEST(OperationValidationTest, CONCATENATION_quant8_signed) {
2457 concatenationTest(ANEURALNETWORKS_TENSOR_QUANT8_ASYMM_SIGNED);
2458 }
2459
resizeBilinearOpTest(int32_t inputOperandCode,int32_t scalarOperandCode)2460 void resizeBilinearOpTest(int32_t inputOperandCode, int32_t scalarOperandCode) {
2461 SCOPED_TRACE(inputOperandCode);
2462 uint32_t inputDimensions[4] = {2, 2, 2, 2};
2463 ANeuralNetworksOperandType input = getOpType(inputOperandCode, 4, inputDimensions);
2464 ANeuralNetworksOperandType height = getOpType(scalarOperandCode);
2465 ANeuralNetworksOperandType width = height;
2466 ANeuralNetworksOperandType output = input;
2467
2468 OperationTestBase resizeTest(ANEURALNETWORKS_RESIZE_BILINEAR, {input, height, width}, {output});
2469 resizeTest.testOpsValidations();
2470
2471 ANeuralNetworksOperandType layout = getOpType(ANEURALNETWORKS_BOOL);
2472 OperationTestBase resizeNchwTest(ANEURALNETWORKS_RESIZE_BILINEAR,
2473 {input, height, width, layout}, {output});
2474 resizeNchwTest.testOpsValidations();
2475 }
2476
TEST(OperationValidationTest,RESIZE_BILINEAR)2477 TEST(OperationValidationTest, RESIZE_BILINEAR) {
2478 resizeBilinearOpTest(ANEURALNETWORKS_TENSOR_FLOAT16, ANEURALNETWORKS_INT32);
2479 resizeBilinearOpTest(ANEURALNETWORKS_TENSOR_FLOAT32, ANEURALNETWORKS_INT32);
2480 resizeBilinearOpTest(ANEURALNETWORKS_TENSOR_QUANT8_ASYMM, ANEURALNETWORKS_INT32);
2481 resizeBilinearOpTest(ANEURALNETWORKS_TENSOR_QUANT8_ASYMM_SIGNED, ANEURALNETWORKS_INT32);
2482 resizeBilinearOpTest(ANEURALNETWORKS_TENSOR_FLOAT16, ANEURALNETWORKS_FLOAT16);
2483 resizeBilinearOpTest(ANEURALNETWORKS_TENSOR_FLOAT32, ANEURALNETWORKS_FLOAT32);
2484 resizeBilinearOpTest(ANEURALNETWORKS_TENSOR_QUANT8_ASYMM, ANEURALNETWORKS_FLOAT32);
2485 resizeBilinearOpTest(ANEURALNETWORKS_TENSOR_QUANT8_ASYMM_SIGNED, ANEURALNETWORKS_FLOAT32);
2486 }
2487
embeddingLookupTest(int32_t operandCode)2488 void embeddingLookupTest(int32_t operandCode) {
2489 uint32_t lookupDimensions[1] = {5};
2490 ANeuralNetworksOperandType lookup = {.type = ANEURALNETWORKS_TENSOR_INT32,
2491 .dimensionCount = 1,
2492 .dimensions = lookupDimensions,
2493 .scale = 0.0f,
2494 .zeroPoint = 0};
2495
2496 uint32_t inputDimensions[2] = {5, 5};
2497 ANeuralNetworksOperandType input = getOpType(operandCode, 2, inputDimensions);
2498 ANeuralNetworksOperandType output = input;
2499
2500 OperationTestBase embedLookupTest(ANEURALNETWORKS_EMBEDDING_LOOKUP, {lookup, input}, {output});
2501 embedLookupTest.testOpsValidations();
2502 }
2503
TEST(OperationValidationTest,EMBEDDING_LOOKUP_float32)2504 TEST(OperationValidationTest, EMBEDDING_LOOKUP_float32) {
2505 embeddingLookupTest(ANEURALNETWORKS_TENSOR_FLOAT32);
2506 }
2507
TEST(OperationValidationTest,EMBEDDING_LOOKUP_int32)2508 TEST(OperationValidationTest, EMBEDDING_LOOKUP_int32) {
2509 embeddingLookupTest(ANEURALNETWORKS_TENSOR_INT32);
2510 }
2511
TEST(OperationValidationTest,EMBEDDING_LOOKUP_quant8)2512 TEST(OperationValidationTest, EMBEDDING_LOOKUP_quant8) {
2513 embeddingLookupTest(ANEURALNETWORKS_TENSOR_QUANT8_ASYMM);
2514 }
2515
TEST(OperationValidationTest,EMBEDDING_LOOKUP_quant8_signed)2516 TEST(OperationValidationTest, EMBEDDING_LOOKUP_quant8_signed) {
2517 embeddingLookupTest(ANEURALNETWORKS_TENSOR_QUANT8_ASYMM_SIGNED);
2518 }
2519
hashtableLookupTest(int32_t operandCode)2520 void hashtableLookupTest(int32_t operandCode) {
2521 uint32_t lookupDimensions[1] = {5};
2522 ANeuralNetworksOperandType lookup = {.type = ANEURALNETWORKS_TENSOR_INT32,
2523 .dimensionCount = 1,
2524 .dimensions = lookupDimensions,
2525 .scale = 0.0f,
2526 .zeroPoint = 0};
2527 ANeuralNetworksOperandType keys = lookup;
2528
2529 uint32_t valuesDimensions[2] = {5, 5};
2530 ANeuralNetworksOperandType values = getOpType(operandCode, 2, valuesDimensions);
2531 ANeuralNetworksOperandType output = values;
2532
2533 ANeuralNetworksOperandType hits = lookup;
2534 hits.type = ANEURALNETWORKS_TENSOR_QUANT8_ASYMM;
2535 hits.scale = 1.0f;
2536
2537 OperationTestBase hashLookupTest(ANEURALNETWORKS_HASHTABLE_LOOKUP, {lookup, keys, values},
2538 {output, hits});
2539 hashLookupTest.testOpsValidations();
2540 }
2541
TEST(OperationValidationTest,HASHTABLE_LOOKUP_float32)2542 TEST(OperationValidationTest, HASHTABLE_LOOKUP_float32) {
2543 hashtableLookupTest(ANEURALNETWORKS_TENSOR_FLOAT32);
2544 }
2545
TEST(OperationValidationTest,HASHTABLE_LOOKUP_int32)2546 TEST(OperationValidationTest, HASHTABLE_LOOKUP_int32) {
2547 hashtableLookupTest(ANEURALNETWORKS_TENSOR_INT32);
2548 }
2549
TEST(OperationValidationTest,HASHTABLE_LOOKUP_quant8)2550 TEST(OperationValidationTest, HASHTABLE_LOOKUP_quant8) {
2551 hashtableLookupTest(ANEURALNETWORKS_TENSOR_QUANT8_ASYMM);
2552 }
2553
lshProjectionTest(int32_t operandCode,int32_t hashAndWeightOperandCode)2554 void lshProjectionTest(int32_t operandCode, int32_t hashAndWeightOperandCode) {
2555 uint32_t inputDimensions[2] = {5, 5};
2556 ANeuralNetworksOperandType hash = getOpType(hashAndWeightOperandCode, 2, inputDimensions);
2557 ANeuralNetworksOperandType input = getOpType(operandCode, 2, inputDimensions);
2558
2559 uint32_t weightDimensions[1] = {5};
2560 ANeuralNetworksOperandType weight = getOpType(hashAndWeightOperandCode, 1, weightDimensions);
2561
2562 ANeuralNetworksOperandType type = {.type = ANEURALNETWORKS_INT32,
2563 .dimensionCount = 0,
2564 .dimensions = nullptr,
2565 .scale = 0.0f,
2566 .zeroPoint = 0};
2567
2568 ANeuralNetworksOperandType output = weight;
2569 output.type = ANEURALNETWORKS_TENSOR_INT32;
2570
2571 OperationTestBase lshProjTest(ANEURALNETWORKS_LSH_PROJECTION, {hash, input, weight, type},
2572 {output});
2573 lshProjTest.testOpsValidations();
2574 }
2575
TEST(OperationValidationTest,LSH_PROJECTION_float16)2576 TEST(OperationValidationTest, LSH_PROJECTION_float16) {
2577 lshProjectionTest(ANEURALNETWORKS_TENSOR_FLOAT16, ANEURALNETWORKS_TENSOR_FLOAT32);
2578 lshProjectionTest(ANEURALNETWORKS_TENSOR_FLOAT16, ANEURALNETWORKS_TENSOR_FLOAT16);
2579 }
2580
TEST(OperationValidationTest,LSH_PROJECTION_float32)2581 TEST(OperationValidationTest, LSH_PROJECTION_float32) {
2582 lshProjectionTest(ANEURALNETWORKS_TENSOR_FLOAT32, ANEURALNETWORKS_TENSOR_FLOAT32);
2583 lshProjectionTest(ANEURALNETWORKS_TENSOR_FLOAT32, ANEURALNETWORKS_TENSOR_FLOAT16);
2584 }
2585
TEST(OperationValidationTest,LSH_PROJECTION_quant8)2586 TEST(OperationValidationTest, LSH_PROJECTION_quant8) {
2587 lshProjectionTest(ANEURALNETWORKS_TENSOR_QUANT8_ASYMM, ANEURALNETWORKS_TENSOR_FLOAT32);
2588 lshProjectionTest(ANEURALNETWORKS_TENSOR_QUANT8_ASYMM, ANEURALNETWORKS_TENSOR_FLOAT16);
2589 }
2590
TEST(OperationValidationTest,LSH_PROJECTION_int32)2591 TEST(OperationValidationTest, LSH_PROJECTION_int32) {
2592 lshProjectionTest(ANEURALNETWORKS_TENSOR_INT32, ANEURALNETWORKS_TENSOR_FLOAT32);
2593 lshProjectionTest(ANEURALNETWORKS_TENSOR_INT32, ANEURALNETWORKS_TENSOR_FLOAT16);
2594 }
2595
TEST(OperationValidationTest,LSTM_float32)2596 TEST(OperationValidationTest, LSTM_float32) {
2597 uint32_t oneDimensional[1] = {5};
2598 uint32_t twoDimensional[2] = {5, 5};
2599 ANeuralNetworksOperandType floatTensor1D = {.type = ANEURALNETWORKS_TENSOR_FLOAT32,
2600 .dimensionCount = 1,
2601 .dimensions = oneDimensional,
2602 .scale = 0.0f,
2603 .zeroPoint = 0};
2604 ANeuralNetworksOperandType floatTensor2D = {.type = ANEURALNETWORKS_TENSOR_FLOAT32,
2605 .dimensionCount = 2,
2606 .dimensions = twoDimensional,
2607 .scale = 0.0f,
2608 .zeroPoint = 0};
2609 ANeuralNetworksOperandType intScalar = {.type = ANEURALNETWORKS_INT32,
2610 .dimensionCount = 0,
2611 .dimensions = nullptr,
2612 .scale = 0.0f,
2613 .zeroPoint = 0};
2614 ANeuralNetworksOperandType floatScalar = {.type = ANEURALNETWORKS_FLOAT32,
2615 .dimensionCount = 0,
2616 .dimensions = nullptr,
2617 .scale = 0.0f,
2618 .zeroPoint = 0};
2619
2620 ANeuralNetworksOperandType input = floatTensor2D;
2621 ANeuralNetworksOperandType inputToInput = floatTensor2D;
2622 ANeuralNetworksOperandType inputToForget = floatTensor2D;
2623 ANeuralNetworksOperandType inputToCell = floatTensor2D;
2624 ANeuralNetworksOperandType inputToOutput = floatTensor2D;
2625 ANeuralNetworksOperandType recurrentToInput = floatTensor2D;
2626 ANeuralNetworksOperandType recurrentToForget = floatTensor2D;
2627 ANeuralNetworksOperandType recurrentToCell = floatTensor2D;
2628 ANeuralNetworksOperandType recurrentToOutput = floatTensor2D;
2629 ANeuralNetworksOperandType cellToInput = floatTensor1D;
2630 ANeuralNetworksOperandType cellToForget = floatTensor1D;
2631 ANeuralNetworksOperandType cellToOutput = floatTensor1D;
2632 ANeuralNetworksOperandType inputGateBias = floatTensor1D;
2633 ANeuralNetworksOperandType forgetGateBias = floatTensor1D;
2634 ANeuralNetworksOperandType cellBias = floatTensor1D;
2635 ANeuralNetworksOperandType outputGateBias = floatTensor1D;
2636 ANeuralNetworksOperandType projWeights = floatTensor2D;
2637 ANeuralNetworksOperandType projBias = floatTensor1D;
2638 ANeuralNetworksOperandType outputStateIn = floatTensor2D;
2639 ANeuralNetworksOperandType cellStateIn = floatTensor2D;
2640 ANeuralNetworksOperandType activation = intScalar;
2641 ANeuralNetworksOperandType clipCellState = floatScalar;
2642 ANeuralNetworksOperandType clipProjLayer = floatScalar;
2643
2644 ANeuralNetworksOperandType scratch = floatTensor2D;
2645 ANeuralNetworksOperandType outputStateOut = floatTensor2D;
2646 ANeuralNetworksOperandType cellStateOut = floatTensor2D;
2647 ANeuralNetworksOperandType output = floatTensor2D;
2648
2649 OperationTestBase lstmTest(ANEURALNETWORKS_LSTM,
2650 {input,
2651 inputToInput,
2652 inputToForget,
2653 inputToCell,
2654 inputToOutput,
2655 recurrentToInput,
2656 recurrentToForget,
2657 recurrentToCell,
2658 recurrentToOutput,
2659 cellToInput,
2660 cellToForget,
2661 cellToOutput,
2662 inputGateBias,
2663 forgetGateBias,
2664 cellBias,
2665 outputGateBias,
2666 projWeights,
2667 projBias,
2668 outputStateIn,
2669 cellStateIn,
2670 activation,
2671 clipCellState,
2672 clipProjLayer},
2673 {scratch, outputStateOut, cellStateOut, output});
2674 lstmTest.testOpsValidations();
2675 }
2676
lstmTestV1_2(int32_t operandCode)2677 void lstmTestV1_2(int32_t operandCode) {
2678 SCOPED_TRACE(operandCode);
2679 uint32_t oneDimensional[1] = {5};
2680 uint32_t twoDimensional[2] = {5, 5};
2681 ANeuralNetworksOperandType floatTensor1D = {.type = operandCode,
2682 .dimensionCount = 1,
2683 .dimensions = oneDimensional,
2684 .scale = 0.0f,
2685 .zeroPoint = 0};
2686 ANeuralNetworksOperandType floatTensor2D = {.type = operandCode,
2687 .dimensionCount = 2,
2688 .dimensions = twoDimensional,
2689 .scale = 0.0f,
2690 .zeroPoint = 0};
2691 ANeuralNetworksOperandType intScalar = {.type = ANEURALNETWORKS_INT32,
2692 .dimensionCount = 0,
2693 .dimensions = nullptr,
2694 .scale = 0.0f,
2695 .zeroPoint = 0};
2696 ANeuralNetworksOperandType floatScalar = {
2697 .type = (operandCode == ANEURALNETWORKS_TENSOR_FLOAT32) ? ANEURALNETWORKS_FLOAT32
2698 : ANEURALNETWORKS_FLOAT16,
2699 .dimensionCount = 0,
2700 .dimensions = nullptr,
2701 .scale = 0.0f,
2702 .zeroPoint = 0};
2703
2704 ANeuralNetworksOperandType input = floatTensor2D;
2705 ANeuralNetworksOperandType inputToInput = floatTensor2D;
2706 ANeuralNetworksOperandType inputToForget = floatTensor2D;
2707 ANeuralNetworksOperandType inputToCell = floatTensor2D;
2708 ANeuralNetworksOperandType inputToOutput = floatTensor2D;
2709 ANeuralNetworksOperandType recurrentToInput = floatTensor2D;
2710 ANeuralNetworksOperandType recurrentToForget = floatTensor2D;
2711 ANeuralNetworksOperandType recurrentToCell = floatTensor2D;
2712 ANeuralNetworksOperandType recurrentToOutput = floatTensor2D;
2713 ANeuralNetworksOperandType cellToInput = floatTensor1D;
2714 ANeuralNetworksOperandType cellToForget = floatTensor1D;
2715 ANeuralNetworksOperandType cellToOutput = floatTensor1D;
2716 ANeuralNetworksOperandType inputGateBias = floatTensor1D;
2717 ANeuralNetworksOperandType forgetGateBias = floatTensor1D;
2718 ANeuralNetworksOperandType cellBias = floatTensor1D;
2719 ANeuralNetworksOperandType outputGateBias = floatTensor1D;
2720 ANeuralNetworksOperandType projWeights = floatTensor2D;
2721 ANeuralNetworksOperandType projBias = floatTensor1D;
2722 ANeuralNetworksOperandType outputStateIn = floatTensor2D;
2723 ANeuralNetworksOperandType cellStateIn = floatTensor2D;
2724 ANeuralNetworksOperandType activation = intScalar;
2725 ANeuralNetworksOperandType clipCellState = floatScalar;
2726 ANeuralNetworksOperandType clipProjLayer = floatScalar;
2727 ANeuralNetworksOperandType inputLayerNormWeights = floatTensor1D;
2728 ANeuralNetworksOperandType forgetLayerNormWeights = floatTensor1D;
2729 ANeuralNetworksOperandType cellLayerNormWeights = floatTensor1D;
2730 ANeuralNetworksOperandType outputLayerNormWeights = floatTensor1D;
2731
2732 ANeuralNetworksOperandType scratch = floatTensor2D;
2733 ANeuralNetworksOperandType outputStateOut = floatTensor2D;
2734 ANeuralNetworksOperandType cellStateOut = floatTensor2D;
2735 ANeuralNetworksOperandType output = floatTensor2D;
2736
2737 OperationTestBase lstmTest(ANEURALNETWORKS_LSTM,
2738 {input,
2739 inputToInput,
2740 inputToForget,
2741 inputToCell,
2742 inputToOutput,
2743 recurrentToInput,
2744 recurrentToForget,
2745 recurrentToCell,
2746 recurrentToOutput,
2747 cellToInput,
2748 cellToForget,
2749 cellToOutput,
2750 inputGateBias,
2751 forgetGateBias,
2752 cellBias,
2753 outputGateBias,
2754 projWeights,
2755 projBias,
2756 outputStateIn,
2757 cellStateIn,
2758 activation,
2759 clipCellState,
2760 clipProjLayer,
2761 inputLayerNormWeights,
2762 forgetLayerNormWeights,
2763 cellLayerNormWeights,
2764 outputLayerNormWeights},
2765 {scratch, outputStateOut, cellStateOut, output});
2766 lstmTest.testOpsValidations();
2767 }
2768
TEST(OperationValidationTest,LSTM_V1_2)2769 TEST(OperationValidationTest, LSTM_V1_2) {
2770 lstmTestV1_2(ANEURALNETWORKS_TENSOR_FLOAT32);
2771 lstmTestV1_2(ANEURALNETWORKS_TENSOR_FLOAT16);
2772 }
2773
lstmBidirectionalSequence(int32_t operandCode)2774 void lstmBidirectionalSequence(int32_t operandCode) {
2775 uint32_t oneDimensional[1] = {5};
2776 uint32_t twoDimensional[2] = {5, 5};
2777 uint32_t threeDimensional[3] = {5, 5, 5};
2778 ANeuralNetworksOperandType floatTensor1D = {
2779 .type = operandCode,
2780 .dimensionCount = 1,
2781 .dimensions = oneDimensional,
2782 .scale = 0.0f,
2783 .zeroPoint = 0,
2784 };
2785 ANeuralNetworksOperandType floatTensor2D = {
2786 .type = operandCode,
2787 .dimensionCount = 2,
2788 .dimensions = twoDimensional,
2789 .scale = 0.0f,
2790 .zeroPoint = 0,
2791 };
2792 ANeuralNetworksOperandType floatTensor3D = {
2793 .type = operandCode,
2794 .dimensionCount = 3,
2795 .dimensions = threeDimensional,
2796 .scale = 0.0f,
2797 .zeroPoint = 0,
2798 };
2799 ANeuralNetworksOperandType intScalar = {
2800 .type = ANEURALNETWORKS_INT32,
2801 .dimensionCount = 0,
2802 .dimensions = nullptr,
2803 .scale = 0.0f,
2804 .zeroPoint = 0,
2805 };
2806 ANeuralNetworksOperandType floatScalar = {
2807 .type = operandCode == ANEURALNETWORKS_TENSOR_FLOAT32 ? ANEURALNETWORKS_FLOAT32
2808 : ANEURALNETWORKS_FLOAT16,
2809 .dimensionCount = 0,
2810 .dimensions = nullptr,
2811 .scale = 0.0f,
2812 .zeroPoint = 0,
2813 };
2814 ANeuralNetworksOperandType boolScalar = {.type = ANEURALNETWORKS_BOOL,
2815 .dimensionCount = 0,
2816 .dimensions = nullptr,
2817 .scale = 0.0f,
2818 .zeroPoint = 0};
2819
2820 ANeuralNetworksOperandType input = floatTensor3D;
2821 ANeuralNetworksOperandType inputToInputFw = floatTensor2D;
2822 ANeuralNetworksOperandType inputToForgetFw = floatTensor2D;
2823 ANeuralNetworksOperandType inputToCellFw = floatTensor2D;
2824 ANeuralNetworksOperandType inputToOutputFw = floatTensor2D;
2825 ANeuralNetworksOperandType recurrentToInputFw = floatTensor2D;
2826 ANeuralNetworksOperandType recurrentToForgetFw = floatTensor2D;
2827 ANeuralNetworksOperandType recurrentToCellFw = floatTensor2D;
2828 ANeuralNetworksOperandType recurrentToOutputFw = floatTensor2D;
2829 ANeuralNetworksOperandType cellToInputFw = floatTensor1D;
2830 ANeuralNetworksOperandType cellToForgetFw = floatTensor1D;
2831 ANeuralNetworksOperandType cellToOutputFw = floatTensor1D;
2832 ANeuralNetworksOperandType inputGateBiasFw = floatTensor1D;
2833 ANeuralNetworksOperandType forgetGateBiasFw = floatTensor1D;
2834 ANeuralNetworksOperandType cellBiasFw = floatTensor1D;
2835 ANeuralNetworksOperandType outputGateBiasFw = floatTensor1D;
2836 ANeuralNetworksOperandType projWeightsFw = floatTensor2D;
2837 ANeuralNetworksOperandType projBiasFw = floatTensor1D;
2838 ANeuralNetworksOperandType outputStateInFw = floatTensor2D;
2839 ANeuralNetworksOperandType cellStateInFw = floatTensor2D;
2840 ANeuralNetworksOperandType inputToInputBw = floatTensor2D;
2841 ANeuralNetworksOperandType inputToForgetBw = floatTensor2D;
2842 ANeuralNetworksOperandType inputToCellBw = floatTensor2D;
2843 ANeuralNetworksOperandType inputToOutputBw = floatTensor2D;
2844 ANeuralNetworksOperandType recurrentToInputBw = floatTensor2D;
2845 ANeuralNetworksOperandType recurrentToForgetBw = floatTensor2D;
2846 ANeuralNetworksOperandType recurrentToCellBw = floatTensor2D;
2847 ANeuralNetworksOperandType recurrentToOutputBw = floatTensor2D;
2848 ANeuralNetworksOperandType cellToInputBw = floatTensor1D;
2849 ANeuralNetworksOperandType cellToForgetBw = floatTensor1D;
2850 ANeuralNetworksOperandType cellToOutputBw = floatTensor1D;
2851 ANeuralNetworksOperandType inputGateBiasBw = floatTensor1D;
2852 ANeuralNetworksOperandType forgetGateBiasBw = floatTensor1D;
2853 ANeuralNetworksOperandType cellBiasBw = floatTensor1D;
2854 ANeuralNetworksOperandType outputGateBiasBw = floatTensor1D;
2855 ANeuralNetworksOperandType projWeightsBw = floatTensor2D;
2856 ANeuralNetworksOperandType projBiasBw = floatTensor1D;
2857 ANeuralNetworksOperandType outputStateInBw = floatTensor2D;
2858 ANeuralNetworksOperandType cellStateInBw = floatTensor2D;
2859 ANeuralNetworksOperandType auxInput = floatTensor3D;
2860 ANeuralNetworksOperandType auxInputToInputFw = floatTensor2D;
2861 ANeuralNetworksOperandType auxInputToForgetFw = floatTensor2D;
2862 ANeuralNetworksOperandType auxInputToCellFw = floatTensor2D;
2863 ANeuralNetworksOperandType auxInputToOutputFw = floatTensor2D;
2864 ANeuralNetworksOperandType auxInputToInputBw = floatTensor2D;
2865 ANeuralNetworksOperandType auxInputToForgetBw = floatTensor2D;
2866 ANeuralNetworksOperandType auxInputToCellBw = floatTensor2D;
2867 ANeuralNetworksOperandType auxInputToOutputBw = floatTensor2D;
2868 ANeuralNetworksOperandType activation = intScalar;
2869 ANeuralNetworksOperandType clipCellState = floatScalar;
2870 ANeuralNetworksOperandType clipProjLayer = floatScalar;
2871 ANeuralNetworksOperandType mergeOutputs = boolScalar;
2872 ANeuralNetworksOperandType timeMajor = boolScalar;
2873 ANeuralNetworksOperandType inputLayerNormWeightsFw = floatTensor1D;
2874 ANeuralNetworksOperandType forgetLayerNormWeightsFw = floatTensor1D;
2875 ANeuralNetworksOperandType cellLayerNormWeightsFw = floatTensor1D;
2876 ANeuralNetworksOperandType outputLayerNormWeightsFw = floatTensor1D;
2877 ANeuralNetworksOperandType inputLayerNormWeightsBw = floatTensor1D;
2878 ANeuralNetworksOperandType forgetLayerNormWeightsBw = floatTensor1D;
2879 ANeuralNetworksOperandType cellLayerNormWeightsBw = floatTensor1D;
2880 ANeuralNetworksOperandType outputLayerNormWeightsBw = floatTensor1D;
2881
2882 ANeuralNetworksOperandType outputFw = floatTensor2D;
2883 ANeuralNetworksOperandType outputBw = floatTensor2D;
2884
2885 OperationTestBase lstmTest(ANEURALNETWORKS_BIDIRECTIONAL_SEQUENCE_LSTM,
2886 {
2887 input,
2888 inputToInputFw,
2889 inputToForgetFw,
2890 inputToCellFw,
2891 inputToOutputFw,
2892 recurrentToInputFw,
2893 recurrentToForgetFw,
2894 recurrentToCellFw,
2895 recurrentToOutputFw,
2896 cellToInputFw,
2897 cellToForgetFw,
2898 cellToOutputFw,
2899 inputGateBiasFw,
2900 forgetGateBiasFw,
2901 cellBiasFw,
2902 outputGateBiasFw,
2903 projWeightsFw,
2904 projBiasFw,
2905 outputStateInFw,
2906 cellStateInFw,
2907 inputToInputBw,
2908 inputToForgetBw,
2909 inputToCellBw,
2910 inputToOutputBw,
2911 recurrentToInputBw,
2912 recurrentToForgetBw,
2913 recurrentToCellBw,
2914 recurrentToOutputBw,
2915 cellToInputBw,
2916 cellToForgetBw,
2917 cellToOutputBw,
2918 inputGateBiasBw,
2919 forgetGateBiasBw,
2920 cellBiasBw,
2921 outputGateBiasBw,
2922 projWeightsBw,
2923 projBiasBw,
2924 outputStateInBw,
2925 cellStateInBw,
2926 auxInput,
2927 auxInputToInputFw,
2928 auxInputToForgetFw,
2929 auxInputToCellFw,
2930 auxInputToOutputFw,
2931 auxInputToInputBw,
2932 auxInputToForgetBw,
2933 auxInputToCellBw,
2934 auxInputToOutputBw,
2935 activation,
2936 clipCellState,
2937 clipProjLayer,
2938 mergeOutputs,
2939 timeMajor,
2940 inputLayerNormWeightsFw,
2941 forgetLayerNormWeightsFw,
2942 cellLayerNormWeightsFw,
2943 outputLayerNormWeightsFw,
2944 inputLayerNormWeightsBw,
2945 forgetLayerNormWeightsBw,
2946 cellLayerNormWeightsBw,
2947 outputLayerNormWeightsBw,
2948 },
2949 {
2950 outputFw,
2951 outputBw,
2952 });
2953
2954 lstmTest.testOpsValidations();
2955 }
2956
TEST(OperationValidationTest,LSTM_BIDIRECTIONAL_SEQUENCE)2957 TEST(OperationValidationTest, LSTM_BIDIRECTIONAL_SEQUENCE) {
2958 lstmBidirectionalSequence(ANEURALNETWORKS_TENSOR_FLOAT32);
2959 lstmBidirectionalSequence(ANEURALNETWORKS_TENSOR_FLOAT16);
2960 }
2961
randomMultinomialOpTest(int32_t operandCode)2962 void randomMultinomialOpTest(int32_t operandCode) {
2963 uint32_t inputDims[2] = {5, 5};
2964 ANeuralNetworksOperandType input = {.type = operandCode,
2965 .dimensionCount = 2,
2966 .dimensions = inputDims,
2967 .scale = 0.0f,
2968 .zeroPoint = 0};
2969 ANeuralNetworksOperandType sample_count = {.type = ANEURALNETWORKS_INT32,
2970 .dimensionCount = 0,
2971 .dimensions = nullptr,
2972 .scale = 0.0f,
2973 .zeroPoint = 0};
2974 uint32_t seedDims[1] = {2};
2975 ANeuralNetworksOperandType seed = {.type = ANEURALNETWORKS_TENSOR_INT32,
2976 .dimensionCount = 1,
2977 .dimensions = seedDims,
2978 .scale = 0.0f,
2979 .zeroPoint = 0};
2980 uint32_t outputDims[2] = {5, 7};
2981 ANeuralNetworksOperandType output = {.type = ANEURALNETWORKS_TENSOR_INT32,
2982 .dimensionCount = 2,
2983 .dimensions = outputDims,
2984 .scale = 0.0f,
2985 .zeroPoint = 0};
2986
2987 OperationTestBase multinomialTest(ANEURALNETWORKS_RANDOM_MULTINOMIAL,
2988 {input, sample_count, seed}, {output});
2989 multinomialTest.testOpsValidations();
2990 }
2991
TEST(OperationValidationTest,RANDOM_MULTINOMIAL_float16)2992 TEST(OperationValidationTest, RANDOM_MULTINOMIAL_float16) {
2993 randomMultinomialOpTest(ANEURALNETWORKS_TENSOR_FLOAT16);
2994 }
2995
TEST(OperationValidationTest,RANDOM_MULTINOMIAL_float32)2996 TEST(OperationValidationTest, RANDOM_MULTINOMIAL_float32) {
2997 randomMultinomialOpTest(ANEURALNETWORKS_TENSOR_FLOAT32);
2998 }
2999
TEST(OperationValidationTest,RNN_float16)3000 TEST(OperationValidationTest, RNN_float16) {
3001 uint32_t oneDimensional[1] = {5};
3002 uint32_t twoDimensional[2] = {5, 5};
3003 ANeuralNetworksOperandType floatTensor1D = {.type = ANEURALNETWORKS_TENSOR_FLOAT16,
3004 .dimensionCount = 1,
3005 .dimensions = oneDimensional,
3006 .scale = 0.0f,
3007 .zeroPoint = 0};
3008 ANeuralNetworksOperandType floatTensor2D = {.type = ANEURALNETWORKS_TENSOR_FLOAT16,
3009 .dimensionCount = 2,
3010 .dimensions = twoDimensional,
3011 .scale = 0.0f,
3012 .zeroPoint = 0};
3013 ANeuralNetworksOperandType intScalar = {.type = ANEURALNETWORKS_INT32,
3014 .dimensionCount = 0,
3015 .dimensions = nullptr,
3016 .scale = 0.0f,
3017 .zeroPoint = 0};
3018
3019 ANeuralNetworksOperandType input = floatTensor2D;
3020 ANeuralNetworksOperandType weights = floatTensor2D;
3021 ANeuralNetworksOperandType recurrentWeights = floatTensor2D;
3022 ANeuralNetworksOperandType bias = floatTensor1D;
3023 ANeuralNetworksOperandType hiddenStateIn = floatTensor2D;
3024 ANeuralNetworksOperandType activation = intScalar;
3025
3026 ANeuralNetworksOperandType hiddenStateOut = floatTensor2D;
3027 ANeuralNetworksOperandType output = floatTensor2D;
3028
3029 OperationTestBase rnnTest(ANEURALNETWORKS_RNN,
3030 {input, weights, recurrentWeights, bias, hiddenStateIn, activation},
3031 {hiddenStateOut, output});
3032 rnnTest.testOpsValidations();
3033 }
3034
TEST(OperationValidationTest,RNN_float32)3035 TEST(OperationValidationTest, RNN_float32) {
3036 uint32_t oneDimensional[1] = {5};
3037 uint32_t twoDimensional[2] = {5, 5};
3038 ANeuralNetworksOperandType floatTensor1D = {.type = ANEURALNETWORKS_TENSOR_FLOAT32,
3039 .dimensionCount = 1,
3040 .dimensions = oneDimensional,
3041 .scale = 0.0f,
3042 .zeroPoint = 0};
3043 ANeuralNetworksOperandType floatTensor2D = {.type = ANEURALNETWORKS_TENSOR_FLOAT32,
3044 .dimensionCount = 2,
3045 .dimensions = twoDimensional,
3046 .scale = 0.0f,
3047 .zeroPoint = 0};
3048 ANeuralNetworksOperandType intScalar = {.type = ANEURALNETWORKS_INT32,
3049 .dimensionCount = 0,
3050 .dimensions = nullptr,
3051 .scale = 0.0f,
3052 .zeroPoint = 0};
3053
3054 ANeuralNetworksOperandType input = floatTensor2D;
3055 ANeuralNetworksOperandType weights = floatTensor2D;
3056 ANeuralNetworksOperandType recurrentWeights = floatTensor2D;
3057 ANeuralNetworksOperandType bias = floatTensor1D;
3058 ANeuralNetworksOperandType hiddenStateIn = floatTensor2D;
3059 ANeuralNetworksOperandType activation = intScalar;
3060
3061 ANeuralNetworksOperandType hiddenStateOut = floatTensor2D;
3062 ANeuralNetworksOperandType output = floatTensor2D;
3063
3064 OperationTestBase rnnTest(ANEURALNETWORKS_RNN,
3065 {input, weights, recurrentWeights, bias, hiddenStateIn, activation},
3066 {hiddenStateOut, output});
3067 rnnTest.testOpsValidations();
3068 }
3069
TEST(OperationValidationTest,SVDF_float32)3070 TEST(OperationValidationTest, SVDF_float32) {
3071 uint32_t oneDimensional[1] = {5};
3072 uint32_t twoDimensional[2] = {5, 5};
3073 ANeuralNetworksOperandType floatTensor1D = {.type = ANEURALNETWORKS_TENSOR_FLOAT32,
3074 .dimensionCount = 1,
3075 .dimensions = oneDimensional,
3076 .scale = 0.0f,
3077 .zeroPoint = 0};
3078 ANeuralNetworksOperandType floatTensor2D = {.type = ANEURALNETWORKS_TENSOR_FLOAT32,
3079 .dimensionCount = 2,
3080 .dimensions = twoDimensional,
3081 .scale = 0.0f,
3082 .zeroPoint = 0};
3083 ANeuralNetworksOperandType intScalar = {.type = ANEURALNETWORKS_INT32,
3084 .dimensionCount = 0,
3085 .dimensions = nullptr,
3086 .scale = 0.0f,
3087 .zeroPoint = 0};
3088
3089 ANeuralNetworksOperandType input = floatTensor2D;
3090 ANeuralNetworksOperandType weightsFeature = floatTensor2D;
3091 ANeuralNetworksOperandType weightsTime = floatTensor2D;
3092 ANeuralNetworksOperandType bias = floatTensor1D;
3093 ANeuralNetworksOperandType stateIn = floatTensor2D;
3094 ANeuralNetworksOperandType rank = intScalar;
3095 ANeuralNetworksOperandType activation = intScalar;
3096
3097 ANeuralNetworksOperandType stateOut = floatTensor2D;
3098 ANeuralNetworksOperandType output = floatTensor2D;
3099
3100 OperationTestBase svdfTest(
3101 ANEURALNETWORKS_SVDF,
3102 {input, weightsFeature, weightsTime, bias, stateIn, rank, activation},
3103 {stateOut, output});
3104 svdfTest.testOpsValidations();
3105 }
3106
TEST(OperationValidationTest,SVDF_float16)3107 TEST(OperationValidationTest, SVDF_float16) {
3108 uint32_t oneDimensional[1] = {5};
3109 uint32_t twoDimensional[2] = {5, 5};
3110 ANeuralNetworksOperandType floatTensor1D = {.type = ANEURALNETWORKS_TENSOR_FLOAT16,
3111 .dimensionCount = 1,
3112 .dimensions = oneDimensional,
3113 .scale = 0.0f,
3114 .zeroPoint = 0};
3115 ANeuralNetworksOperandType floatTensor2D = {.type = ANEURALNETWORKS_TENSOR_FLOAT16,
3116 .dimensionCount = 2,
3117 .dimensions = twoDimensional,
3118 .scale = 0.0f,
3119 .zeroPoint = 0};
3120 ANeuralNetworksOperandType intScalar = {.type = ANEURALNETWORKS_INT32,
3121 .dimensionCount = 0,
3122 .dimensions = nullptr,
3123 .scale = 0.0f,
3124 .zeroPoint = 0};
3125
3126 ANeuralNetworksOperandType input = floatTensor2D;
3127 ANeuralNetworksOperandType weightsFeature = floatTensor2D;
3128 ANeuralNetworksOperandType weightsTime = floatTensor2D;
3129 ANeuralNetworksOperandType bias = floatTensor1D;
3130 ANeuralNetworksOperandType stateIn = floatTensor2D;
3131 ANeuralNetworksOperandType rank = intScalar;
3132 ANeuralNetworksOperandType activation = intScalar;
3133
3134 ANeuralNetworksOperandType stateOut = floatTensor2D;
3135 ANeuralNetworksOperandType output = floatTensor2D;
3136
3137 OperationTestBase svdfTest(
3138 ANEURALNETWORKS_SVDF,
3139 {input, weightsFeature, weightsTime, bias, stateIn, rank, activation},
3140 {stateOut, output});
3141 svdfTest.testOpsValidations();
3142 }
3143
stridedSliceOpTest(int32_t operandCode)3144 void stridedSliceOpTest(int32_t operandCode) {
3145 uint32_t inputDimensions[2] = {5, 5};
3146 ANeuralNetworksOperandType input = getOpType(operandCode, 2, inputDimensions);
3147 ANeuralNetworksOperandType output = input;
3148
3149 uint32_t beginsDimensions[1] = {2};
3150 ANeuralNetworksOperandType begins = {.type = ANEURALNETWORKS_TENSOR_INT32,
3151 .dimensionCount = 1,
3152 .dimensions = beginsDimensions,
3153 .scale = 0.0f,
3154 .zeroPoint = 0};
3155
3156 ANeuralNetworksOperandType ends = begins;
3157 ANeuralNetworksOperandType strides = begins;
3158
3159 ANeuralNetworksOperandType beginMask = {.type = ANEURALNETWORKS_INT32,
3160 .dimensionCount = 0,
3161 .dimensions = nullptr,
3162 .scale = 0.0f,
3163 .zeroPoint = 0};
3164 ANeuralNetworksOperandType endMask = beginMask;
3165 ANeuralNetworksOperandType shrinkAxisMask = beginMask;
3166
3167 OperationTestBase stridedSliceTest(
3168 ANEURALNETWORKS_STRIDED_SLICE,
3169 {input, begins, ends, strides, beginMask, endMask, shrinkAxisMask}, {output},
3170 {{TensorRankConstraint::UpTo(4)}});
3171 stridedSliceTest.testOpsValidations();
3172 }
3173
TEST(OperationValidationTest,STRIDED_SLICE_float32)3174 TEST(OperationValidationTest, STRIDED_SLICE_float32) {
3175 stridedSliceOpTest(ANEURALNETWORKS_TENSOR_FLOAT32);
3176 }
3177
TEST(OperationValidationTest,STRIDED_SLICE_float16)3178 TEST(OperationValidationTest, STRIDED_SLICE_float16) {
3179 stridedSliceOpTest(ANEURALNETWORKS_TENSOR_FLOAT16);
3180 }
3181
TEST(OperationValidationTest,STRIDED_SLICE_quant8)3182 TEST(OperationValidationTest, STRIDED_SLICE_quant8) {
3183 stridedSliceOpTest(ANEURALNETWORKS_TENSOR_QUANT8_ASYMM);
3184 }
3185
TEST(OperationValidationTest,STRIDED_SLICE_quant8_signed)3186 TEST(OperationValidationTest, STRIDED_SLICE_quant8_signed) {
3187 stridedSliceOpTest(ANEURALNETWORKS_TENSOR_QUANT8_ASYMM_SIGNED);
3188 }
3189
roiAlignOpTest(int32_t inputOperandCode,int32_t roiOperandCode,int32_t scalarOperandCode)3190 void roiAlignOpTest(int32_t inputOperandCode, int32_t roiOperandCode, int32_t scalarOperandCode) {
3191 uint32_t inDim[] = {1, 4, 4, 1}, roiDim[] = {4, 4}, batchSplitDim[] = {1};
3192 uint32_t outDim[] = {4, 2, 2, 1};
3193 OperationTestBase roiAlignTest(
3194 ANEURALNETWORKS_ROI_ALIGN,
3195 {getOpType(inputOperandCode, 4, inDim), getOpType(roiOperandCode, 2, roiDim),
3196 getOpType(ANEURALNETWORKS_TENSOR_INT32, 1, batchSplitDim),
3197 getOpType(ANEURALNETWORKS_INT32), getOpType(ANEURALNETWORKS_INT32),
3198 getOpType(scalarOperandCode), getOpType(scalarOperandCode),
3199 getOpType(ANEURALNETWORKS_INT32), getOpType(ANEURALNETWORKS_INT32),
3200 getOpType(ANEURALNETWORKS_BOOL)},
3201 {getOpType(inputOperandCode, 4, outDim)});
3202 roiAlignTest.testOpsValidations();
3203 }
3204
TEST(OperationValidationTest,ROI_ALIGN_float16)3205 TEST(OperationValidationTest, ROI_ALIGN_float16) {
3206 roiAlignOpTest(ANEURALNETWORKS_TENSOR_FLOAT16, ANEURALNETWORKS_TENSOR_FLOAT16,
3207 ANEURALNETWORKS_FLOAT16);
3208 }
3209
TEST(OperationValidationTest,ROI_ALIGN_float32)3210 TEST(OperationValidationTest, ROI_ALIGN_float32) {
3211 roiAlignOpTest(ANEURALNETWORKS_TENSOR_FLOAT32, ANEURALNETWORKS_TENSOR_FLOAT32,
3212 ANEURALNETWORKS_FLOAT32);
3213 }
3214
TEST(OperationValidationTest,ROI_ALIGN_quant8)3215 TEST(OperationValidationTest, ROI_ALIGN_quant8) {
3216 roiAlignOpTest(ANEURALNETWORKS_TENSOR_QUANT8_ASYMM, ANEURALNETWORKS_TENSOR_QUANT16_ASYMM,
3217 ANEURALNETWORKS_FLOAT32);
3218 }
3219
TEST(OperationValidationTest,ROI_ALIGN_quant8signed)3220 TEST(OperationValidationTest, ROI_ALIGN_quant8signed) {
3221 roiAlignOpTest(ANEURALNETWORKS_TENSOR_QUANT8_ASYMM_SIGNED, ANEURALNETWORKS_TENSOR_QUANT16_ASYMM,
3222 ANEURALNETWORKS_FLOAT32);
3223 }
3224
roiPoolingOpTest(int32_t inputOperandCode,int32_t roiOperandCode,int32_t scalarOperandCode)3225 void roiPoolingOpTest(int32_t inputOperandCode, int32_t roiOperandCode, int32_t scalarOperandCode) {
3226 uint32_t inDim[] = {1, 4, 4, 1}, roiDim[] = {4, 4}, batchSplitDim[] = {1};
3227 uint32_t outDim[] = {4, 2, 2, 1};
3228 OperationTestBase roiPoolingTest(
3229 ANEURALNETWORKS_ROI_POOLING,
3230 {getOpType(inputOperandCode, 4, inDim), getOpType(roiOperandCode, 2, roiDim),
3231 getOpType(ANEURALNETWORKS_TENSOR_INT32, 1, batchSplitDim),
3232 getOpType(ANEURALNETWORKS_INT32), getOpType(ANEURALNETWORKS_INT32),
3233 getOpType(scalarOperandCode), getOpType(scalarOperandCode),
3234 getOpType(ANEURALNETWORKS_BOOL)},
3235 {getOpType(inputOperandCode, 4, outDim)});
3236 roiPoolingTest.testOpsValidations();
3237 }
3238
TEST(OperationValidationTest,ROI_POOLING_float16)3239 TEST(OperationValidationTest, ROI_POOLING_float16) {
3240 roiPoolingOpTest(ANEURALNETWORKS_TENSOR_FLOAT16, ANEURALNETWORKS_TENSOR_FLOAT16,
3241 ANEURALNETWORKS_FLOAT16);
3242 }
3243
TEST(OperationValidationTest,ROI_POOLING_float32)3244 TEST(OperationValidationTest, ROI_POOLING_float32) {
3245 roiPoolingOpTest(ANEURALNETWORKS_TENSOR_FLOAT32, ANEURALNETWORKS_TENSOR_FLOAT32,
3246 ANEURALNETWORKS_FLOAT32);
3247 }
3248
TEST(OperationValidationTest,ROI_POOLING_quant8)3249 TEST(OperationValidationTest, ROI_POOLING_quant8) {
3250 roiPoolingOpTest(ANEURALNETWORKS_TENSOR_QUANT8_ASYMM, ANEURALNETWORKS_TENSOR_QUANT16_ASYMM,
3251 ANEURALNETWORKS_FLOAT32);
3252 }
3253
TEST(OperationValidationTest,ROI_POOLING_quant8signed)3254 TEST(OperationValidationTest, ROI_POOLING_quant8signed) {
3255 roiPoolingOpTest(ANEURALNETWORKS_TENSOR_QUANT8_ASYMM_SIGNED,
3256 ANEURALNETWORKS_TENSOR_QUANT16_ASYMM, ANEURALNETWORKS_FLOAT32);
3257 }
3258
heatmapMaxKeypointOpTest(int32_t heatmapOperandCode,int32_t roiOperandCode)3259 void heatmapMaxKeypointOpTest(int32_t heatmapOperandCode, int32_t roiOperandCode) {
3260 uint32_t heatmapDim[] = {6, 4, 4, 1}, boxDim[] = {6, 4}, outScoreDim[] = {6, 1},
3261 outKeypointDim[] = {6, 1, 2};
3262 OperationTestBase heatmapMaxKeypointTest(
3263 ANEURALNETWORKS_HEATMAP_MAX_KEYPOINT,
3264 {getOpType(heatmapOperandCode, 4, heatmapDim), getOpType(roiOperandCode, 2, boxDim),
3265 getOpType(ANEURALNETWORKS_BOOL)},
3266 {getOpType(heatmapOperandCode, 2, outScoreDim),
3267 getOpType(roiOperandCode, 3, outKeypointDim)});
3268 heatmapMaxKeypointTest.testOpsValidations();
3269 }
3270
TEST(OperationValidationTest,HEATMAP_MAX_KEYPOINT_float16)3271 TEST(OperationValidationTest, HEATMAP_MAX_KEYPOINT_float16) {
3272 heatmapMaxKeypointOpTest(ANEURALNETWORKS_TENSOR_FLOAT16, ANEURALNETWORKS_TENSOR_FLOAT16);
3273 }
3274
TEST(OperationValidationTest,HEATMAP_MAX_KEYPOINT_float32)3275 TEST(OperationValidationTest, HEATMAP_MAX_KEYPOINT_float32) {
3276 heatmapMaxKeypointOpTest(ANEURALNETWORKS_TENSOR_FLOAT32, ANEURALNETWORKS_TENSOR_FLOAT32);
3277 }
3278
TEST(OperationValidationTest,HEATMAP_MAX_KEYPOINT_quant)3279 TEST(OperationValidationTest, HEATMAP_MAX_KEYPOINT_quant) {
3280 heatmapMaxKeypointOpTest(ANEURALNETWORKS_TENSOR_QUANT8_ASYMM,
3281 ANEURALNETWORKS_TENSOR_QUANT16_ASYMM);
3282 }
3283
TEST(OperationValidationTest,HEATMAP_MAX_KEYPOINT_quant_signed)3284 TEST(OperationValidationTest, HEATMAP_MAX_KEYPOINT_quant_signed) {
3285 heatmapMaxKeypointOpTest(ANEURALNETWORKS_TENSOR_QUANT8_ASYMM_SIGNED,
3286 ANEURALNETWORKS_TENSOR_QUANT16_ASYMM);
3287 }
3288
instanceNormalizationOpTest(int32_t inputOperandType)3289 void instanceNormalizationOpTest(int32_t inputOperandType) {
3290 SCOPED_TRACE(inputOperandType);
3291 uint32_t inputDims[4] = {4, 4, 4, 4};
3292 ANeuralNetworksOperandType input = getOpType(inputOperandType, 4, inputDims);
3293 ANeuralNetworksOperandType floatScalar = getOpType(ANEURALNETWORKS_FLOAT32);
3294 if (inputOperandType == ANEURALNETWORKS_TENSOR_FLOAT16) {
3295 floatScalar = getOpType(ANEURALNETWORKS_FLOAT16);
3296 }
3297 ANeuralNetworksOperandType gamma = floatScalar;
3298 ANeuralNetworksOperandType beta = floatScalar;
3299 ANeuralNetworksOperandType epsilon = floatScalar;
3300 ANeuralNetworksOperandType isNCHW = getOpType(ANEURALNETWORKS_BOOL);
3301 ANeuralNetworksOperandType output = input;
3302
3303 OperationTestBase test(ANEURALNETWORKS_INSTANCE_NORMALIZATION,
3304 {input, gamma, beta, epsilon, isNCHW}, {output});
3305 test.testOpsValidations();
3306 }
3307
TEST(OperationValidationTest,INSTANCE_NORMALIZATION)3308 TEST(OperationValidationTest, INSTANCE_NORMALIZATION) {
3309 instanceNormalizationOpTest(ANEURALNETWORKS_TENSOR_FLOAT16);
3310 instanceNormalizationOpTest(ANEURALNETWORKS_TENSOR_FLOAT32);
3311 }
3312
groupedConvOpTest(int32_t inputOperandCode,int32_t filterOperandCode)3313 void groupedConvOpTest(int32_t inputOperandCode, int32_t filterOperandCode) {
3314 uint32_t inDim[] = {1, 3, 3, 2}, filterDim[] = {2, 2, 2, 1}, biasDim[] = {2};
3315 uint32_t outDim[] = {1, 2, 2, 2};
3316 ANeuralNetworksOperandType input = getOpType(inputOperandCode, 4, inDim);
3317
3318 float filterScales[2] = {0.5f, 1.0f};
3319 ANeuralNetworksOperandType filter = getOpType(filterOperandCode, 4, filterDim);
3320
3321 ANeuralNetworksSymmPerChannelQuantParams filterChannelQuantParams = {
3322 .channelDim = 0,
3323 .scaleCount = 2,
3324 .scales = filterScales,
3325 };
3326
3327 ANeuralNetworksOperandType bias = getOpType(inputOperandCode, 1, biasDim);
3328 if (filterOperandCode == ANEURALNETWORKS_TENSOR_QUANT8_ASYMM ||
3329 filterOperandCode == ANEURALNETWORKS_TENSOR_QUANT8_ASYMM_SIGNED) {
3330 bias.type = ANEURALNETWORKS_TENSOR_INT32;
3331 bias.scale = 0.25f;
3332 }
3333 if (filterOperandCode == ANEURALNETWORKS_TENSOR_QUANT8_SYMM_PER_CHANNEL) {
3334 bias.type = ANEURALNETWORKS_TENSOR_INT32;
3335 bias.scale = 0.0f;
3336 }
3337
3338 ANeuralNetworksOperandType scalar = getOpType(ANEURALNETWORKS_INT32);
3339 ANeuralNetworksOperandType layout = getOpType(ANEURALNETWORKS_BOOL);
3340
3341 ANeuralNetworksOperandType output = getOpType(inputOperandCode, 4, outDim);
3342
3343 OperationTestBase explicitGroupedConvTest(ANEURALNETWORKS_GROUPED_CONV_2D,
3344 {input, filter, bias, scalar, scalar, scalar, scalar,
3345 scalar, scalar, scalar, scalar, layout},
3346 {output});
3347 if (filterOperandCode == ANEURALNETWORKS_TENSOR_QUANT8_SYMM_PER_CHANNEL) {
3348 explicitGroupedConvTest.setInputSymmPerChannelQuantParams(1, filterChannelQuantParams);
3349 }
3350 explicitGroupedConvTest.testOpsValidations();
3351
3352 OperationTestBase implicitGroupedConvTest(
3353 ANEURALNETWORKS_GROUPED_CONV_2D,
3354 {input, filter, bias, scalar, scalar, scalar, scalar, scalar, layout}, {output});
3355 if (filterOperandCode == ANEURALNETWORKS_TENSOR_QUANT8_SYMM_PER_CHANNEL) {
3356 implicitGroupedConvTest.setInputSymmPerChannelQuantParams(1, filterChannelQuantParams);
3357 }
3358 implicitGroupedConvTest.testOpsValidations();
3359 }
3360
TEST(OperationValidationTest,GROUPED_CONV_2D_float16)3361 TEST(OperationValidationTest, GROUPED_CONV_2D_float16) {
3362 groupedConvOpTest(ANEURALNETWORKS_TENSOR_FLOAT16, ANEURALNETWORKS_TENSOR_FLOAT16);
3363 }
3364
TEST(OperationValidationTest,GROUPED_CONV_2D_float32)3365 TEST(OperationValidationTest, GROUPED_CONV_2D_float32) {
3366 groupedConvOpTest(ANEURALNETWORKS_TENSOR_FLOAT32, ANEURALNETWORKS_TENSOR_FLOAT32);
3367 }
3368
TEST(OperationValidationTest,GROUPED_CONV_2D_quant8)3369 TEST(OperationValidationTest, GROUPED_CONV_2D_quant8) {
3370 groupedConvOpTest(ANEURALNETWORKS_TENSOR_QUANT8_ASYMM, ANEURALNETWORKS_TENSOR_QUANT8_ASYMM);
3371 }
3372
TEST(OperationValidationTest,GROUPED_CONV_2D_quant8_per_channel)3373 TEST(OperationValidationTest, GROUPED_CONV_2D_quant8_per_channel) {
3374 groupedConvOpTest(ANEURALNETWORKS_TENSOR_QUANT8_ASYMM,
3375 ANEURALNETWORKS_TENSOR_QUANT8_SYMM_PER_CHANNEL);
3376 }
3377
TEST(OperationValidationTest,GROUPED_CONV_2D_quant8signed)3378 TEST(OperationValidationTest, GROUPED_CONV_2D_quant8signed) {
3379 groupedConvOpTest(ANEURALNETWORKS_TENSOR_QUANT8_ASYMM_SIGNED,
3380 ANEURALNETWORKS_TENSOR_QUANT8_ASYMM_SIGNED);
3381 }
3382
TEST(OperationValidationTest,GROUPED_CONV_2D_quant8signed_per_channel)3383 TEST(OperationValidationTest, GROUPED_CONV_2D_quant8signed_per_channel) {
3384 groupedConvOpTest(ANEURALNETWORKS_TENSOR_QUANT8_ASYMM_SIGNED,
3385 ANEURALNETWORKS_TENSOR_QUANT8_SYMM_PER_CHANNEL);
3386 }
3387
transposeConvOpTest(int32_t inputOperandCode,int32_t filterOperandCode)3388 void transposeConvOpTest(int32_t inputOperandCode, int32_t filterOperandCode) {
3389 uint32_t inDim[] = {1, 2, 2, 2}, filterDim[] = {2, 3, 3, 1}, biasDim[] = {2};
3390 uint32_t outDim[] = {1, 5, 5, 2}, outShapeDim[] = {4};
3391 ANeuralNetworksOperandType input = getOpType(inputOperandCode, 4, inDim);
3392 ANeuralNetworksOperandType filter = getOpType(filterOperandCode, 4, filterDim);
3393
3394 float filterScales[2] = {0.5f, 1.0f};
3395 ANeuralNetworksSymmPerChannelQuantParams filterChannelQuantParams = {
3396 .channelDim = 0,
3397 .scaleCount = 2,
3398 .scales = filterScales,
3399 };
3400
3401 ANeuralNetworksOperandType bias = getOpType(inputOperandCode, 1, biasDim);
3402 if (filterOperandCode == ANEURALNETWORKS_TENSOR_QUANT8_ASYMM ||
3403 filterOperandCode == ANEURALNETWORKS_TENSOR_QUANT8_ASYMM_SIGNED) {
3404 bias.type = ANEURALNETWORKS_TENSOR_INT32;
3405 bias.scale = 0.25f;
3406 }
3407 if (filterOperandCode == ANEURALNETWORKS_TENSOR_QUANT8_SYMM_PER_CHANNEL) {
3408 bias.type = ANEURALNETWORKS_TENSOR_INT32;
3409 bias.scale = 0.0f;
3410 }
3411
3412 ANeuralNetworksOperandType scalar = getOpType(ANEURALNETWORKS_INT32);
3413 ANeuralNetworksOperandType layout = getOpType(ANEURALNETWORKS_BOOL);
3414 ANeuralNetworksOperandType output = getOpType(inputOperandCode, 4, outDim);
3415
3416 OperationTestBase explicitTransposeConvTest(
3417 ANEURALNETWORKS_TRANSPOSE_CONV_2D,
3418 {input, filter, bias, scalar, scalar, scalar, scalar, scalar, scalar, scalar, layout},
3419 {output});
3420 if (filterOperandCode == ANEURALNETWORKS_TENSOR_QUANT8_SYMM_PER_CHANNEL) {
3421 explicitTransposeConvTest.setInputSymmPerChannelQuantParams(1, filterChannelQuantParams);
3422 }
3423 explicitTransposeConvTest.testOpsValidations();
3424
3425 OperationTestBase implicitTransposeConvTest(
3426 ANEURALNETWORKS_TRANSPOSE_CONV_2D,
3427 {input, filter, bias, getOpType(ANEURALNETWORKS_TENSOR_INT32, 1, outShapeDim), scalar,
3428 scalar, scalar, scalar, layout},
3429 {output});
3430 if (filterOperandCode == ANEURALNETWORKS_TENSOR_QUANT8_SYMM_PER_CHANNEL) {
3431 implicitTransposeConvTest.setInputSymmPerChannelQuantParams(1, filterChannelQuantParams);
3432 }
3433 implicitTransposeConvTest.testOpsValidations();
3434 }
3435
TEST(OperationValidationTest,TRANSPOSE_CONV_2D_float16)3436 TEST(OperationValidationTest, TRANSPOSE_CONV_2D_float16) {
3437 transposeConvOpTest(ANEURALNETWORKS_TENSOR_FLOAT16, ANEURALNETWORKS_TENSOR_FLOAT16);
3438 }
3439
TEST(OperationValidationTest,TRANSPOSE_CONV_2D_float32)3440 TEST(OperationValidationTest, TRANSPOSE_CONV_2D_float32) {
3441 transposeConvOpTest(ANEURALNETWORKS_TENSOR_FLOAT32, ANEURALNETWORKS_TENSOR_FLOAT32);
3442 }
3443
TEST(OperationValidationTest,TRANSPOSE_CONV_2D_quant8)3444 TEST(OperationValidationTest, TRANSPOSE_CONV_2D_quant8) {
3445 transposeConvOpTest(ANEURALNETWORKS_TENSOR_QUANT8_ASYMM, ANEURALNETWORKS_TENSOR_QUANT8_ASYMM);
3446 }
3447
TEST(OperationValidationTest,TRANSPOSE_CONV_2D_quant8_per_channel)3448 TEST(OperationValidationTest, TRANSPOSE_CONV_2D_quant8_per_channel) {
3449 transposeConvOpTest(ANEURALNETWORKS_TENSOR_QUANT8_ASYMM,
3450 ANEURALNETWORKS_TENSOR_QUANT8_SYMM_PER_CHANNEL);
3451 }
3452
TEST(OperationValidationTest,TRANSPOSE_CONV_2D_quant8_signed)3453 TEST(OperationValidationTest, TRANSPOSE_CONV_2D_quant8_signed) {
3454 transposeConvOpTest(ANEURALNETWORKS_TENSOR_QUANT8_ASYMM_SIGNED,
3455 ANEURALNETWORKS_TENSOR_QUANT8_ASYMM_SIGNED);
3456 }
3457
TEST(OperationValidationTest,TRANSPOSE_CONV_2D_quant8_signed_per_channel)3458 TEST(OperationValidationTest, TRANSPOSE_CONV_2D_quant8_signed_per_channel) {
3459 transposeConvOpTest(ANEURALNETWORKS_TENSOR_QUANT8_ASYMM_SIGNED,
3460 ANEURALNETWORKS_TENSOR_QUANT8_SYMM_PER_CHANNEL);
3461 }
3462
channelShuffleOpTest(int32_t operandCode)3463 void channelShuffleOpTest(int32_t operandCode) {
3464 uint32_t inoutDim[] = {2, 2, 3, 12};
3465 OperationTestBase channelShuffleTest(
3466 ANEURALNETWORKS_CHANNEL_SHUFFLE,
3467 {getOpType(operandCode, 2, inoutDim), getOpType(ANEURALNETWORKS_INT32),
3468 getOpType(ANEURALNETWORKS_INT32)},
3469 {getOpType(operandCode, 2, inoutDim)}, {{TensorRankConstraint::UpTo(4)}});
3470 channelShuffleTest.testOpsValidations();
3471 }
3472
TEST(OperationValidationTest,CHANNEL_SHUFFLE_float16)3473 TEST(OperationValidationTest, CHANNEL_SHUFFLE_float16) {
3474 channelShuffleOpTest(ANEURALNETWORKS_TENSOR_FLOAT16);
3475 }
3476
TEST(OperationValidationTest,CHANNEL_SHUFFLE_float32)3477 TEST(OperationValidationTest, CHANNEL_SHUFFLE_float32) {
3478 channelShuffleOpTest(ANEURALNETWORKS_TENSOR_FLOAT32);
3479 }
3480
TEST(OperationValidationTest,CHANNEL_SHUFFLE_quant8)3481 TEST(OperationValidationTest, CHANNEL_SHUFFLE_quant8) {
3482 channelShuffleOpTest(ANEURALNETWORKS_TENSOR_QUANT8_ASYMM);
3483 }
3484
TEST(OperationValidationTest,CHANNEL_SHUFFLE_quant8signed)3485 TEST(OperationValidationTest, CHANNEL_SHUFFLE_quant8signed) {
3486 channelShuffleOpTest(ANEURALNETWORKS_TENSOR_QUANT8_ASYMM_SIGNED);
3487 }
3488
detectionPostprocessingOpTest(int32_t inputOperandCode)3489 void detectionPostprocessingOpTest(int32_t inputOperandCode) {
3490 SCOPED_TRACE(inputOperandCode);
3491 const int numBatches = 2;
3492 const int numAnchors = 10;
3493 const int numClasses = 5;
3494 const int lengthBoxEncoding = 4;
3495
3496 uint32_t inputDims[3] = {numBatches, numAnchors, numClasses};
3497 ANeuralNetworksOperandType input = getOpType(inputOperandCode, 3, inputDims);
3498 uint32_t deltasDims[3] = {numBatches, numAnchors, lengthBoxEncoding};
3499 ANeuralNetworksOperandType deltas = getOpType(inputOperandCode, 3, deltasDims);
3500 uint32_t anchorsDims[2] = {numAnchors, 4};
3501 ANeuralNetworksOperandType anchors = getOpType(inputOperandCode, 2, anchorsDims);
3502 ANeuralNetworksOperandType scaleScalar = getOpType(ANEURALNETWORKS_FLOAT32);
3503 if (inputOperandCode == ANEURALNETWORKS_TENSOR_FLOAT16) {
3504 scaleScalar = getOpType(ANEURALNETWORKS_FLOAT16);
3505 }
3506 ANeuralNetworksOperandType isRegularNMS = getOpType(ANEURALNETWORKS_BOOL);
3507 ANeuralNetworksOperandType maxNumDetections = getOpType(ANEURALNETWORKS_INT32);
3508 ANeuralNetworksOperandType numOfClassesPerDetection = maxNumDetections;
3509 ANeuralNetworksOperandType numOfDetections = numOfClassesPerDetection;
3510 ANeuralNetworksOperandType scoreThreshold = scaleScalar;
3511 ANeuralNetworksOperandType iouThreshold = scaleScalar;
3512 ANeuralNetworksOperandType includeBackground = getOpType(ANEURALNETWORKS_BOOL);
3513 // Outputs
3514 const int maxNumDetectionsValue = 5;
3515 uint32_t outputScoreDims[2] = {numBatches, maxNumDetectionsValue};
3516 ANeuralNetworksOperandType outputScore = getOpType(inputOperandCode, 2, outputScoreDims);
3517 uint32_t boundingBoxesDims[3] = {numBatches, maxNumDetectionsValue, 4};
3518 ANeuralNetworksOperandType boundingBoxes = getOpType(inputOperandCode, 3, boundingBoxesDims);
3519 ANeuralNetworksOperandType classLabel =
3520 getOpType(ANEURALNETWORKS_TENSOR_INT32, 2, outputScoreDims);
3521 uint32_t numValidDims[1] = {numBatches};
3522 ANeuralNetworksOperandType numValid = getOpType(ANEURALNETWORKS_TENSOR_INT32, 1, numValidDims);
3523
3524 OperationTestBase test(ANEURALNETWORKS_DETECTION_POSTPROCESSING,
3525 {input, deltas, anchors, scaleScalar, scaleScalar, scaleScalar,
3526 scaleScalar, isRegularNMS, maxNumDetections, numOfClassesPerDetection,
3527 numOfDetections, scoreThreshold, iouThreshold, includeBackground},
3528 {outputScore, boundingBoxes, classLabel, numValid});
3529 test.testOpsValidations();
3530 }
3531
TEST(OperationValidationTest,DETECTION_POSTPROCESSING)3532 TEST(OperationValidationTest, DETECTION_POSTPROCESSING) {
3533 detectionPostprocessingOpTest(ANEURALNETWORKS_TENSOR_FLOAT16);
3534 detectionPostprocessingOpTest(ANEURALNETWORKS_TENSOR_FLOAT32);
3535 }
3536
preluOpTest(int32_t operandCode)3537 void preluOpTest(int32_t operandCode) {
3538 uint32_t inoutDim[] = {1, 2, 2, 3}, alphaDim[] = {1, 1, 3};
3539 OperationTestBase preluTest(
3540 ANEURALNETWORKS_PRELU,
3541 {getOpType(operandCode, 4, inoutDim), getOpType(operandCode, 3, alphaDim)},
3542 {getOpType(operandCode, 4, inoutDim)});
3543 preluTest.testOpsValidations();
3544 }
3545
TEST(OperationValidationTest,PRELU_float16)3546 TEST(OperationValidationTest, PRELU_float16) {
3547 preluOpTest(ANEURALNETWORKS_TENSOR_FLOAT16);
3548 }
3549
TEST(OperationValidationTest,PRELU_float32)3550 TEST(OperationValidationTest, PRELU_float32) {
3551 preluOpTest(ANEURALNETWORKS_TENSOR_FLOAT32);
3552 }
3553
TEST(OperationValidationTest,PRELU_quant8)3554 TEST(OperationValidationTest, PRELU_quant8) {
3555 preluOpTest(ANEURALNETWORKS_TENSOR_QUANT8_ASYMM);
3556 }
3557
TEST(OperationValidationTest,PRELU_quant8signed)3558 TEST(OperationValidationTest, PRELU_quant8signed) {
3559 preluOpTest(ANEURALNETWORKS_TENSOR_QUANT8_ASYMM_SIGNED);
3560 }
3561
normalizationOpTest(ANeuralNetworksOperationType operationCode,int32_t operandCode)3562 void normalizationOpTest(ANeuralNetworksOperationType operationCode, int32_t operandCode) {
3563 uint32_t inputDim[] = {2, 2, 2, 2};
3564 OperationTestBase normalizationTest(operationCode, {getOpType(operandCode, 4, inputDim)},
3565 {getOpType(operandCode, 4, inputDim)});
3566 normalizationTest.testOpsValidations();
3567
3568 OperationTestBase normalizationAxisTest(
3569 operationCode, {getOpType(operandCode, 4, inputDim), getOpType(ANEURALNETWORKS_INT32)},
3570 {getOpType(operandCode, 4, inputDim)}, {{TensorRankConstraint::UpTo(4)}});
3571 normalizationAxisTest.testOpsValidations();
3572 }
3573
TEST(OperationValidationTest,L2_NORMALIZATION_float16)3574 TEST(OperationValidationTest, L2_NORMALIZATION_float16) {
3575 normalizationOpTest(ANEURALNETWORKS_L2_NORMALIZATION, ANEURALNETWORKS_TENSOR_FLOAT16);
3576 }
3577
TEST(OperationValidationTest,L2_NORMALIZATION_float32)3578 TEST(OperationValidationTest, L2_NORMALIZATION_float32) {
3579 normalizationOpTest(ANEURALNETWORKS_L2_NORMALIZATION, ANEURALNETWORKS_TENSOR_FLOAT32);
3580 }
3581
TEST(OperationValidationTest,L2_NORMALIZATION_quant8)3582 TEST(OperationValidationTest, L2_NORMALIZATION_quant8) {
3583 normalizationOpTest(ANEURALNETWORKS_L2_NORMALIZATION, ANEURALNETWORKS_TENSOR_QUANT8_ASYMM);
3584 }
3585
TEST(OperationValidationTest,L2_NORMALIZATION_quant8_signed)3586 TEST(OperationValidationTest, L2_NORMALIZATION_quant8_signed) {
3587 normalizationOpTest(ANEURALNETWORKS_L2_NORMALIZATION,
3588 ANEURALNETWORKS_TENSOR_QUANT8_ASYMM_SIGNED);
3589 }
3590
localResponseNormOpTest(int32_t operandCode)3591 void localResponseNormOpTest(int32_t operandCode) {
3592 int32_t floatScalarType = (operandCode == ANEURALNETWORKS_TENSOR_FLOAT32)
3593 ? ANEURALNETWORKS_FLOAT32
3594 : ANEURALNETWORKS_FLOAT16;
3595 uint32_t inputDim[] = {2, 2, 2, 6};
3596 OperationTestBase lrnTest(
3597 ANEURALNETWORKS_LOCAL_RESPONSE_NORMALIZATION,
3598 {getOpType(operandCode, 4, inputDim), getOpType(ANEURALNETWORKS_INT32),
3599 getOpType(floatScalarType), getOpType(floatScalarType), getOpType(floatScalarType)},
3600 {getOpType(operandCode, 4, inputDim)}, {{TensorRankConstraint::UpTo(4), {0}}});
3601 lrnTest.testOpsValidations();
3602
3603 OperationTestBase lrnAxisTest(
3604 ANEURALNETWORKS_LOCAL_RESPONSE_NORMALIZATION,
3605 {getOpType(operandCode, 4, inputDim), getOpType(ANEURALNETWORKS_INT32),
3606 getOpType(floatScalarType), getOpType(floatScalarType), getOpType(floatScalarType),
3607 getOpType(ANEURALNETWORKS_INT32)},
3608 {getOpType(operandCode, 4, inputDim)}, {{TensorRankConstraint::UpTo(4), {0}}});
3609 lrnAxisTest.testOpsValidations();
3610 }
3611
TEST(OperationValidationTest,LOCAL_RESPONSE_NORMALIZATION_float16)3612 TEST(OperationValidationTest, LOCAL_RESPONSE_NORMALIZATION_float16) {
3613 localResponseNormOpTest(ANEURALNETWORKS_TENSOR_FLOAT16);
3614 }
3615
TEST(OperationValidationTest,LOCAL_RESPONSE_NORMALIZATION_float32)3616 TEST(OperationValidationTest, LOCAL_RESPONSE_NORMALIZATION_float32) {
3617 localResponseNormOpTest(ANEURALNETWORKS_TENSOR_FLOAT32);
3618 }
3619
axisAlignedBBoxTransformOpTest(int32_t roiOperandCode,int32_t deltaOperandCode)3620 void axisAlignedBBoxTransformOpTest(int32_t roiOperandCode, int32_t deltaOperandCode) {
3621 uint32_t roiDim[] = {5, 4}, deltaDim[] = {5, 8}, bsDim[] = {5}, imageDim[] = {5, 2};
3622 uint32_t outDim[] = {5, 8};
3623 OperationTestBase axisAlignedBBoxTransformTest(
3624 ANEURALNETWORKS_AXIS_ALIGNED_BBOX_TRANSFORM,
3625 {getOpType(roiOperandCode, 2, roiDim), getOpType(deltaOperandCode, 2, deltaDim),
3626 getOpType(ANEURALNETWORKS_TENSOR_INT32, 1, bsDim),
3627 getOpType(roiOperandCode, 2, imageDim)},
3628 {getOpType(roiOperandCode, 2, outDim)});
3629 axisAlignedBBoxTransformTest.testOpsValidations();
3630 }
3631
TEST(OperationValidationTest,AXIS_ALIGNED_BBOX_TRANSFORM_float16)3632 TEST(OperationValidationTest, AXIS_ALIGNED_BBOX_TRANSFORM_float16) {
3633 axisAlignedBBoxTransformOpTest(ANEURALNETWORKS_TENSOR_FLOAT16, ANEURALNETWORKS_TENSOR_FLOAT16);
3634 }
3635
TEST(OperationValidationTest,AXIS_ALIGNED_BBOX_TRANSFORM_float32)3636 TEST(OperationValidationTest, AXIS_ALIGNED_BBOX_TRANSFORM_float32) {
3637 axisAlignedBBoxTransformOpTest(ANEURALNETWORKS_TENSOR_FLOAT32, ANEURALNETWORKS_TENSOR_FLOAT32);
3638 }
3639
TEST(OperationValidationTest,AXIS_ALIGNED_BBOX_TRANSFORM_quant)3640 TEST(OperationValidationTest, AXIS_ALIGNED_BBOX_TRANSFORM_quant) {
3641 axisAlignedBBoxTransformOpTest(ANEURALNETWORKS_TENSOR_QUANT16_ASYMM,
3642 ANEURALNETWORKS_TENSOR_QUANT8_ASYMM);
3643 }
3644
TEST(OperationValidationTest,AXIS_ALIGNED_BBOX_TRANSFORM_quant_signed)3645 TEST(OperationValidationTest, AXIS_ALIGNED_BBOX_TRANSFORM_quant_signed) {
3646 axisAlignedBBoxTransformOpTest(ANEURALNETWORKS_TENSOR_QUANT16_ASYMM,
3647 ANEURALNETWORKS_TENSOR_QUANT8_ASYMM_SIGNED);
3648 }
3649
sliceTest(int32_t operandCode)3650 void sliceTest(int32_t operandCode) {
3651 uint32_t inputDim[] = {3, 3, 3};
3652 uint32_t startDim[] = {3};
3653 uint32_t sizeDim[] = {3};
3654 uint32_t outputDim[] = {1, 2, 3};
3655
3656 OperationTestBase sliceTest(ANEURALNETWORKS_SLICE,
3657 {getOpType(operandCode, 3, inputDim),
3658 getOpType(ANEURALNETWORKS_TENSOR_INT32, 1, startDim),
3659 getOpType(ANEURALNETWORKS_TENSOR_INT32, 1, sizeDim)},
3660 {getOpType(operandCode, 3, outputDim)});
3661 sliceTest.testOpsValidations();
3662 }
3663
TEST(OperationValidationTest,SLICE_float32)3664 TEST(OperationValidationTest, SLICE_float32) {
3665 sliceTest(ANEURALNETWORKS_TENSOR_FLOAT32);
3666 }
TEST(OperationValidationTest,SLICE_int32)3667 TEST(OperationValidationTest, SLICE_int32) {
3668 sliceTest(ANEURALNETWORKS_TENSOR_INT32);
3669 }
TEST(OperationValidationTest,SLICE_uint8)3670 TEST(OperationValidationTest, SLICE_uint8) {
3671 sliceTest(ANEURALNETWORKS_TENSOR_QUANT8_ASYMM);
3672 }
TEST(OperationValidationTest,SLICE_int8)3673 TEST(OperationValidationTest, SLICE_int8) {
3674 sliceTest(ANEURALNETWORKS_TENSOR_QUANT8_ASYMM_SIGNED);
3675 }
TEST(OperationValidationTest,SLICE_float16)3676 TEST(OperationValidationTest, SLICE_float16) {
3677 sliceTest(ANEURALNETWORKS_TENSOR_FLOAT16);
3678 }
3679
logicalTest(ANeuralNetworksOperationType operationCode)3680 void logicalTest(ANeuralNetworksOperationType operationCode) {
3681 uint32_t inputDimensions[4] = {2, 2, 2, 2};
3682 ANeuralNetworksOperandType input1 = {.type = ANEURALNETWORKS_TENSOR_BOOL8,
3683 .dimensionCount = 4,
3684 .dimensions = inputDimensions,
3685 .scale = 0.0f,
3686 .zeroPoint = 0};
3687 ANeuralNetworksOperandType input2 = input1;
3688 ANeuralNetworksOperandType output = input1;
3689
3690 OperationTestBase test(operationCode, {input1, input2}, {output});
3691 test.testOpsValidations();
3692 }
3693
TEST(OperationValidationTest,LOGICAL_AND)3694 TEST(OperationValidationTest, LOGICAL_AND) {
3695 logicalTest(ANEURALNETWORKS_LOGICAL_AND);
3696 }
3697
TEST(OperationValidationTest,LOGICAL_OR)3698 TEST(OperationValidationTest, LOGICAL_OR) {
3699 logicalTest(ANEURALNETWORKS_LOGICAL_OR);
3700 }
3701
comparisonTest(ANeuralNetworksOperationType operationCode,int32_t inputOperandType)3702 void comparisonTest(ANeuralNetworksOperationType operationCode, int32_t inputOperandType) {
3703 uint32_t inputDimensions[4] = {2, 2, 2, 2};
3704 ANeuralNetworksOperandType input1 = getOpType(inputOperandType, 4, inputDimensions);
3705 ANeuralNetworksOperandType input2 = input1;
3706 ANeuralNetworksOperandType output = {.type = ANEURALNETWORKS_TENSOR_BOOL8,
3707 .dimensionCount = 4,
3708 .dimensions = inputDimensions,
3709 .scale = 0.0f,
3710 .zeroPoint = 0};
3711 OperationTestBase test(operationCode, {input1, input2}, {output});
3712 test.testOpsValidations();
3713 }
3714
TEST(OperationValidationTest,LESS)3715 TEST(OperationValidationTest, LESS) {
3716 comparisonTest(ANEURALNETWORKS_LESS, ANEURALNETWORKS_TENSOR_BOOL8);
3717 comparisonTest(ANEURALNETWORKS_LESS, ANEURALNETWORKS_TENSOR_FLOAT16);
3718 comparisonTest(ANEURALNETWORKS_LESS, ANEURALNETWORKS_TENSOR_FLOAT32);
3719 comparisonTest(ANEURALNETWORKS_LESS, ANEURALNETWORKS_TENSOR_INT32);
3720 comparisonTest(ANEURALNETWORKS_LESS, ANEURALNETWORKS_TENSOR_QUANT8_ASYMM);
3721 comparisonTest(ANEURALNETWORKS_LESS, ANEURALNETWORKS_TENSOR_QUANT8_ASYMM_SIGNED);
3722 }
3723
TEST(OperationValidationTest,LESS_EQUAL)3724 TEST(OperationValidationTest, LESS_EQUAL) {
3725 comparisonTest(ANEURALNETWORKS_LESS_EQUAL, ANEURALNETWORKS_TENSOR_BOOL8);
3726 comparisonTest(ANEURALNETWORKS_LESS_EQUAL, ANEURALNETWORKS_TENSOR_FLOAT16);
3727 comparisonTest(ANEURALNETWORKS_LESS_EQUAL, ANEURALNETWORKS_TENSOR_FLOAT32);
3728 comparisonTest(ANEURALNETWORKS_LESS_EQUAL, ANEURALNETWORKS_TENSOR_INT32);
3729 comparisonTest(ANEURALNETWORKS_LESS_EQUAL, ANEURALNETWORKS_TENSOR_QUANT8_ASYMM);
3730 comparisonTest(ANEURALNETWORKS_LESS_EQUAL, ANEURALNETWORKS_TENSOR_QUANT8_ASYMM_SIGNED);
3731 }
3732
TEST(OperationValidationTest,EQUAL)3733 TEST(OperationValidationTest, EQUAL) {
3734 comparisonTest(ANEURALNETWORKS_EQUAL, ANEURALNETWORKS_TENSOR_BOOL8);
3735 comparisonTest(ANEURALNETWORKS_EQUAL, ANEURALNETWORKS_TENSOR_FLOAT16);
3736 comparisonTest(ANEURALNETWORKS_EQUAL, ANEURALNETWORKS_TENSOR_FLOAT32);
3737 comparisonTest(ANEURALNETWORKS_EQUAL, ANEURALNETWORKS_TENSOR_INT32);
3738 comparisonTest(ANEURALNETWORKS_EQUAL, ANEURALNETWORKS_TENSOR_QUANT8_ASYMM);
3739 comparisonTest(ANEURALNETWORKS_EQUAL, ANEURALNETWORKS_TENSOR_QUANT8_ASYMM_SIGNED);
3740 }
3741
TEST(OperationValidationTest,NOT_EQUAL)3742 TEST(OperationValidationTest, NOT_EQUAL) {
3743 comparisonTest(ANEURALNETWORKS_NOT_EQUAL, ANEURALNETWORKS_TENSOR_BOOL8);
3744 comparisonTest(ANEURALNETWORKS_NOT_EQUAL, ANEURALNETWORKS_TENSOR_FLOAT16);
3745 comparisonTest(ANEURALNETWORKS_NOT_EQUAL, ANEURALNETWORKS_TENSOR_FLOAT32);
3746 comparisonTest(ANEURALNETWORKS_NOT_EQUAL, ANEURALNETWORKS_TENSOR_INT32);
3747 comparisonTest(ANEURALNETWORKS_NOT_EQUAL, ANEURALNETWORKS_TENSOR_QUANT8_ASYMM);
3748 comparisonTest(ANEURALNETWORKS_NOT_EQUAL, ANEURALNETWORKS_TENSOR_QUANT8_ASYMM_SIGNED);
3749 }
3750
TEST(OperationValidationTest,GREATER)3751 TEST(OperationValidationTest, GREATER) {
3752 comparisonTest(ANEURALNETWORKS_GREATER, ANEURALNETWORKS_TENSOR_BOOL8);
3753 comparisonTest(ANEURALNETWORKS_GREATER, ANEURALNETWORKS_TENSOR_FLOAT16);
3754 comparisonTest(ANEURALNETWORKS_GREATER, ANEURALNETWORKS_TENSOR_FLOAT32);
3755 comparisonTest(ANEURALNETWORKS_GREATER, ANEURALNETWORKS_TENSOR_INT32);
3756 comparisonTest(ANEURALNETWORKS_GREATER, ANEURALNETWORKS_TENSOR_QUANT8_ASYMM);
3757 comparisonTest(ANEURALNETWORKS_GREATER, ANEURALNETWORKS_TENSOR_QUANT8_ASYMM_SIGNED);
3758 }
3759
TEST(OperationValidationTest,GREATER_EQUAL)3760 TEST(OperationValidationTest, GREATER_EQUAL) {
3761 comparisonTest(ANEURALNETWORKS_GREATER_EQUAL, ANEURALNETWORKS_TENSOR_BOOL8);
3762 comparisonTest(ANEURALNETWORKS_GREATER_EQUAL, ANEURALNETWORKS_TENSOR_FLOAT16);
3763 comparisonTest(ANEURALNETWORKS_GREATER_EQUAL, ANEURALNETWORKS_TENSOR_FLOAT32);
3764 comparisonTest(ANEURALNETWORKS_GREATER_EQUAL, ANEURALNETWORKS_TENSOR_INT32);
3765 comparisonTest(ANEURALNETWORKS_GREATER_EQUAL, ANEURALNETWORKS_TENSOR_QUANT8_ASYMM);
3766 comparisonTest(ANEURALNETWORKS_GREATER_EQUAL, ANEURALNETWORKS_TENSOR_QUANT8_ASYMM_SIGNED);
3767 }
3768
reduceOpTest(ANeuralNetworksOperationType operationCode,int32_t inputOperandType)3769 void reduceOpTest(ANeuralNetworksOperationType operationCode, int32_t inputOperandType) {
3770 uint32_t inputDimensions[4] = {2, 2, 2, 2};
3771 ANeuralNetworksOperandType input1 = getOpType(inputOperandType, 4, inputDimensions);
3772 uint32_t axesDimensions[1] = {2};
3773 ANeuralNetworksOperandType input2 = getOpType(ANEURALNETWORKS_TENSOR_INT32, 1, axesDimensions);
3774 ANeuralNetworksOperandType input3 = getOpType(ANEURALNETWORKS_BOOL, 0);
3775 ANeuralNetworksOperandType output = getOpType(inputOperandType, 4, inputDimensions);
3776 OperationTestBase test(operationCode, {input1, input2, input3}, {output},
3777 {{TensorRankConstraint::UpTo(4)}});
3778 test.testOpsValidations();
3779 }
3780
TEST(OperationValidationTest,REDUCE_PROD)3781 TEST(OperationValidationTest, REDUCE_PROD) {
3782 reduceOpTest(ANEURALNETWORKS_REDUCE_PROD, ANEURALNETWORKS_TENSOR_FLOAT16);
3783 reduceOpTest(ANEURALNETWORKS_REDUCE_PROD, ANEURALNETWORKS_TENSOR_FLOAT32);
3784 }
3785
TEST(OperationValidationTest,REDUCE_SUM)3786 TEST(OperationValidationTest, REDUCE_SUM) {
3787 reduceOpTest(ANEURALNETWORKS_REDUCE_SUM, ANEURALNETWORKS_TENSOR_FLOAT16);
3788 reduceOpTest(ANEURALNETWORKS_REDUCE_SUM, ANEURALNETWORKS_TENSOR_FLOAT32);
3789 }
3790
TEST(OperationValidationTest,REDUCE_MAX)3791 TEST(OperationValidationTest, REDUCE_MAX) {
3792 reduceOpTest(ANEURALNETWORKS_REDUCE_MAX, ANEURALNETWORKS_TENSOR_FLOAT16);
3793 reduceOpTest(ANEURALNETWORKS_REDUCE_MAX, ANEURALNETWORKS_TENSOR_FLOAT32);
3794 reduceOpTest(ANEURALNETWORKS_REDUCE_MAX, ANEURALNETWORKS_TENSOR_QUANT8_ASYMM);
3795 reduceOpTest(ANEURALNETWORKS_REDUCE_MAX, ANEURALNETWORKS_TENSOR_QUANT8_ASYMM_SIGNED);
3796 }
3797
TEST(OperationValidationTest,REDUCE_MIN)3798 TEST(OperationValidationTest, REDUCE_MIN) {
3799 reduceOpTest(ANEURALNETWORKS_REDUCE_MIN, ANEURALNETWORKS_TENSOR_FLOAT16);
3800 reduceOpTest(ANEURALNETWORKS_REDUCE_MIN, ANEURALNETWORKS_TENSOR_FLOAT32);
3801 reduceOpTest(ANEURALNETWORKS_REDUCE_MIN, ANEURALNETWORKS_TENSOR_QUANT8_ASYMM);
3802 reduceOpTest(ANEURALNETWORKS_REDUCE_MIN, ANEURALNETWORKS_TENSOR_QUANT8_ASYMM_SIGNED);
3803 }
3804
TEST(OperationValidationTest,REDUCE_ANY)3805 TEST(OperationValidationTest, REDUCE_ANY) {
3806 reduceOpTest(ANEURALNETWORKS_REDUCE_ANY, ANEURALNETWORKS_TENSOR_BOOL8);
3807 }
3808
TEST(OperationValidationTest,REDUCE_ALL)3809 TEST(OperationValidationTest, REDUCE_ALL) {
3810 reduceOpTest(ANEURALNETWORKS_REDUCE_ALL, ANEURALNETWORKS_TENSOR_BOOL8);
3811 }
3812
selectTest(ANeuralNetworksOperationType operationCode,int32_t inputOperandType)3813 void selectTest(ANeuralNetworksOperationType operationCode, int32_t inputOperandType) {
3814 uint32_t inputDimensions[4] = {2, 2, 2, 2};
3815 ANeuralNetworksOperandType input0 = getOpType(ANEURALNETWORKS_TENSOR_BOOL8, 4, inputDimensions);
3816 ANeuralNetworksOperandType input1 = getOpType(inputOperandType, 4, inputDimensions);
3817 ANeuralNetworksOperandType input2 = input1;
3818 ANeuralNetworksOperandType output = input1;
3819
3820 OperationTestBase test(operationCode, {input0, input1, input2}, {output});
3821 test.testOpsValidations();
3822 }
3823
TEST(OperationValidationTest,SELECT)3824 TEST(OperationValidationTest, SELECT) {
3825 selectTest(ANEURALNETWORKS_SELECT, ANEURALNETWORKS_TENSOR_FLOAT16);
3826 selectTest(ANEURALNETWORKS_SELECT, ANEURALNETWORKS_TENSOR_FLOAT32);
3827 selectTest(ANEURALNETWORKS_SELECT, ANEURALNETWORKS_TENSOR_INT32);
3828 selectTest(ANEURALNETWORKS_SELECT, ANEURALNETWORKS_TENSOR_QUANT8_ASYMM);
3829 selectTest(ANEURALNETWORKS_SELECT, ANEURALNETWORKS_TENSOR_QUANT8_ASYMM_SIGNED);
3830 }
3831
powTest(int32_t inputOperandType)3832 void powTest(int32_t inputOperandType) {
3833 const uint32_t inputDimensions[] = {3, 3};
3834 ANeuralNetworksOperandType inputType = {.type = inputOperandType,
3835 .dimensionCount = 2,
3836 .dimensions = inputDimensions,
3837 .scale = 0.0f,
3838 .zeroPoint = 0};
3839
3840 OperationTestBase test(ANEURALNETWORKS_POW, {inputType, inputType}, {inputType});
3841 test.testOpsValidations();
3842 }
3843
TEST(OperationValidationTest,POW)3844 TEST(OperationValidationTest, POW) {
3845 powTest(ANEURALNETWORKS_TENSOR_FLOAT16);
3846 powTest(ANEURALNETWORKS_TENSOR_FLOAT32);
3847 }
3848
boxWithNmsLimitOpTest(int32_t scoreOperandCode,int32_t roiOperandCode,int32_t scalarOperandCode)3849 void boxWithNmsLimitOpTest(int32_t scoreOperandCode, int32_t roiOperandCode,
3850 int32_t scalarOperandCode) {
3851 uint32_t scoreDim[] = {19, 3}, roiDim[] = {19, 12}, splitDim[] = {2};
3852 uint32_t outScoreDim[] = {12}, outRoiDim[] = {12, 4}, outClassDim[] = {12}, outSplitDim[] = {2};
3853 OperationTestBase boxWithNmsLimitTest(
3854 ANEURALNETWORKS_BOX_WITH_NMS_LIMIT,
3855 {getOpType(scoreOperandCode, 2, scoreDim), getOpType(roiOperandCode, 2, roiDim),
3856 getOpType(ANEURALNETWORKS_TENSOR_INT32, 1, splitDim), getOpType(scalarOperandCode),
3857 getOpType(ANEURALNETWORKS_INT32), getOpType(ANEURALNETWORKS_INT32),
3858 getOpType(scalarOperandCode), getOpType(scalarOperandCode),
3859 getOpType(scalarOperandCode)},
3860 {getOpType(scoreOperandCode, 1, outScoreDim), getOpType(roiOperandCode, 2, outRoiDim),
3861 getOpType(ANEURALNETWORKS_TENSOR_INT32, 1, outClassDim),
3862 getOpType(ANEURALNETWORKS_TENSOR_INT32, 1, outSplitDim)});
3863 boxWithNmsLimitTest.testOpsValidations();
3864 }
3865
TEST(OperationValidationTest,BOX_WITH_NMS_LIMIT_float16)3866 TEST(OperationValidationTest, BOX_WITH_NMS_LIMIT_float16) {
3867 boxWithNmsLimitOpTest(ANEURALNETWORKS_TENSOR_FLOAT16, ANEURALNETWORKS_TENSOR_FLOAT16,
3868 ANEURALNETWORKS_FLOAT16);
3869 }
3870
TEST(OperationValidationTest,BOX_WITH_NMS_LIMIT_float32)3871 TEST(OperationValidationTest, BOX_WITH_NMS_LIMIT_float32) {
3872 boxWithNmsLimitOpTest(ANEURALNETWORKS_TENSOR_FLOAT32, ANEURALNETWORKS_TENSOR_FLOAT32,
3873 ANEURALNETWORKS_FLOAT32);
3874 }
3875
TEST(OperationValidationTest,BOX_WITH_NMS_LIMIT_quant)3876 TEST(OperationValidationTest, BOX_WITH_NMS_LIMIT_quant) {
3877 boxWithNmsLimitOpTest(ANEURALNETWORKS_TENSOR_QUANT8_ASYMM, ANEURALNETWORKS_TENSOR_QUANT16_ASYMM,
3878 ANEURALNETWORKS_FLOAT32);
3879 }
3880
TEST(OperationValidationTest,BOX_WITH_NMS_LIMIT_quant_signed)3881 TEST(OperationValidationTest, BOX_WITH_NMS_LIMIT_quant_signed) {
3882 boxWithNmsLimitOpTest(ANEURALNETWORKS_TENSOR_QUANT8_ASYMM_SIGNED,
3883 ANEURALNETWORKS_TENSOR_QUANT16_ASYMM, ANEURALNETWORKS_FLOAT32);
3884 }
3885
castOpTest(int32_t inputOperandCode,int32_t outputOperandCode)3886 void castOpTest(int32_t inputOperandCode, int32_t outputOperandCode) {
3887 SCOPED_TRACE(testing::Message()
3888 << "inputType: " << inputOperandCode << ", outputType: " << outputOperandCode);
3889 uint32_t inputDimensions[3] = {2, 2, 2};
3890 ANeuralNetworksOperandType input = getOpType(inputOperandCode, 3, inputDimensions);
3891 ANeuralNetworksOperandType output = getOpType(outputOperandCode, 3, inputDimensions);
3892 OperationTestBase test(ANEURALNETWORKS_CAST, {input}, {output});
3893 test.testOpsValidations();
3894 }
3895
TEST(OperationValidationTest,CAST)3896 TEST(OperationValidationTest, CAST) {
3897 std::vector<int32_t> inputTypes = {ANEURALNETWORKS_TENSOR_FLOAT16,
3898 ANEURALNETWORKS_TENSOR_FLOAT32, ANEURALNETWORKS_TENSOR_INT32,
3899 ANEURALNETWORKS_TENSOR_QUANT8_ASYMM};
3900 std::vector<int32_t> outputTypes = inputTypes;
3901 for (auto inputType : inputTypes) {
3902 for (auto outputType : outputTypes) {
3903 castOpTest(inputType, outputType);
3904 }
3905 }
3906 }
3907
TEST(OperationValidationTest,CAST_identity)3908 TEST(OperationValidationTest, CAST_identity) {
3909 std::vector<int32_t> inputTypes = {
3910 ANEURALNETWORKS_TENSOR_FLOAT32,
3911 ANEURALNETWORKS_TENSOR_INT32,
3912 ANEURALNETWORKS_TENSOR_QUANT8_ASYMM,
3913 ANEURALNETWORKS_TENSOR_QUANT16_SYMM,
3914 ANEURALNETWORKS_TENSOR_FLOAT16,
3915 ANEURALNETWORKS_TENSOR_BOOL8,
3916 ANEURALNETWORKS_TENSOR_QUANT16_ASYMM,
3917 ANEURALNETWORKS_TENSOR_QUANT8_SYMM,
3918 ANEURALNETWORKS_TENSOR_QUANT8_ASYMM_SIGNED,
3919 };
3920 for (auto inputType : inputTypes) {
3921 castOpTest(inputType, inputType);
3922 }
3923 }
3924
bidirectionlSequenceRNNTest(int32_t inputOperandCode)3925 void bidirectionlSequenceRNNTest(int32_t inputOperandCode) {
3926 const uint32_t batchSize = 2;
3927 const uint32_t maxTime = 3;
3928 const uint32_t inputSize = 4;
3929 const uint32_t numUnits = 5;
3930
3931 uint32_t inputDims[3] = {maxTime, batchSize, inputSize};
3932 uint32_t weightsDims[2] = {inputSize, numUnits};
3933 uint32_t recurrentWeightsDims[2] = {numUnits, numUnits};
3934 uint32_t biasDims[1] = {numUnits};
3935 uint32_t hiddenStateDims[2] = {batchSize, numUnits};
3936 uint32_t outputDims[2] = {batchSize, numUnits};
3937
3938 ANeuralNetworksOperandType input = {.type = inputOperandCode,
3939 .dimensionCount = 3,
3940 .dimensions = inputDims,
3941 .scale = 0.0f,
3942 .zeroPoint = 0};
3943 ANeuralNetworksOperandType fwWeights = {.type = inputOperandCode,
3944 .dimensionCount = 2,
3945 .dimensions = weightsDims,
3946 .scale = 0.0f,
3947 .zeroPoint = 0};
3948 ANeuralNetworksOperandType bwWeights = fwWeights;
3949 ANeuralNetworksOperandType fwRecurrentWeights = {.type = inputOperandCode,
3950 .dimensionCount = 2,
3951 .dimensions = recurrentWeightsDims,
3952 .scale = 0.0f,
3953 .zeroPoint = 0};
3954 ANeuralNetworksOperandType bwRecurrentWeights = fwRecurrentWeights;
3955 ANeuralNetworksOperandType fwBias = {.type = inputOperandCode,
3956 .dimensionCount = 1,
3957 .dimensions = biasDims,
3958 .scale = 0.0f,
3959 .zeroPoint = 0};
3960 ANeuralNetworksOperandType bwBias = fwBias;
3961 ANeuralNetworksOperandType fwHiddenState = {.type = inputOperandCode,
3962 .dimensionCount = 2,
3963 .dimensions = hiddenStateDims,
3964 .scale = 0.0f,
3965 .zeroPoint = 0};
3966 ANeuralNetworksOperandType bwHiddenState = fwHiddenState;
3967 ANeuralNetworksOperandType output = {.type = inputOperandCode,
3968 .dimensionCount = 2,
3969 .dimensions = outputDims,
3970 .scale = 0.0f,
3971 .zeroPoint = 0};
3972 ANeuralNetworksOperandType activation = {.type = ANEURALNETWORKS_INT32,
3973 .dimensionCount = 0,
3974 .dimensions = nullptr,
3975 .scale = 0.0f,
3976 .zeroPoint = 0};
3977 ANeuralNetworksOperandType boolScalar = {.type = ANEURALNETWORKS_BOOL,
3978 .dimensionCount = 0,
3979 .dimensions = nullptr,
3980 .scale = 0.0f,
3981 .zeroPoint = 0};
3982 ANeuralNetworksOperandType timeMajor = boolScalar;
3983 ANeuralNetworksOperandType mergeOutputs = boolScalar;
3984
3985 OperationTestBase rnnTest(ANEURALNETWORKS_BIDIRECTIONAL_SEQUENCE_RNN,
3986 {input, fwWeights, fwRecurrentWeights, fwBias, fwHiddenState,
3987 bwWeights, bwRecurrentWeights, bwBias, bwHiddenState, input,
3988 fwWeights, bwWeights, activation, timeMajor, mergeOutputs},
3989 {output, output});
3990 rnnTest.testOpsValidations();
3991 }
3992
TEST(OperationValidationTest,BIDIRECTIONAL_SEQUENCE_RNN_float32)3993 TEST(OperationValidationTest, BIDIRECTIONAL_SEQUENCE_RNN_float32) {
3994 bidirectionlSequenceRNNTest(ANEURALNETWORKS_TENSOR_FLOAT32);
3995 }
3996
TEST(OperationValidationTest,BIDIRECTIONAL_SEQUENCE_RNN_float16)3997 TEST(OperationValidationTest, BIDIRECTIONAL_SEQUENCE_RNN_float16) {
3998 bidirectionlSequenceRNNTest(ANEURALNETWORKS_TENSOR_FLOAT16);
3999 }
4000
unidirectionlSequenceRNNTest(int32_t inputOperandCode)4001 void unidirectionlSequenceRNNTest(int32_t inputOperandCode) {
4002 const uint32_t batchSize = 2;
4003 const uint32_t maxTime = 3;
4004 const uint32_t inputSize = 4;
4005 const uint32_t numUnits = 5;
4006
4007 uint32_t inputDims[3] = {maxTime, batchSize, inputSize};
4008 uint32_t weightsDims[2] = {inputSize, numUnits};
4009 uint32_t recurrentWeightsDims[2] = {numUnits, numUnits};
4010 uint32_t biasDims[1] = {numUnits};
4011 uint32_t hiddenStateDims[2] = {batchSize, numUnits};
4012 uint32_t outputDims[2] = {batchSize, numUnits};
4013
4014 ANeuralNetworksOperandType input = {.type = inputOperandCode,
4015 .dimensionCount = 3,
4016 .dimensions = inputDims,
4017 .scale = 0.0f,
4018 .zeroPoint = 0};
4019 ANeuralNetworksOperandType weights = {.type = inputOperandCode,
4020 .dimensionCount = 2,
4021 .dimensions = weightsDims,
4022 .scale = 0.0f,
4023 .zeroPoint = 0};
4024 ANeuralNetworksOperandType recurrentWeights = {.type = inputOperandCode,
4025 .dimensionCount = 2,
4026 .dimensions = recurrentWeightsDims,
4027 .scale = 0.0f,
4028 .zeroPoint = 0};
4029 ANeuralNetworksOperandType bias = {.type = inputOperandCode,
4030 .dimensionCount = 1,
4031 .dimensions = biasDims,
4032 .scale = 0.0f,
4033 .zeroPoint = 0};
4034 ANeuralNetworksOperandType hiddenState = {.type = inputOperandCode,
4035 .dimensionCount = 2,
4036 .dimensions = hiddenStateDims,
4037 .scale = 0.0f,
4038 .zeroPoint = 0};
4039 ANeuralNetworksOperandType output = {.type = inputOperandCode,
4040 .dimensionCount = 2,
4041 .dimensions = outputDims,
4042 .scale = 0.0f,
4043 .zeroPoint = 0};
4044 ANeuralNetworksOperandType intScalar = {.type = ANEURALNETWORKS_INT32,
4045 .dimensionCount = 0,
4046 .dimensions = nullptr,
4047 .scale = 0.0f,
4048 .zeroPoint = 0};
4049 ANeuralNetworksOperandType activation = intScalar;
4050 ANeuralNetworksOperandType timeMajor = intScalar;
4051
4052 OperationTestBase rnnTest(
4053 ANEURALNETWORKS_UNIDIRECTIONAL_SEQUENCE_RNN,
4054 {input, weights, recurrentWeights, bias, hiddenState, activation, timeMajor}, {output});
4055 rnnTest.testOpsValidations();
4056 }
4057
TEST(OperationValidationTest,UNIDIRECTIONAL_SEQUENCE_RNN_float32)4058 TEST(OperationValidationTest, UNIDIRECTIONAL_SEQUENCE_RNN_float32) {
4059 unidirectionlSequenceRNNTest(ANEURALNETWORKS_TENSOR_FLOAT32);
4060 }
4061
TEST(OperationValidationTest,UNIDIRECTIONAL_SEQUENCE_RNN_float16)4062 TEST(OperationValidationTest, UNIDIRECTIONAL_SEQUENCE_RNN_float16) {
4063 unidirectionlSequenceRNNTest(ANEURALNETWORKS_TENSOR_FLOAT16);
4064 }
4065
unidirectionalSequenceLSTMTest(int32_t inputOperandCode)4066 void unidirectionalSequenceLSTMTest(int32_t inputOperandCode) {
4067 const uint32_t maxTime = 2;
4068 const uint32_t batchSize = 3;
4069 const uint32_t numUnits = 4;
4070 const uint32_t inputSize = 5;
4071 const uint32_t outputSize = 6;
4072
4073 uint32_t inputDims[3] = {maxTime, batchSize, inputSize};
4074 uint32_t inputWeightsDims[2] = {numUnits, inputSize};
4075 uint32_t recurrentWeightsDims[2] = {numUnits, outputSize};
4076 uint32_t diagonalDims[1] = {numUnits};
4077 uint32_t projectionDims[2] = {outputSize, numUnits};
4078 uint32_t projectionBiasDims[1] = {outputSize};
4079 uint32_t outputStateDims[2] = {batchSize, outputSize};
4080 uint32_t cellStateDims[2] = {batchSize, numUnits};
4081
4082 uint32_t outputDims[3] = {maxTime, batchSize, outputSize};
4083
4084 ANeuralNetworksOperandType input = {.type = inputOperandCode,
4085 .dimensionCount = 3,
4086 .dimensions = inputDims,
4087 .scale = 0.0f,
4088 .zeroPoint = 0};
4089 ANeuralNetworksOperandType inputToInputWeights = {.type = inputOperandCode,
4090 .dimensionCount = 2,
4091 .dimensions = inputWeightsDims,
4092 .scale = 0.0f,
4093 .zeroPoint = 0};
4094 ANeuralNetworksOperandType inputToForgetWeights = inputToInputWeights;
4095 ANeuralNetworksOperandType inputToCellWeights = inputToInputWeights;
4096 ANeuralNetworksOperandType inputToOutputWeights = inputToInputWeights;
4097 ANeuralNetworksOperandType recurrentToInputWeights = {.type = inputOperandCode,
4098 .dimensionCount = 2,
4099 .dimensions = recurrentWeightsDims,
4100 .scale = 0.0f,
4101 .zeroPoint = 0};
4102 ANeuralNetworksOperandType recurrentToForgetWeights = recurrentToInputWeights;
4103 ANeuralNetworksOperandType recurrentToCellWeights = recurrentToInputWeights;
4104 ANeuralNetworksOperandType recurrentToOutputWeights = recurrentToInputWeights;
4105 ANeuralNetworksOperandType cellToInputWeights = {.type = inputOperandCode,
4106 .dimensionCount = 1,
4107 .dimensions = diagonalDims,
4108 .scale = 0.0f,
4109 .zeroPoint = 0};
4110 ANeuralNetworksOperandType cellToForgetWeights = cellToInputWeights;
4111 ANeuralNetworksOperandType cellToOutputWeights = cellToInputWeights;
4112 ANeuralNetworksOperandType inputGateBias = {.type = inputOperandCode,
4113 .dimensionCount = 1,
4114 .dimensions = diagonalDims,
4115 .scale = 0.0f,
4116 .zeroPoint = 0};
4117 ANeuralNetworksOperandType forgetGateBias = inputGateBias;
4118 ANeuralNetworksOperandType cellGateBias = inputGateBias;
4119 ANeuralNetworksOperandType outputGateBias = inputGateBias;
4120 ANeuralNetworksOperandType projectionWeights = {.type = inputOperandCode,
4121 .dimensionCount = 2,
4122 .dimensions = projectionDims,
4123 .scale = 0.0f,
4124 .zeroPoint = 0};
4125 ANeuralNetworksOperandType projectionBias = {.type = inputOperandCode,
4126 .dimensionCount = 1,
4127 .dimensions = projectionBiasDims,
4128 .scale = 0.0f,
4129 .zeroPoint = 0};
4130 ANeuralNetworksOperandType outputStateIn = {.type = inputOperandCode,
4131 .dimensionCount = 2,
4132 .dimensions = outputStateDims,
4133 .scale = 0.0f,
4134 .zeroPoint = 0};
4135 ANeuralNetworksOperandType cellStateIn = {.type = inputOperandCode,
4136 .dimensionCount = 2,
4137 .dimensions = cellStateDims,
4138 .scale = 0.0f,
4139 .zeroPoint = 0};
4140 ANeuralNetworksOperandType intScalar = {
4141 .type = ANEURALNETWORKS_INT32,
4142 .dimensionCount = 0,
4143 .dimensions = nullptr,
4144 .scale = 0.0f,
4145 .zeroPoint = 0,
4146 };
4147 ANeuralNetworksOperandType activation = intScalar;
4148 ANeuralNetworksOperandType floatScalar = {
4149 .type = inputOperandCode == ANEURALNETWORKS_TENSOR_FLOAT32 ? ANEURALNETWORKS_FLOAT32
4150 : ANEURALNETWORKS_FLOAT16,
4151 .dimensionCount = 0,
4152 .dimensions = nullptr,
4153 .scale = 0.0f,
4154 .zeroPoint = 0,
4155 };
4156 ANeuralNetworksOperandType cellClip = floatScalar;
4157 ANeuralNetworksOperandType projClip = floatScalar;
4158 ANeuralNetworksOperandType boolScalar = {
4159 .type = ANEURALNETWORKS_BOOL,
4160 .dimensionCount = 0,
4161 .dimensions = nullptr,
4162 .scale = 0.0f,
4163 .zeroPoint = 0,
4164 };
4165 ANeuralNetworksOperandType timeMajor = boolScalar;
4166 ANeuralNetworksOperandType inputLayerNormWeights = {.type = inputOperandCode,
4167 .dimensionCount = 1,
4168 .dimensions = diagonalDims,
4169 .scale = 0.0f,
4170 .zeroPoint = 0};
4171 ANeuralNetworksOperandType forgetLayerNormWeights = inputLayerNormWeights;
4172 ANeuralNetworksOperandType cellLayerNormWeights = inputLayerNormWeights;
4173 ANeuralNetworksOperandType outputLayerNormWeights = inputLayerNormWeights;
4174
4175 ANeuralNetworksOperandType output = {.type = inputOperandCode,
4176 .dimensionCount = 3,
4177 .dimensions = outputDims,
4178 .scale = 0.0f,
4179 .zeroPoint = 0};
4180
4181 OperationTestBase ulstmTest(ANEURALNETWORKS_UNIDIRECTIONAL_SEQUENCE_LSTM,
4182 {input,
4183 inputToInputWeights,
4184 inputToForgetWeights,
4185 inputToCellWeights,
4186 inputToOutputWeights,
4187 recurrentToInputWeights,
4188 recurrentToForgetWeights,
4189 recurrentToCellWeights,
4190 recurrentToOutputWeights,
4191 cellToInputWeights,
4192 cellToForgetWeights,
4193 cellToOutputWeights,
4194 inputGateBias,
4195 forgetGateBias,
4196 cellGateBias,
4197 outputGateBias,
4198 projectionWeights,
4199 projectionBias,
4200 outputStateIn,
4201 cellStateIn,
4202 activation,
4203 cellClip,
4204 projClip,
4205 timeMajor,
4206 inputLayerNormWeights,
4207 forgetLayerNormWeights,
4208 cellLayerNormWeights,
4209 outputLayerNormWeights},
4210 {output});
4211 ulstmTest.testOpsValidations();
4212 }
4213
TEST(OperationValidationTest,UNIDIRECTIONAL_SEQUENCE_LSTM_float32)4214 TEST(OperationValidationTest, UNIDIRECTIONAL_SEQUENCE_LSTM_float32) {
4215 unidirectionalSequenceLSTMTest(ANEURALNETWORKS_TENSOR_FLOAT32);
4216 }
4217
TEST(OperationValidationTest,UNIDIRECTIONAL_SEQUENCE_LSTM_float16)4218 TEST(OperationValidationTest, UNIDIRECTIONAL_SEQUENCE_LSTM_float16) {
4219 unidirectionalSequenceLSTMTest(ANEURALNETWORKS_TENSOR_FLOAT16);
4220 }
4221
generateProposalsOpTest(int32_t scoreOperandCode,int32_t deltaOperandCode,int32_t anchorOperandCode,int32_t roiOperandCode,int32_t scalarOperandCode)4222 void generateProposalsOpTest(int32_t scoreOperandCode, int32_t deltaOperandCode,
4223 int32_t anchorOperandCode, int32_t roiOperandCode,
4224 int32_t scalarOperandCode) {
4225 uint32_t scoreDim[] = {1, 2, 2, 2}, deltaDim[] = {1, 2, 2, 8}, anchorDim[] = {2, 4},
4226 imageInfoDim[] = {1, 2};
4227 uint32_t outScoreDim[] = {4}, outRoiDim[] = {4, 4}, outSplitDim[] = {1};
4228 OperationTestBase generateProposalsTest(
4229 ANEURALNETWORKS_GENERATE_PROPOSALS,
4230 {getOpType(scoreOperandCode, 4, scoreDim), getOpType(deltaOperandCode, 4, deltaDim),
4231 getOpType(anchorOperandCode, 2, anchorDim), getOpType(roiOperandCode, 2, imageInfoDim),
4232 getOpType(scalarOperandCode), getOpType(scalarOperandCode),
4233 getOpType(ANEURALNETWORKS_INT32), getOpType(ANEURALNETWORKS_INT32),
4234 getOpType(scalarOperandCode), getOpType(scalarOperandCode),
4235 getOpType(ANEURALNETWORKS_BOOL)},
4236 {getOpType(scoreOperandCode, 1, outScoreDim), getOpType(roiOperandCode, 2, outRoiDim),
4237 getOpType(ANEURALNETWORKS_TENSOR_INT32, 1, outSplitDim)});
4238 generateProposalsTest.testOpsValidations();
4239 }
4240
TEST(OperationValidationTest,GENERATE_PROPOSALS_float16)4241 TEST(OperationValidationTest, GENERATE_PROPOSALS_float16) {
4242 generateProposalsOpTest(ANEURALNETWORKS_TENSOR_FLOAT16, ANEURALNETWORKS_TENSOR_FLOAT16,
4243 ANEURALNETWORKS_TENSOR_FLOAT16, ANEURALNETWORKS_TENSOR_FLOAT16,
4244 ANEURALNETWORKS_FLOAT16);
4245 }
4246
TEST(OperationValidationTest,GENERATE_PROPOSALS_float32)4247 TEST(OperationValidationTest, GENERATE_PROPOSALS_float32) {
4248 generateProposalsOpTest(ANEURALNETWORKS_TENSOR_FLOAT32, ANEURALNETWORKS_TENSOR_FLOAT32,
4249 ANEURALNETWORKS_TENSOR_FLOAT32, ANEURALNETWORKS_TENSOR_FLOAT32,
4250 ANEURALNETWORKS_FLOAT32);
4251 }
4252
TEST(OperationValidationTest,GENERATE_PROPOSALS_quant)4253 TEST(OperationValidationTest, GENERATE_PROPOSALS_quant) {
4254 generateProposalsOpTest(ANEURALNETWORKS_TENSOR_QUANT8_ASYMM,
4255 ANEURALNETWORKS_TENSOR_QUANT8_ASYMM,
4256 ANEURALNETWORKS_TENSOR_QUANT16_SYMM,
4257 ANEURALNETWORKS_TENSOR_QUANT16_ASYMM, ANEURALNETWORKS_FLOAT32);
4258 }
4259
TEST(OperationValidationTest,GENERATE_PROPOSALS_quant_signed)4260 TEST(OperationValidationTest, GENERATE_PROPOSALS_quant_signed) {
4261 generateProposalsOpTest(ANEURALNETWORKS_TENSOR_QUANT8_ASYMM_SIGNED,
4262 ANEURALNETWORKS_TENSOR_QUANT8_ASYMM_SIGNED,
4263 ANEURALNETWORKS_TENSOR_QUANT16_SYMM,
4264 ANEURALNETWORKS_TENSOR_QUANT16_ASYMM, ANEURALNETWORKS_FLOAT32);
4265 }
4266
resizeNearestNeighborTest(int32_t inputCode,int32_t scalarCode)4267 void resizeNearestNeighborTest(int32_t inputCode, int32_t scalarCode) {
4268 uint32_t inputDim[] = {1, 2, 2, 1}, outputDim[] = {1, 1, 1, 1};
4269 OperationTestBase resizeImageOpTest(ANEURALNETWORKS_RESIZE_NEAREST_NEIGHBOR,
4270 {getOpType(inputCode, 4, inputDim), getOpType(scalarCode),
4271 getOpType(scalarCode), getOpType(ANEURALNETWORKS_BOOL)},
4272 {getOpType(inputCode, 4, outputDim)});
4273 resizeImageOpTest.testOpsValidations();
4274 }
4275
TEST(OperationValidationTest,RESIZE_NEAREST_NEIGHBOR)4276 TEST(OperationValidationTest, RESIZE_NEAREST_NEIGHBOR) {
4277 resizeNearestNeighborTest(ANEURALNETWORKS_TENSOR_FLOAT32, ANEURALNETWORKS_INT32);
4278 resizeNearestNeighborTest(ANEURALNETWORKS_TENSOR_FLOAT32, ANEURALNETWORKS_FLOAT32);
4279 }
4280
TEST(OperationValidationTest,RESIZE_NEAREST_NEIGHBOR_float16)4281 TEST(OperationValidationTest, RESIZE_NEAREST_NEIGHBOR_float16) {
4282 resizeNearestNeighborTest(ANEURALNETWORKS_TENSOR_FLOAT16, ANEURALNETWORKS_INT32);
4283 resizeNearestNeighborTest(ANEURALNETWORKS_TENSOR_FLOAT16, ANEURALNETWORKS_FLOAT16);
4284 }
4285
TEST(OperationValidationTest,RESIZE_NEAREST_NEIGHBOR_quant8)4286 TEST(OperationValidationTest, RESIZE_NEAREST_NEIGHBOR_quant8) {
4287 resizeNearestNeighborTest(ANEURALNETWORKS_TENSOR_QUANT8_ASYMM, ANEURALNETWORKS_INT32);
4288 resizeNearestNeighborTest(ANEURALNETWORKS_TENSOR_QUANT8_ASYMM, ANEURALNETWORKS_FLOAT32);
4289 }
4290
TEST(OperationValidationTest,RESIZE_NEAREST_NEIGHBOR_quant8_signed)4291 TEST(OperationValidationTest, RESIZE_NEAREST_NEIGHBOR_quant8_signed) {
4292 resizeNearestNeighborTest(ANEURALNETWORKS_TENSOR_QUANT8_ASYMM_SIGNED, ANEURALNETWORKS_INT32);
4293 resizeNearestNeighborTest(ANEURALNETWORKS_TENSOR_QUANT8_ASYMM_SIGNED, ANEURALNETWORKS_FLOAT32);
4294 }
4295
TEST(OperationValidationTest,QUANTIZED_LSTM)4296 TEST(OperationValidationTest, QUANTIZED_LSTM) {
4297 uint32_t oneDimensional[1] = {5};
4298 uint32_t twoDimensional[2] = {5, 5};
4299
4300 ANeuralNetworksOperandType quant8AsymSignedTensor2D = {
4301 .type = ANEURALNETWORKS_TENSOR_QUANT8_ASYMM_SIGNED,
4302 .dimensionCount = 2,
4303 .dimensions = twoDimensional,
4304 .scale = 0.0078125,
4305 .zeroPoint = 0,
4306 };
4307 ANeuralNetworksOperandType quant8SymTensor2D = {
4308 .type = ANEURALNETWORKS_TENSOR_QUANT8_SYMM,
4309 .dimensionCount = 2,
4310 .dimensions = twoDimensional,
4311 .scale = 0.0078125,
4312 .zeroPoint = 0,
4313 };
4314 ANeuralNetworksOperandType quant16SymTensor1D = {
4315 .type = ANEURALNETWORKS_TENSOR_QUANT16_SYMM,
4316 .dimensionCount = 1,
4317 .dimensions = oneDimensional,
4318 .scale = 1.0,
4319 .zeroPoint = 0,
4320 };
4321 ANeuralNetworksOperandType quant16SymTensor2D = {
4322 .type = ANEURALNETWORKS_TENSOR_QUANT16_SYMM,
4323 .dimensionCount = 2,
4324 .dimensions = twoDimensional,
4325 .scale = 1.0,
4326 .zeroPoint = 0,
4327 };
4328 ANeuralNetworksOperandType int32Tensor1D = {
4329 .type = ANEURALNETWORKS_TENSOR_INT32,
4330 .dimensionCount = 1,
4331 .dimensions = oneDimensional,
4332 .scale = 4.65661e-08,
4333 .zeroPoint = 0,
4334 };
4335 ANeuralNetworksOperandType int32Scalar = {
4336 .type = ANEURALNETWORKS_INT32,
4337 };
4338 ANeuralNetworksOperandType float32Scalar = {
4339 .type = ANEURALNETWORKS_FLOAT32,
4340 };
4341
4342 ANeuralNetworksOperandType input = quant8AsymSignedTensor2D;
4343 ANeuralNetworksOperandType input_to_input_weights = quant8SymTensor2D;
4344 ANeuralNetworksOperandType input_to_forget_weights = quant8SymTensor2D;
4345 ANeuralNetworksOperandType input_to_cell_weights = quant8SymTensor2D;
4346 ANeuralNetworksOperandType input_to_output_weights = quant8SymTensor2D;
4347 ANeuralNetworksOperandType recurrent_to_input_weights = quant8SymTensor2D;
4348 ANeuralNetworksOperandType recurrent_to_forget_weights = quant8SymTensor2D;
4349 ANeuralNetworksOperandType recurrent_to_cell_weights = quant8SymTensor2D;
4350 ANeuralNetworksOperandType recurrent_to_output_weights = quant8SymTensor2D;
4351 ANeuralNetworksOperandType cell_to_input_weights = quant16SymTensor2D;
4352 ANeuralNetworksOperandType cell_to_forget_weights = quant16SymTensor2D;
4353 ANeuralNetworksOperandType cell_to_output_weights = quant16SymTensor2D;
4354 ANeuralNetworksOperandType input_gate_bias = int32Tensor1D;
4355 ANeuralNetworksOperandType forget_gate_bias = int32Tensor1D;
4356 ANeuralNetworksOperandType cell_gate_bias = int32Tensor1D;
4357 ANeuralNetworksOperandType output_gate_bias = int32Tensor1D;
4358 ANeuralNetworksOperandType projection_weights = quant8SymTensor2D;
4359 ANeuralNetworksOperandType projection_bias = int32Tensor1D;
4360 ANeuralNetworksOperandType output_state_in = quant8AsymSignedTensor2D;
4361 ANeuralNetworksOperandType cell_state_in = quant16SymTensor2D;
4362 ANeuralNetworksOperandType input_layer_norm_weights = quant16SymTensor1D;
4363 ANeuralNetworksOperandType forget_layer_norm_weights = quant16SymTensor1D;
4364 ANeuralNetworksOperandType cell_layer_norm_weights = quant16SymTensor1D;
4365 ANeuralNetworksOperandType output_layer_norm_weights = quant16SymTensor1D;
4366 ANeuralNetworksOperandType cell_clip = float32Scalar;
4367 ANeuralNetworksOperandType projection_clip = float32Scalar;
4368 ANeuralNetworksOperandType input_intermediate_scale = float32Scalar;
4369 ANeuralNetworksOperandType forget_intermediate_scale = float32Scalar;
4370 ANeuralNetworksOperandType cell_intermediate_scale = float32Scalar;
4371 ANeuralNetworksOperandType output_intermediate_scale = float32Scalar;
4372 ANeuralNetworksOperandType hidden_state_zero_point = int32Scalar;
4373 ANeuralNetworksOperandType hidden_state_scale = float32Scalar;
4374
4375 ANeuralNetworksOperandType output_state_out = quant8AsymSignedTensor2D;
4376 ANeuralNetworksOperandType cell_state_out = quant16SymTensor2D;
4377 ANeuralNetworksOperandType output = quant8AsymSignedTensor2D;
4378
4379 OperationTestBase test(ANEURALNETWORKS_QUANTIZED_LSTM,
4380 {input,
4381 input_to_input_weights,
4382 input_to_forget_weights,
4383 input_to_cell_weights,
4384 input_to_output_weights,
4385 recurrent_to_input_weights,
4386 recurrent_to_forget_weights,
4387 recurrent_to_cell_weights,
4388 recurrent_to_output_weights,
4389 cell_to_input_weights,
4390 cell_to_forget_weights,
4391 cell_to_output_weights,
4392 input_gate_bias,
4393 forget_gate_bias,
4394 cell_gate_bias,
4395 output_gate_bias,
4396 projection_weights,
4397 projection_bias,
4398 output_state_in,
4399 cell_state_in,
4400 input_layer_norm_weights,
4401 forget_layer_norm_weights,
4402 cell_layer_norm_weights,
4403 output_layer_norm_weights,
4404 cell_clip,
4405 projection_clip,
4406 input_intermediate_scale,
4407 forget_intermediate_scale,
4408 cell_intermediate_scale,
4409 output_intermediate_scale,
4410 hidden_state_zero_point,
4411 hidden_state_scale},
4412 {output_state_out, cell_state_out, output});
4413 test.testOpsValidations();
4414 }
4415
fillTest(int32_t valueOperandType,int32_t outputOperandType)4416 void fillTest(int32_t valueOperandType, int32_t outputOperandType) {
4417 uint32_t inputDimensions[1] = {3};
4418 ANeuralNetworksOperandType input0 = getOpType(ANEURALNETWORKS_TENSOR_INT32, 1, inputDimensions);
4419 ANeuralNetworksOperandType input1 = getOpType(valueOperandType);
4420 uint32_t outputDimensions[3] = {3, 4, 5};
4421 ANeuralNetworksOperandType output = getOpType(outputOperandType, 3, outputDimensions);
4422 OperationTestBase test(ANEURALNETWORKS_FILL, {input0, input1}, {output});
4423 test.testOpsValidations();
4424 }
4425
TEST(OperationValidationTest,FILL_float16)4426 TEST(OperationValidationTest, FILL_float16) {
4427 fillTest(ANEURALNETWORKS_FLOAT16, ANEURALNETWORKS_TENSOR_FLOAT16);
4428 }
4429
TEST(OperationValidationTest,FILL_float32)4430 TEST(OperationValidationTest, FILL_float32) {
4431 fillTest(ANEURALNETWORKS_FLOAT32, ANEURALNETWORKS_TENSOR_FLOAT32);
4432 }
4433
TEST(OperationValidationTest,FILL_int32)4434 TEST(OperationValidationTest, FILL_int32) {
4435 fillTest(ANEURALNETWORKS_INT32, ANEURALNETWORKS_TENSOR_INT32);
4436 }
4437
rankTest(int32_t inputOperandType)4438 void rankTest(int32_t inputOperandType) {
4439 uint32_t inputDimensions[3] = {3, 4, 5};
4440 ANeuralNetworksOperandType input = getOpType(inputOperandType, 3, inputDimensions);
4441 ANeuralNetworksOperandType output = getOpType(ANEURALNETWORKS_INT32);
4442 OperationTestBase test(ANEURALNETWORKS_RANK, {input}, {output});
4443 test.testOpsValidations();
4444 }
4445
TEST(OperationValidationTest,RANK_float16)4446 TEST(OperationValidationTest, RANK_float16) {
4447 rankTest(ANEURALNETWORKS_TENSOR_FLOAT16);
4448 }
4449
TEST(OperationValidationTest,RANK_float32)4450 TEST(OperationValidationTest, RANK_float32) {
4451 rankTest(ANEURALNETWORKS_TENSOR_FLOAT32);
4452 }
4453
TEST(OperationValidationTest,RANK_int32)4454 TEST(OperationValidationTest, RANK_int32) {
4455 rankTest(ANEURALNETWORKS_TENSOR_INT32);
4456 }
4457
TEST(OperationValidationTest,RANK_quant8)4458 TEST(OperationValidationTest, RANK_quant8) {
4459 rankTest(ANEURALNETWORKS_TENSOR_QUANT8_ASYMM);
4460 }
4461
TEST(OperationValidationTest,RANK_quant8_signed)4462 TEST(OperationValidationTest, RANK_quant8_signed) {
4463 rankTest(ANEURALNETWORKS_TENSOR_QUANT8_ASYMM_SIGNED);
4464 }
4465
makeIdentityModel(const ANeuralNetworksOperandType * type)4466 ANeuralNetworksModel* makeIdentityModel(const ANeuralNetworksOperandType* type) {
4467 ANeuralNetworksModel* model = nullptr;
4468 EXPECT_EQ(ANeuralNetworksModel_create(&model), ANEURALNETWORKS_NO_ERROR);
4469 EXPECT_EQ(ANeuralNetworksModel_addOperand(model, type), ANEURALNETWORKS_NO_ERROR);
4470 EXPECT_EQ(ANeuralNetworksModel_addOperand(model, type), ANEURALNETWORKS_NO_ERROR);
4471 uint32_t inputs[] = {0};
4472 uint32_t outputs[] = {1};
4473 EXPECT_EQ(ANeuralNetworksModel_addOperation(model, ANEURALNETWORKS_CAST, std::size(inputs),
4474 inputs, std::size(outputs), outputs),
4475 ANEURALNETWORKS_NO_ERROR);
4476 EXPECT_EQ(ANeuralNetworksModel_identifyInputsAndOutputs(model, std::size(inputs), inputs,
4477 std::size(outputs), outputs),
4478 ANEURALNETWORKS_NO_ERROR);
4479 EXPECT_EQ(ANeuralNetworksModel_finish(model), ANEURALNETWORKS_NO_ERROR);
4480 return model;
4481 }
4482
testIf(const std::vector<uint32_t> & outerDims,const ANeuralNetworksModel * thenModel,const ANeuralNetworksModel * elseModel,bool testMutations)4483 void testIf(const std::vector<uint32_t>& outerDims, const ANeuralNetworksModel* thenModel,
4484 const ANeuralNetworksModel* elseModel, bool testMutations) {
4485 const uint32_t kThenOperand = 1;
4486 const uint32_t kElseOperand = 2;
4487 const uint32_t boolDims[] = {1};
4488 ANeuralNetworksOperandType boolType =
4489 getOpType(ANEURALNETWORKS_TENSOR_BOOL8, std::size(boolDims), boolDims);
4490 ANeuralNetworksOperandType dataType =
4491 getOpType(ANEURALNETWORKS_TENSOR_FLOAT32, outerDims.size(), outerDims.data());
4492 ANeuralNetworksOperandType modelType = getOpType(ANEURALNETWORKS_MODEL);
4493 OperationTestBase test(ANEURALNETWORKS_IF, {boolType, modelType, modelType, dataType},
4494 {dataType});
4495 test.setInputOperandValueFromModel(kThenOperand, thenModel);
4496 test.setInputOperandValueFromModel(kElseOperand, elseModel);
4497 if (testMutations) {
4498 test.testOpsValidations();
4499 } else {
4500 EXPECT_TRUE(test.testSuccess());
4501 }
4502 }
4503
testIf(const std::vector<uint32_t> & outerDims,const std::vector<uint32_t> & thenDims,const std::vector<uint32_t> & elseDims,bool testMutations)4504 void testIf(const std::vector<uint32_t>& outerDims, const std::vector<uint32_t>& thenDims,
4505 const std::vector<uint32_t>& elseDims, bool testMutations) {
4506 ANeuralNetworksOperandType thenDataType =
4507 getOpType(ANEURALNETWORKS_TENSOR_FLOAT32, thenDims.size(), thenDims.data());
4508 ANeuralNetworksOperandType elseDataType =
4509 getOpType(ANEURALNETWORKS_TENSOR_FLOAT32, elseDims.size(), elseDims.data());
4510 ANeuralNetworksModel* thenModel = makeIdentityModel(&thenDataType);
4511 ANeuralNetworksModel* elseModel = makeIdentityModel(&elseDataType);
4512 testIf(outerDims, thenModel, elseModel, testMutations);
4513 ANeuralNetworksModel_free(thenModel);
4514 ANeuralNetworksModel_free(elseModel);
4515 }
4516
TEST(OperationValidationTest,IF)4517 TEST(OperationValidationTest, IF) {
4518 const std::vector<std::pair<std::string, std::vector<uint32_t>>> configurations = {
4519 {"fully specified", {1, 2, 3}},
4520 {"unknown dimensions", {0, 2, 0}},
4521 {"unknown rank", {}},
4522 };
4523 // We skip mutation testing for all but the first configuration to avoid the
4524 // exponential runtime blowup. The value of additional operand code and
4525 // count mutations is negligible because whether the shapes are fully
4526 // specified should have nothing to do with the operand code or count.
4527 bool testMutations = true;
4528 for (const auto& [outerTrace, outerDims] : configurations) {
4529 SCOPED_TRACE(testing::Message() << "outerDims: " << outerTrace);
4530 for (const auto& [thenTrace, thenDims] : configurations) {
4531 SCOPED_TRACE(testing::Message() << "thenDims: " << thenTrace);
4532 for (const auto& [elseTrace, elseDims] : configurations) {
4533 SCOPED_TRACE(testing::Message() << "elseDims: " << elseTrace);
4534 testIf(outerDims, thenDims, elseDims, testMutations);
4535 testMutations = false;
4536 }
4537 }
4538 }
4539 }
4540
4541 // operand 0 --> +------+
4542 // | LESS | --> operand 2
4543 // operand 1 --> +------+
4544 //
makeWhileCondModel(const ANeuralNetworksOperandType * dataType,const ANeuralNetworksOperandType * boolType)4545 ANeuralNetworksModel* makeWhileCondModel(const ANeuralNetworksOperandType* dataType,
4546 const ANeuralNetworksOperandType* boolType) {
4547 ANeuralNetworksModel* model = nullptr;
4548 EXPECT_EQ(ANeuralNetworksModel_create(&model), ANEURALNETWORKS_NO_ERROR);
4549 EXPECT_EQ(ANeuralNetworksModel_addOperand(model, dataType), ANEURALNETWORKS_NO_ERROR);
4550 EXPECT_EQ(ANeuralNetworksModel_addOperand(model, dataType), ANEURALNETWORKS_NO_ERROR);
4551 EXPECT_EQ(ANeuralNetworksModel_addOperand(model, boolType), ANEURALNETWORKS_NO_ERROR);
4552 const uint32_t inputs[] = {0, 1};
4553 const uint32_t outputs[] = {2};
4554 EXPECT_EQ(ANeuralNetworksModel_addOperation(model, ANEURALNETWORKS_LESS, std::size(inputs),
4555 inputs, std::size(outputs), outputs),
4556 ANEURALNETWORKS_NO_ERROR);
4557 EXPECT_EQ(ANeuralNetworksModel_identifyInputsAndOutputs(model, std::size(inputs), inputs,
4558 std::size(outputs), outputs),
4559 ANEURALNETWORKS_NO_ERROR);
4560 EXPECT_EQ(ANeuralNetworksModel_finish(model), ANEURALNETWORKS_NO_ERROR);
4561 return model;
4562 }
4563
4564 // +------+
4565 // operand 0 --> | CAST | --> operand 2
4566 // +------+
4567 //
4568 // operand 1 --> (unused)
4569 //
makeWhileBodyModel(const ANeuralNetworksOperandType * type)4570 ANeuralNetworksModel* makeWhileBodyModel(const ANeuralNetworksOperandType* type) {
4571 ANeuralNetworksModel* model = nullptr;
4572 EXPECT_EQ(ANeuralNetworksModel_create(&model), ANEURALNETWORKS_NO_ERROR);
4573 EXPECT_EQ(ANeuralNetworksModel_addOperand(model, type), ANEURALNETWORKS_NO_ERROR);
4574 EXPECT_EQ(ANeuralNetworksModel_addOperand(model, type), ANEURALNETWORKS_NO_ERROR);
4575 EXPECT_EQ(ANeuralNetworksModel_addOperand(model, type), ANEURALNETWORKS_NO_ERROR);
4576 const uint32_t castInputs[] = {0};
4577 const uint32_t castOutputs[] = {2};
4578 EXPECT_EQ(ANeuralNetworksModel_addOperation(model, ANEURALNETWORKS_CAST, std::size(castInputs),
4579 castInputs, std::size(castOutputs), castOutputs),
4580 ANEURALNETWORKS_NO_ERROR);
4581 const uint32_t modelInputs[] = {0, 1};
4582 const uint32_t modelOutputs[] = {2};
4583 EXPECT_EQ(ANeuralNetworksModel_identifyInputsAndOutputs(model, std::size(modelInputs),
4584 modelInputs, std::size(modelOutputs),
4585 modelOutputs),
4586 ANEURALNETWORKS_NO_ERROR);
4587 EXPECT_EQ(ANeuralNetworksModel_finish(model), ANEURALNETWORKS_NO_ERROR);
4588 return model;
4589 }
4590
testWhile(const std::vector<uint32_t> & outerDims,const ANeuralNetworksModel * condModel,const ANeuralNetworksModel * bodyModel,bool testMutations)4591 void testWhile(const std::vector<uint32_t>& outerDims, const ANeuralNetworksModel* condModel,
4592 const ANeuralNetworksModel* bodyModel, bool testMutations) {
4593 const uint32_t kCondOperand = 0;
4594 const uint32_t kBodyOperand = 1;
4595 ANeuralNetworksOperandType modelType = getOpType(ANEURALNETWORKS_MODEL);
4596 ANeuralNetworksOperandType dataType =
4597 getOpType(ANEURALNETWORKS_TENSOR_FLOAT32, outerDims.size(), outerDims.data());
4598 OperationTestBase test(ANEURALNETWORKS_WHILE, {modelType, modelType, dataType, dataType},
4599 {dataType});
4600 test.setInputOperandValueFromModel(kCondOperand, condModel);
4601 test.setInputOperandValueFromModel(kBodyOperand, bodyModel);
4602 if (testMutations) {
4603 test.testOpsValidations();
4604 } else {
4605 EXPECT_TRUE(test.testSuccess());
4606 }
4607 }
4608
testWhile(const std::vector<uint32_t> & outerDims,const std::vector<uint32_t> & condDims,const std::vector<uint32_t> & bodyDims,bool testMutations)4609 void testWhile(const std::vector<uint32_t>& outerDims, const std::vector<uint32_t>& condDims,
4610 const std::vector<uint32_t>& bodyDims, bool testMutations) {
4611 const uint32_t boolDims[] = {1};
4612 ANeuralNetworksOperandType boolType =
4613 getOpType(ANEURALNETWORKS_TENSOR_BOOL8, std::size(boolDims), boolDims);
4614 ANeuralNetworksOperandType condDataType =
4615 getOpType(ANEURALNETWORKS_TENSOR_FLOAT32, condDims.size(), condDims.data());
4616 ANeuralNetworksOperandType bodyDataType =
4617 getOpType(ANEURALNETWORKS_TENSOR_FLOAT32, bodyDims.size(), bodyDims.data());
4618 ANeuralNetworksModel* condModel = makeWhileCondModel(&condDataType, &boolType);
4619 ANeuralNetworksModel* bodyModel = makeWhileBodyModel(&bodyDataType);
4620 testWhile(outerDims, condModel, bodyModel, testMutations);
4621 ANeuralNetworksModel_free(condModel);
4622 ANeuralNetworksModel_free(bodyModel);
4623 }
4624
TEST(OperationValidationTest,WHILE)4625 TEST(OperationValidationTest, WHILE) {
4626 const std::vector<std::pair<std::string, std::vector<uint32_t>>> configurations = {
4627 {"fully specified", {1, 2, 3}},
4628 {"unknown dimensions", {0, 2, 0}},
4629 {"unknown rank", {}},
4630 };
4631 // We skip mutation testing for all but the first configuration to avoid the
4632 // exponential runtime blowup. The value of additional operand code and
4633 // count mutations is negligible because whether the shapes are fully
4634 // specified should have nothing to do with the operand code or count.
4635 bool testMutations = true;
4636 for (const auto& [outerTrace, outerDims] : configurations) {
4637 SCOPED_TRACE(testing::Message() << "outerDims: " << outerTrace);
4638 for (const auto& [condTrace, condDims] : configurations) {
4639 SCOPED_TRACE(testing::Message() << "condDims: " << condTrace);
4640 for (const auto& [bodyTrace, bodyDims] : configurations) {
4641 SCOPED_TRACE(testing::Message() << "bodyDims: " << bodyTrace);
4642 testWhile(outerDims, condDims, bodyDims, testMutations);
4643 testMutations = false;
4644 }
4645 }
4646 }
4647 }
4648
4649 } // end namespace
4650