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 "NeuralNetworksWrapper.h" 18#include "NeuralNetworksOEM.h" 19 20#include <gtest/gtest.h> 21 22using namespace android::nn::wrapper; 23 24namespace { 25 26static const int32_t kAvailableOperandCodes[] = { 27 ANEURALNETWORKS_FLOAT32, 28 ANEURALNETWORKS_INT32, 29 ANEURALNETWORKS_UINT32, 30 ANEURALNETWORKS_TENSOR_FLOAT32, 31 ANEURALNETWORKS_TENSOR_INT32, 32 ANEURALNETWORKS_TENSOR_QUANT8_ASYMM, 33 ANEURALNETWORKS_TENSOR_OEM_BYTE 34}; 35 36class OperationTestBase { 37public: 38 OperationTestBase(ANeuralNetworksOperationType opCode, 39 std::vector<ANeuralNetworksOperandType> validInputs, 40 std::vector<ANeuralNetworksOperandType> validOutputs) 41 : mOpCode(opCode), 42 mValidInputs(std::move(validInputs)), 43 mValidOutputs(std::move(validOutputs)) {} 44 45 // Add each operand separately and add the operation using these operands. 46 // This function does not cover the cases that a operand used mutiple times. 47 int32_t addOperation(const std::vector<ANeuralNetworksOperandType>& inputs, 48 const std::vector<ANeuralNetworksOperandType>& outputs) { 49 ANeuralNetworksModel* model = nullptr; 50 ANeuralNetworksModel_create(&model); 51 52 uint32_t opIdx = 0; 53 std::vector<uint32_t> inputIds; 54 std::vector<uint32_t> outputIds; 55 for (uint32_t i = 0; i < inputs.size(); i++) { 56 ANeuralNetworksModel_addOperand(model, &inputs[i]); 57 inputIds.push_back(opIdx++); 58 } 59 for (uint32_t i = 0; i < outputs.size(); i++) { 60 ANeuralNetworksModel_addOperand(model, &outputs[i]); 61 outputIds.push_back(opIdx++); 62 } 63 64 int32_t result = ANeuralNetworksModel_addOperation(model, mOpCode, 65 static_cast<uint32_t>(inputIds.size()), 66 inputIds.data(), 67 static_cast<uint32_t>(outputIds.size()), 68 outputIds.data()); 69 ANeuralNetworksModel_free(model); 70 return result; 71 } 72 73 bool testMutatingInputOperandCode() { 74 for (uint32_t i = 0; i < mValidInputs.size(); i++) { 75 // LSH_PROJECTION's second argument is allowed to have any type. 76 // This is the only operation that currently has a type that can be 77 // anything independent from any other type. Changing the operand 78 // type to any other type will result in a valid model for 79 // LSH_PROJECTION. If this is the case, skip the test. 80 if (mOpCode == ANEURALNETWORKS_LSH_PROJECTION && i == 1) { 81 continue; 82 } 83 ANeuralNetworksOperandType newType = mValidInputs[i]; 84 int32_t originalOperandCode = mValidInputs[i].type; 85 for (int32_t newOperandCode : kAvailableOperandCodes) { 86 if (newOperandCode == originalOperandCode) { 87 continue; 88 } 89 newType.type = newOperandCode; 90 std::vector<ANeuralNetworksOperandType> inputs = mValidInputs; 91 inputs[i] = newType; 92 int32_t result = addOperation(inputs, mValidOutputs); 93 if (ANEURALNETWORKS_NO_ERROR == result) { 94 return false; 95 } 96 } 97 } 98 return true; 99 } 100 101 bool testMutatingOutputOperandCode() { 102 for (uint32_t i = 0; i < mValidOutputs.size(); i++) { 103 // LSH_PROJECTION's second argument is allowed to have any type. 104 // This is the only operation that currently has a type that can be 105 // anything independent from any other type. Changing the operand 106 // type to any other type will result in a valid model for 107 // LSH_PROJECTION. If this is the case, skip the test. 108 if (mOpCode == ANEURALNETWORKS_LSH_PROJECTION && i == 1) { 109 continue; 110 } 111 ANeuralNetworksOperandType newType = mValidOutputs[i]; 112 int32_t originalOperandCode = mValidOutputs[i].type; 113 for (int32_t newOperandCode : kAvailableOperandCodes) { 114 if (newOperandCode == originalOperandCode) { 115 continue; 116 } 117 newType.type = newOperandCode; 118 std::vector<ANeuralNetworksOperandType> outputs = mValidOutputs; 119 outputs[i] = newType; 120 int32_t result = addOperation(mValidInputs, outputs); 121 if (ANEURALNETWORKS_NO_ERROR == result) { 122 return false; 123 } 124 } 125 } 126 return true; 127 } 128 129 bool testMutatingInputOperandCounts() { 130 std::vector<ANeuralNetworksOperandType> inputs = mValidInputs; 131 for (uint32_t i = 0; i < 5; i++) { 132 inputs.push_back(inputs[0]); 133 if (ANEURALNETWORKS_NO_ERROR == addOperation(inputs, mValidOutputs)) { 134 return false; 135 } 136 } 137 return true; 138 } 139 140 bool testMutatingOutputOperandCounts() { 141 std::vector<ANeuralNetworksOperandType> outputs = mValidOutputs; 142 for (int i = 0; i < 5; i++) { 143 outputs.push_back(outputs[0]); 144 if (ANEURALNETWORKS_NO_ERROR == addOperation(mValidInputs, outputs)) { 145 return false; 146 } 147 } 148 return true; 149 } 150 151private: 152 ANeuralNetworksOperationType mOpCode; 153 // The dimensions in the ANeuralNetworksOperandType must outlive the test object. 154 std::vector<ANeuralNetworksOperandType> mValidInputs; 155 std::vector<ANeuralNetworksOperandType> mValidOutputs; 156}; 157 158TEST(OperationValidationTest, DEQUANTIZE_float32) { 159 uint32_t inputDimensions[4] = {2, 2, 2, 2}; 160 ANeuralNetworksOperandType input = {.type = ANEURALNETWORKS_TENSOR_QUANT8_ASYMM, 161 .dimensionCount = 4, 162 .dimensions = inputDimensions, 163 .scale = 1.0f, 164 .zeroPoint = 0}; 165 ANeuralNetworksOperandType output = {.type = ANEURALNETWORKS_TENSOR_FLOAT32, 166 .dimensionCount = 4, 167 .dimensions = inputDimensions, 168 .scale = 0.0f, 169 .zeroPoint = 0}; 170 OperationTestBase dequantizeTest(ANEURALNETWORKS_DEQUANTIZE, {input}, {output}); 171 172 EXPECT_TRUE(dequantizeTest.testMutatingInputOperandCode()); 173 EXPECT_TRUE(dequantizeTest.testMutatingInputOperandCounts()); 174 EXPECT_TRUE(dequantizeTest.testMutatingOutputOperandCode()); 175 EXPECT_TRUE(dequantizeTest.testMutatingOutputOperandCounts()); 176} 177 178void simpleMathOpTest(ANeuralNetworksOperationType operationCode, int32_t operandCode) { 179 uint32_t inputDimensions[4] = {2, 2, 2, 2}; 180 ANeuralNetworksOperandType input1 = {.type = operandCode, 181 .dimensionCount = 4, 182 .dimensions = inputDimensions, 183 .scale = 0.0f, 184 .zeroPoint = 0}; 185 if (operandCode == ANEURALNETWORKS_TENSOR_QUANT8_ASYMM) { 186 input1.scale = 0.5f; 187 } 188 189 ANeuralNetworksOperandType input2 = input1; 190 ANeuralNetworksOperandType output = input1; 191 ANeuralNetworksOperandType activation = {.type = ANEURALNETWORKS_INT32, 192 .dimensionCount = 0, 193 .dimensions = nullptr, 194 .scale = 0.0f, 195 .zeroPoint = 0}; 196 197 OperationTestBase simpleMathTest(operationCode, {input1, input2, activation}, {output}); 198 199 EXPECT_TRUE(simpleMathTest.testMutatingInputOperandCode()); 200 EXPECT_TRUE(simpleMathTest.testMutatingInputOperandCounts()); 201 EXPECT_TRUE(simpleMathTest.testMutatingOutputOperandCode()); 202 EXPECT_TRUE(simpleMathTest.testMutatingOutputOperandCounts()); 203} 204 205TEST(OperationValidationTest, ADD_float32) { 206 simpleMathOpTest(ANEURALNETWORKS_ADD, ANEURALNETWORKS_TENSOR_FLOAT32); 207} 208 209TEST(OperationValidationTest, MUL_float32) { 210 simpleMathOpTest(ANEURALNETWORKS_MUL, ANEURALNETWORKS_TENSOR_FLOAT32); 211} 212 213TEST(OperationValidationTest, SUB_float32) { 214 simpleMathOpTest(ANEURALNETWORKS_SUB, ANEURALNETWORKS_TENSOR_FLOAT32); 215} 216 217TEST(OperationValidationTest, DIV_float32) { 218 simpleMathOpTest(ANEURALNETWORKS_DIV, ANEURALNETWORKS_TENSOR_FLOAT32); 219} 220 221TEST(OperationValidationTest, ADD_quant8) { 222 simpleMathOpTest(ANEURALNETWORKS_ADD, ANEURALNETWORKS_TENSOR_QUANT8_ASYMM); 223} 224 225TEST(OperationValidationTest, MUL_quant8) { 226 simpleMathOpTest(ANEURALNETWORKS_MUL, ANEURALNETWORKS_TENSOR_QUANT8_ASYMM); 227} 228 229void activationOpTest(ANeuralNetworksOperationType operationCode, int32_t operandCode) { 230 uint32_t inputDimensions[4] = {2, 2, 2, 2}; 231 ANeuralNetworksOperandType input = {.type = operandCode, 232 .dimensionCount = 4, 233 .dimensions = inputDimensions, 234 .scale = 0.0f, 235 .zeroPoint = 0}; 236 if (operandCode == ANEURALNETWORKS_TENSOR_QUANT8_ASYMM) { 237 input.scale = 1.f / 256; 238 } 239 240 ANeuralNetworksOperandType output = input; 241 OperationTestBase activationTest(operationCode, {input}, {output}); 242 243 EXPECT_TRUE(activationTest.testMutatingInputOperandCode()); 244 EXPECT_TRUE(activationTest.testMutatingInputOperandCounts()); 245 EXPECT_TRUE(activationTest.testMutatingOutputOperandCode()); 246 EXPECT_TRUE(activationTest.testMutatingOutputOperandCounts()); 247} 248 249TEST(OperationValidationTest, L2_NORMALIZATION_float32) { 250 activationOpTest(ANEURALNETWORKS_L2_NORMALIZATION, ANEURALNETWORKS_TENSOR_FLOAT32); 251} 252 253TEST(OperationValidationTest, FLOOR_float32) { 254 activationOpTest(ANEURALNETWORKS_FLOOR, ANEURALNETWORKS_TENSOR_FLOAT32); 255} 256 257TEST(OperationValidationTest, TANH_float32) { 258 activationOpTest(ANEURALNETWORKS_TANH, ANEURALNETWORKS_TENSOR_FLOAT32); 259} 260 261TEST(OperationValidationTest, RELU_float32) { 262 activationOpTest(ANEURALNETWORKS_RELU, ANEURALNETWORKS_TENSOR_FLOAT32); 263} 264 265TEST(OperationValidationTest, RELU1_float32) { 266 activationOpTest(ANEURALNETWORKS_RELU, ANEURALNETWORKS_TENSOR_FLOAT32); 267} 268 269TEST(OperationValidationTest, RELU6_float32) { 270 activationOpTest(ANEURALNETWORKS_RELU, ANEURALNETWORKS_TENSOR_FLOAT32); 271} 272 273TEST(OperationValidationTest, LOGISTIC_float32) { 274 activationOpTest(ANEURALNETWORKS_LOGISTIC, ANEURALNETWORKS_TENSOR_FLOAT32); 275} 276 277TEST(OperationValidationTest, RELU_quant8) { 278 activationOpTest(ANEURALNETWORKS_RELU, ANEURALNETWORKS_TENSOR_QUANT8_ASYMM); 279} 280 281TEST(OperationValidationTest, RELU1_quant8) { 282 activationOpTest(ANEURALNETWORKS_RELU, ANEURALNETWORKS_TENSOR_QUANT8_ASYMM); 283} 284 285TEST(OperationValidationTest, RELU6_quant8) { 286 activationOpTest(ANEURALNETWORKS_RELU, ANEURALNETWORKS_TENSOR_QUANT8_ASYMM); 287} 288 289TEST(OperationValidationTest, LOGISTIC_quant8) { 290 activationOpTest(ANEURALNETWORKS_LOGISTIC, ANEURALNETWORKS_TENSOR_QUANT8_ASYMM); 291} 292 293void softmaxOpTest(int32_t operandCode) { 294 uint32_t inputDimensions[4] = {2, 2, 2, 2}; 295 ANeuralNetworksOperandType input = {.type = operandCode, 296 .dimensionCount = 4, 297 .dimensions = inputDimensions, 298 .scale = 0.0f, 299 .zeroPoint = 0}; 300 if (operandCode == ANEURALNETWORKS_TENSOR_QUANT8_ASYMM) { 301 input.scale = 1.f / 256; 302 } 303 304 ANeuralNetworksOperandType output = input; 305 ANeuralNetworksOperandType beta = {.type = ANEURALNETWORKS_FLOAT32, 306 .dimensionCount = 0, 307 .dimensions = nullptr, 308 .scale = 0.0f, 309 .zeroPoint = 0}; 310 311 OperationTestBase softmaxTest(ANEURALNETWORKS_SOFTMAX, {input, beta}, {output}); 312 313 EXPECT_TRUE(softmaxTest.testMutatingInputOperandCode()); 314 EXPECT_TRUE(softmaxTest.testMutatingInputOperandCounts()); 315 EXPECT_TRUE(softmaxTest.testMutatingOutputOperandCode()); 316 EXPECT_TRUE(softmaxTest.testMutatingOutputOperandCounts()); 317} 318 319TEST(OperationValidationTest, SOFTMAX_float32) { 320 softmaxOpTest(ANEURALNETWORKS_TENSOR_FLOAT32); 321} 322 323TEST(OperationValidationTest, SOFTMAX_quant8) { 324 softmaxOpTest(ANEURALNETWORKS_TENSOR_QUANT8_ASYMM); 325} 326 327void poolingOpTest(ANeuralNetworksOperationType operationCode, int32_t operandCode) { 328 uint32_t inputDimensions[4] = {2, 4, 4, 2}; 329 ANeuralNetworksOperandType input = {.type = operandCode, 330 .dimensionCount = 4, 331 .dimensions = inputDimensions, 332 .scale = 0.0f, 333 .zeroPoint = 0}; 334 if (operandCode == ANEURALNETWORKS_TENSOR_QUANT8_ASYMM) { 335 input.scale = 1.f / 256; 336 } 337 ANeuralNetworksOperandType output = input; 338 339 ANeuralNetworksOperandType scalar = {.type = ANEURALNETWORKS_INT32, 340 .dimensionCount = 0, 341 .dimensions = nullptr, 342 .scale = 0.0f, 343 .zeroPoint = 0}; 344 ANeuralNetworksOperandType padLeft = scalar; 345 ANeuralNetworksOperandType padRight = scalar; 346 ANeuralNetworksOperandType padTop = scalar; 347 ANeuralNetworksOperandType padBottom = scalar; 348 ANeuralNetworksOperandType strideWidth = scalar; 349 ANeuralNetworksOperandType strideHeight = scalar; 350 ANeuralNetworksOperandType filterWidth = scalar; 351 ANeuralNetworksOperandType filterHeight = scalar; 352 ANeuralNetworksOperandType activation = scalar; 353 354 OperationTestBase explicitPoolingTest(operationCode, 355 {input, 356 padLeft, padRight, padTop, padBottom, 357 strideWidth, strideHeight, 358 filterWidth, filterHeight, 359 activation}, 360 {output}); 361 362 EXPECT_TRUE(explicitPoolingTest.testMutatingInputOperandCode()); 363 EXPECT_TRUE(explicitPoolingTest.testMutatingInputOperandCounts()); 364 EXPECT_TRUE(explicitPoolingTest.testMutatingOutputOperandCode()); 365 EXPECT_TRUE(explicitPoolingTest.testMutatingOutputOperandCounts()); 366 367 ANeuralNetworksOperandType padImplicit = scalar; 368 OperationTestBase implicitPoolingTest(operationCode, 369 {input, 370 padImplicit, 371 strideWidth, strideHeight, 372 filterWidth, filterHeight, 373 activation}, 374 {output}); 375 376 EXPECT_TRUE(implicitPoolingTest.testMutatingInputOperandCode()); 377 EXPECT_TRUE(implicitPoolingTest.testMutatingInputOperandCounts()); 378 EXPECT_TRUE(implicitPoolingTest.testMutatingOutputOperandCode()); 379 EXPECT_TRUE(implicitPoolingTest.testMutatingOutputOperandCounts()); 380} 381 382TEST(OperationValidationTest, AVERAGE_POOL_2D_float32) { 383 poolingOpTest(ANEURALNETWORKS_AVERAGE_POOL_2D, ANEURALNETWORKS_TENSOR_FLOAT32); 384} 385 386TEST(OperationValidationTest, MAX_POOL_2D_float32) { 387 poolingOpTest(ANEURALNETWORKS_MAX_POOL_2D, ANEURALNETWORKS_TENSOR_FLOAT32); 388} 389 390TEST(OperationValidationTest, L2_POOL_2D_float32) { 391 poolingOpTest(ANEURALNETWORKS_L2_POOL_2D, ANEURALNETWORKS_TENSOR_FLOAT32); 392} 393 394TEST(OperationValidationTest, AVERAGE_POOL_2D_quant8) { 395 poolingOpTest(ANEURALNETWORKS_AVERAGE_POOL_2D, ANEURALNETWORKS_TENSOR_QUANT8_ASYMM); 396} 397 398TEST(OperationValidationTest, MAX_POOL_2D_quant8) { 399 poolingOpTest(ANEURALNETWORKS_MAX_POOL_2D, ANEURALNETWORKS_TENSOR_QUANT8_ASYMM); 400} 401 402void spaceDepthOpTest(ANeuralNetworksOperationType operationCode, int32_t operandCode) { 403 uint32_t inputDimensions[4] = {2, 2, 2, 2}; 404 ANeuralNetworksOperandType input = {.type = operandCode, 405 .dimensionCount = 4, 406 .dimensions = inputDimensions, 407 .scale = 0.0f, 408 .zeroPoint = 0}; 409 if (operandCode == ANEURALNETWORKS_TENSOR_QUANT8_ASYMM) { 410 input.scale = 1.f / 256; 411 } 412 413 ANeuralNetworksOperandType block_size = {.type = ANEURALNETWORKS_INT32, 414 .dimensionCount = 0, 415 .dimensions = nullptr, 416 .scale = 0.0f, 417 .zeroPoint = 0}; 418 419 ANeuralNetworksOperandType output = input; 420 OperationTestBase spaceDepthTest(operationCode, {input, block_size}, {output}); 421 422 EXPECT_TRUE(spaceDepthTest.testMutatingInputOperandCode()); 423 EXPECT_TRUE(spaceDepthTest.testMutatingInputOperandCounts()); 424 EXPECT_TRUE(spaceDepthTest.testMutatingOutputOperandCode()); 425 EXPECT_TRUE(spaceDepthTest.testMutatingOutputOperandCounts()); 426} 427 428TEST(OperationValidationTest, SPACE_TO_DEPTH_float32) { 429 spaceDepthOpTest(ANEURALNETWORKS_SPACE_TO_DEPTH, ANEURALNETWORKS_TENSOR_FLOAT32); 430} 431 432TEST(OperationValidationTest, DEPTH_TO_SPACE_float32) { 433 spaceDepthOpTest(ANEURALNETWORKS_DEPTH_TO_SPACE, ANEURALNETWORKS_TENSOR_FLOAT32); 434} 435 436TEST(OperationValidationTest, SPACE_TO_DEPTH_quant8) { 437 spaceDepthOpTest(ANEURALNETWORKS_SPACE_TO_DEPTH, ANEURALNETWORKS_TENSOR_QUANT8_ASYMM); 438} 439 440TEST(OperationValidationTest, DEPTH_TO_SPACE_quant8) { 441 spaceDepthOpTest(ANEURALNETWORKS_DEPTH_TO_SPACE, ANEURALNETWORKS_TENSOR_QUANT8_ASYMM); 442} 443 444void spaceBatchOpTest(ANeuralNetworksOperationType operationCode, int32_t operandCode) { 445 uint32_t inputDimensions[4] = {2, 2, 2, 2}; 446 ANeuralNetworksOperandType input = {.type = operandCode, 447 .dimensionCount = 4, 448 .dimensions = inputDimensions, 449 .scale = 0.0f, 450 .zeroPoint = 0}; 451 if (operandCode == ANEURALNETWORKS_TENSOR_QUANT8_ASYMM) { 452 input.scale = 1.f / 256; 453 } 454 455 uint32_t blockDimensions[1] = {2}; 456 ANeuralNetworksOperandType blockShape = {.type = ANEURALNETWORKS_TENSOR_INT32, 457 .dimensionCount = 1, 458 .dimensions = blockDimensions, 459 .scale = 0.0f, 460 .zeroPoint = 0}; 461 462 ANeuralNetworksOperandType padding = blockShape; 463 ANeuralNetworksOperandType output = input; 464 if (operationCode == ANEURALNETWORKS_SPACE_TO_BATCH_ND) { 465 OperationTestBase spaceBatchTest(operationCode, {input, blockShape, padding}, {output}); 466 467 EXPECT_TRUE(spaceBatchTest.testMutatingInputOperandCode()); 468 EXPECT_TRUE(spaceBatchTest.testMutatingInputOperandCounts()); 469 EXPECT_TRUE(spaceBatchTest.testMutatingOutputOperandCode()); 470 EXPECT_TRUE(spaceBatchTest.testMutatingOutputOperandCounts()); 471 } else { 472 OperationTestBase spaceBatchTest(operationCode, {input, blockShape}, {output}); 473 474 EXPECT_TRUE(spaceBatchTest.testMutatingInputOperandCode()); 475 EXPECT_TRUE(spaceBatchTest.testMutatingInputOperandCounts()); 476 EXPECT_TRUE(spaceBatchTest.testMutatingOutputOperandCode()); 477 EXPECT_TRUE(spaceBatchTest.testMutatingOutputOperandCounts()); 478 } 479} 480 481TEST(OperationValidationTest, SPACE_TO_BATCH_ND_float32) { 482 spaceBatchOpTest(ANEURALNETWORKS_SPACE_TO_BATCH_ND, ANEURALNETWORKS_TENSOR_FLOAT32); 483} 484 485TEST(OperationValidationTest, BATCH_TO_SPACE_ND_float32) { 486 spaceBatchOpTest(ANEURALNETWORKS_BATCH_TO_SPACE_ND, ANEURALNETWORKS_TENSOR_FLOAT32); 487} 488 489TEST(OperationValidationTest, SPACE_TO_BATCH_ND_quant8) { 490 spaceBatchOpTest(ANEURALNETWORKS_SPACE_TO_BATCH_ND, ANEURALNETWORKS_TENSOR_QUANT8_ASYMM); 491} 492 493TEST(OperationValidationTest, BATCH_TO_SPACE_ND_quant8) { 494 spaceBatchOpTest(ANEURALNETWORKS_BATCH_TO_SPACE_ND, ANEURALNETWORKS_TENSOR_QUANT8_ASYMM); 495} 496 497void transposeAndSqueezeOpTest(ANeuralNetworksOperationType operationCode, int32_t operandCode) { 498 uint32_t inputDimensions[4] = {2, 2, 2, 2}; 499 ANeuralNetworksOperandType input = {.type = operandCode, 500 .dimensionCount = 4, 501 .dimensions = inputDimensions, 502 .scale = 0.0f, 503 .zeroPoint = 0}; 504 if (operandCode == ANEURALNETWORKS_TENSOR_QUANT8_ASYMM) { 505 input.scale = 1.f / 256; 506 } 507 508 uint32_t blockDimensions[1] = {4}; 509 ANeuralNetworksOperandType dims = {.type = ANEURALNETWORKS_TENSOR_INT32, 510 .dimensionCount = 1, 511 .dimensions = blockDimensions, 512 .scale = 0.0f, 513 .zeroPoint = 0}; 514 515 ANeuralNetworksOperandType output = input; 516 OperationTestBase transposeAndSqueezeTest(operationCode, {input, dims}, {output}); 517 518 EXPECT_TRUE(transposeAndSqueezeTest.testMutatingInputOperandCode()); 519 EXPECT_TRUE(transposeAndSqueezeTest.testMutatingInputOperandCounts()); 520 EXPECT_TRUE(transposeAndSqueezeTest.testMutatingOutputOperandCode()); 521 EXPECT_TRUE(transposeAndSqueezeTest.testMutatingOutputOperandCounts()); 522} 523 524TEST(OperationValidationTest, TRANSPOSE_float32) { 525 transposeAndSqueezeOpTest(ANEURALNETWORKS_TRANSPOSE, ANEURALNETWORKS_TENSOR_FLOAT32); 526} 527 528TEST(OperationValidationTest, SQUEEZE_float32) { 529 transposeAndSqueezeOpTest(ANEURALNETWORKS_SQUEEZE, ANEURALNETWORKS_TENSOR_FLOAT32); 530} 531 532TEST(OperationValidationTest, TRANSPOSE_quant8) { 533 transposeAndSqueezeOpTest(ANEURALNETWORKS_TRANSPOSE, ANEURALNETWORKS_TENSOR_QUANT8_ASYMM); 534} 535 536TEST(OperationValidationTest, SQUEEZE_quant8) { 537 transposeAndSqueezeOpTest(ANEURALNETWORKS_SQUEEZE, ANEURALNETWORKS_TENSOR_QUANT8_ASYMM); 538} 539 540void convOpTest(int32_t operandCode) { 541 uint32_t inputDimensions[4] = {2, 4, 4, 2}; 542 ANeuralNetworksOperandType input = {.type = operandCode, 543 .dimensionCount = 4, 544 .dimensions = inputDimensions, 545 .scale = 0.0f, 546 .zeroPoint = 0}; 547 if (operandCode == ANEURALNETWORKS_TENSOR_QUANT8_ASYMM) { 548 input.scale = 0.5f; 549 } 550 551 ANeuralNetworksOperandType filter = input; 552 ANeuralNetworksOperandType output = input; 553 554 uint32_t biasDimensions[1] = {2}; 555 ANeuralNetworksOperandType bias = {.type = operandCode, 556 .dimensionCount = 1, 557 .dimensions = biasDimensions, 558 .scale = 0.0f, 559 .zeroPoint = 0}; 560 if (operandCode == ANEURALNETWORKS_TENSOR_QUANT8_ASYMM) { 561 bias.type = ANEURALNETWORKS_TENSOR_INT32; 562 bias.scale = 0.25f; 563 } 564 565 ANeuralNetworksOperandType scalar = {.type = ANEURALNETWORKS_INT32, 566 .dimensionCount = 0, 567 .dimensions = nullptr, 568 .scale = 0.0f, 569 .zeroPoint = 0}; 570 ANeuralNetworksOperandType padLeft = scalar; 571 ANeuralNetworksOperandType padRight = scalar; 572 ANeuralNetworksOperandType padTop = scalar; 573 ANeuralNetworksOperandType padBottom = scalar; 574 ANeuralNetworksOperandType strideWidth = scalar; 575 ANeuralNetworksOperandType strideHeight = scalar; 576 ANeuralNetworksOperandType activation = scalar; 577 578 OperationTestBase explicitConvTest(ANEURALNETWORKS_CONV_2D, 579 {input, filter, bias, 580 padLeft, padRight, padTop, padBottom, 581 strideWidth, strideHeight, 582 activation}, 583 {output}); 584 585 EXPECT_TRUE(explicitConvTest.testMutatingInputOperandCode()); 586 EXPECT_TRUE(explicitConvTest.testMutatingInputOperandCounts()); 587 EXPECT_TRUE(explicitConvTest.testMutatingOutputOperandCode()); 588 EXPECT_TRUE(explicitConvTest.testMutatingOutputOperandCounts()); 589 590 ANeuralNetworksOperandType padImplicit = scalar; 591 OperationTestBase implicitConvTest(ANEURALNETWORKS_CONV_2D, 592 {input, filter, bias, 593 padImplicit, 594 strideWidth, strideHeight, 595 activation}, 596 {output}); 597 598 EXPECT_TRUE(implicitConvTest.testMutatingInputOperandCode()); 599 EXPECT_TRUE(implicitConvTest.testMutatingInputOperandCounts()); 600 EXPECT_TRUE(implicitConvTest.testMutatingOutputOperandCode()); 601 EXPECT_TRUE(implicitConvTest.testMutatingOutputOperandCounts()); 602} 603 604TEST(OperationValidationTest, CONV_2D_float32) { 605 convOpTest(ANEURALNETWORKS_TENSOR_FLOAT32); 606} 607 608TEST(OperationValidationTest, CONV_2D_quant8) { 609 convOpTest(ANEURALNETWORKS_TENSOR_QUANT8_ASYMM); 610} 611 612void depthwiseConvOpTest(int32_t operandCode) { 613 uint32_t inputDimensions[4] = {1, 2, 2, 2}; 614 ANeuralNetworksOperandType input = {.type = operandCode, 615 .dimensionCount = 4, 616 .dimensions = inputDimensions, 617 .scale = 0.0f, 618 .zeroPoint = 0}; 619 if (operandCode == ANEURALNETWORKS_TENSOR_QUANT8_ASYMM) { 620 input.scale = 0.5f; 621 } 622 623 ANeuralNetworksOperandType filter = input; 624 ANeuralNetworksOperandType output = input; 625 626 uint32_t biasDimensions[1] = {2}; 627 ANeuralNetworksOperandType bias = {.type = operandCode, 628 .dimensionCount = 1, 629 .dimensions = biasDimensions, 630 .scale = 0.0f, 631 .zeroPoint = 0}; 632 if (operandCode == ANEURALNETWORKS_TENSOR_QUANT8_ASYMM) { 633 bias.type = ANEURALNETWORKS_TENSOR_INT32; 634 bias.scale = 0.25f; 635 } 636 637 ANeuralNetworksOperandType scalar = {.type = ANEURALNETWORKS_INT32, 638 .dimensionCount = 0, 639 .dimensions = nullptr, 640 .scale = 0.0f, 641 .zeroPoint = 0}; 642 ANeuralNetworksOperandType padLeft = scalar; 643 ANeuralNetworksOperandType padRight = scalar; 644 ANeuralNetworksOperandType padTop = scalar; 645 ANeuralNetworksOperandType padBottom = scalar; 646 ANeuralNetworksOperandType strideWidth = scalar; 647 ANeuralNetworksOperandType strideHeight = scalar; 648 ANeuralNetworksOperandType multiplier = scalar; 649 ANeuralNetworksOperandType activation = scalar; 650 651 OperationTestBase explicitDepthwiseConvTest(ANEURALNETWORKS_DEPTHWISE_CONV_2D, 652 {input, filter, bias, 653 padLeft, padRight, padTop, padBottom, 654 strideWidth, strideHeight, 655 multiplier, activation}, 656 {output}); 657 658 EXPECT_TRUE(explicitDepthwiseConvTest.testMutatingInputOperandCode()); 659 EXPECT_TRUE(explicitDepthwiseConvTest.testMutatingInputOperandCounts()); 660 EXPECT_TRUE(explicitDepthwiseConvTest.testMutatingOutputOperandCode()); 661 EXPECT_TRUE(explicitDepthwiseConvTest.testMutatingOutputOperandCounts()); 662 663 ANeuralNetworksOperandType padImplicit = scalar; 664 OperationTestBase implicitDepthwiseConvTest(ANEURALNETWORKS_DEPTHWISE_CONV_2D, 665 {input, filter, bias, 666 padImplicit, 667 strideWidth, strideHeight, 668 multiplier, activation}, 669 {output}); 670 671 EXPECT_TRUE(implicitDepthwiseConvTest.testMutatingInputOperandCode()); 672 EXPECT_TRUE(implicitDepthwiseConvTest.testMutatingInputOperandCounts()); 673 EXPECT_TRUE(implicitDepthwiseConvTest.testMutatingOutputOperandCode()); 674 EXPECT_TRUE(implicitDepthwiseConvTest.testMutatingOutputOperandCounts()); 675} 676 677TEST(OperationValidationTest, DEPTHWISE_CONV_2D_float32) { 678 depthwiseConvOpTest(ANEURALNETWORKS_TENSOR_FLOAT32); 679} 680 681TEST(OperationValidationTest, DEPTHWISE_CONV_2D_quant8) { 682 depthwiseConvOpTest(ANEURALNETWORKS_TENSOR_QUANT8_ASYMM); 683} 684 685void fullyConnectedOpTest(int32_t operandCode) { 686 uint32_t inputDimensions[2] = {5, 5}; 687 ANeuralNetworksOperandType input = {.type = operandCode, 688 .dimensionCount = 2, 689 .dimensions = inputDimensions, 690 .scale = 0.0f, 691 .zeroPoint = 0}; 692 if (operandCode == ANEURALNETWORKS_TENSOR_QUANT8_ASYMM) { 693 input.scale = 0.5f; 694 } 695 696 ANeuralNetworksOperandType weights = input; 697 ANeuralNetworksOperandType output = input; 698 699 uint32_t biasDimensions[1] = {5}; 700 ANeuralNetworksOperandType bias = {.type = operandCode, 701 .dimensionCount = 1, 702 .dimensions = biasDimensions, 703 .scale = 0.0f, 704 .zeroPoint = 0}; 705 if (operandCode == ANEURALNETWORKS_TENSOR_QUANT8_ASYMM) { 706 bias.type = ANEURALNETWORKS_TENSOR_INT32; 707 bias.scale = 0.25f; 708 } 709 710 ANeuralNetworksOperandType activation = {.type = ANEURALNETWORKS_INT32, 711 .dimensionCount = 0, 712 .dimensions = nullptr, 713 .scale = 0.0f, 714 .zeroPoint = 0}; 715 716 OperationTestBase fullyConnectedTest(ANEURALNETWORKS_FULLY_CONNECTED, 717 {input, weights, bias, activation}, 718 {output}); 719 720 EXPECT_TRUE(fullyConnectedTest.testMutatingInputOperandCode()); 721 EXPECT_TRUE(fullyConnectedTest.testMutatingInputOperandCounts()); 722 EXPECT_TRUE(fullyConnectedTest.testMutatingOutputOperandCode()); 723 EXPECT_TRUE(fullyConnectedTest.testMutatingOutputOperandCounts()); 724} 725 726TEST(OperationValidationTest, FULLY_CONNECTED_float32) { 727 fullyConnectedOpTest(ANEURALNETWORKS_TENSOR_FLOAT32); 728} 729 730TEST(OperationValidationTest, FULLY_CONNECTED_quant8) { 731 fullyConnectedOpTest(ANEURALNETWORKS_TENSOR_QUANT8_ASYMM); 732} 733 734void concatenationTest(int32_t operandCode) { 735 uint32_t inputDimensions[2] = {5, 5}; 736 ANeuralNetworksOperandType input1 = {.type = operandCode, 737 .dimensionCount = 2, 738 .dimensions = inputDimensions, 739 .scale = 0.0f, 740 .zeroPoint = 0}; 741 if (operandCode == ANEURALNETWORKS_TENSOR_QUANT8_ASYMM) { 742 input1.scale = 0.5f; 743 } 744 ANeuralNetworksOperandType input2 = input1; 745 ANeuralNetworksOperandType output = input1; 746 747 ANeuralNetworksOperandType activation = {.type = ANEURALNETWORKS_INT32, 748 .dimensionCount = 0, 749 .dimensions = nullptr, 750 .scale = 0.0f, 751 .zeroPoint = 0}; 752 753 OperationTestBase concat2Test(ANEURALNETWORKS_CONCATENATION, 754 {input1, input2, activation}, {output}); 755 756 EXPECT_TRUE(concat2Test.testMutatingInputOperandCode()); 757 EXPECT_TRUE(concat2Test.testMutatingOutputOperandCode()); 758 EXPECT_TRUE(concat2Test.testMutatingOutputOperandCounts()); 759 760 OperationTestBase concat1Test(ANEURALNETWORKS_CONCATENATION, 761 {input1, activation}, {output}); 762 763 EXPECT_TRUE(concat1Test.testMutatingInputOperandCode()); 764 EXPECT_TRUE(concat1Test.testMutatingOutputOperandCode()); 765 EXPECT_TRUE(concat1Test.testMutatingOutputOperandCounts()); 766} 767 768TEST(OperationValidationTest, CONCATENATION_float32) { 769 concatenationTest(ANEURALNETWORKS_TENSOR_FLOAT32); 770} 771 772TEST(OperationValidationTest, CONCATENATION_quant8) { 773 concatenationTest(ANEURALNETWORKS_TENSOR_QUANT8_ASYMM); 774} 775 776TEST(OperationValidationTest, RESIZE_BILINEAR_float32) { 777 uint32_t inputDimensions[4] = {2, 2, 2, 2}; 778 ANeuralNetworksOperandType input = {.type = ANEURALNETWORKS_TENSOR_FLOAT32, 779 .dimensionCount = 4, 780 .dimensions = inputDimensions, 781 .scale = 0.0f, 782 .zeroPoint = 0}; 783 ANeuralNetworksOperandType height = {.type = ANEURALNETWORKS_INT32, 784 .dimensionCount = 0, 785 .dimensions = nullptr, 786 .scale = 0.0f, 787 .zeroPoint = 0}; 788 ANeuralNetworksOperandType width = height; 789 ANeuralNetworksOperandType output = input; 790 OperationTestBase resizeTest(ANEURALNETWORKS_RESIZE_BILINEAR, 791 {input, height, width}, {output}); 792 793 EXPECT_TRUE(resizeTest.testMutatingInputOperandCode()); 794 EXPECT_TRUE(resizeTest.testMutatingInputOperandCounts()); 795 EXPECT_TRUE(resizeTest.testMutatingOutputOperandCode()); 796 EXPECT_TRUE(resizeTest.testMutatingOutputOperandCounts()); 797} 798 799void embeddingLookupTest(int32_t operandCode) { 800 uint32_t lookupDimensions[1] = {5}; 801 ANeuralNetworksOperandType lookup = {.type = ANEURALNETWORKS_TENSOR_INT32, 802 .dimensionCount = 1, 803 .dimensions = lookupDimensions, 804 .scale = 0.0f, 805 .zeroPoint = 0}; 806 807 uint32_t inputDimensions[2] = {5, 5}; 808 ANeuralNetworksOperandType input = {.type = operandCode, 809 .dimensionCount = 2, 810 .dimensions = inputDimensions, 811 .scale = 0.0f, 812 .zeroPoint = 0}; 813 if (operandCode == ANEURALNETWORKS_TENSOR_QUANT8_ASYMM) { 814 input.scale = 0.5f; 815 } 816 ANeuralNetworksOperandType output = input; 817 818 OperationTestBase embedLookupTest(ANEURALNETWORKS_EMBEDDING_LOOKUP, 819 {lookup, input}, {output}); 820 821 EXPECT_TRUE(embedLookupTest.testMutatingInputOperandCode()); 822 EXPECT_TRUE(embedLookupTest.testMutatingInputOperandCounts()); 823 EXPECT_TRUE(embedLookupTest.testMutatingOutputOperandCode()); 824 EXPECT_TRUE(embedLookupTest.testMutatingOutputOperandCounts()); 825} 826 827TEST(OperationValidationTest, EMBEDDING_LOOKUP_float32) { 828 embeddingLookupTest(ANEURALNETWORKS_TENSOR_FLOAT32); 829} 830 831TEST(OperationValidationTest, EMBEDDING_LOOKUP_quant8) { 832 embeddingLookupTest(ANEURALNETWORKS_TENSOR_QUANT8_ASYMM); 833} 834 835void hashtableLookupTest(int32_t operandCode) { 836 uint32_t lookupDimensions[1] = {5}; 837 ANeuralNetworksOperandType lookup = {.type = ANEURALNETWORKS_TENSOR_INT32, 838 .dimensionCount = 1, 839 .dimensions = lookupDimensions, 840 .scale = 0.0f, 841 .zeroPoint = 0}; 842 ANeuralNetworksOperandType keys = lookup; 843 844 uint32_t valuesDimensions[2] = {5, 5}; 845 ANeuralNetworksOperandType values = {.type = operandCode, 846 .dimensionCount = 2, 847 .dimensions = valuesDimensions, 848 .scale = 0.0f, 849 .zeroPoint = 0}; 850 if (operandCode == ANEURALNETWORKS_TENSOR_QUANT8_ASYMM) { 851 values.scale = 0.5f; 852 } 853 ANeuralNetworksOperandType output = values; 854 855 ANeuralNetworksOperandType hits = lookup; 856 hits.type = ANEURALNETWORKS_TENSOR_QUANT8_ASYMM; 857 hits.scale = 1.0f; 858 859 OperationTestBase hashLookupTest(ANEURALNETWORKS_HASHTABLE_LOOKUP, 860 {lookup, keys, values}, {output, hits}); 861 862 EXPECT_TRUE(hashLookupTest.testMutatingInputOperandCode()); 863 EXPECT_TRUE(hashLookupTest.testMutatingInputOperandCounts()); 864 EXPECT_TRUE(hashLookupTest.testMutatingOutputOperandCode()); 865 EXPECT_TRUE(hashLookupTest.testMutatingOutputOperandCounts()); 866} 867 868TEST(OperationValidationTest, HASHTABLE_LOOKUP_float32) { 869 hashtableLookupTest(ANEURALNETWORKS_TENSOR_FLOAT32); 870} 871 872TEST(OperationValidationTest, HASHTABLE_LOOKUP_quant8) { 873 hashtableLookupTest(ANEURALNETWORKS_TENSOR_QUANT8_ASYMM); 874} 875 876void lshProjectionTest(int32_t operandCode) { 877 uint32_t inputDimensions[2] = {5, 5}; 878 ANeuralNetworksOperandType hash = {.type = ANEURALNETWORKS_TENSOR_FLOAT32, 879 .dimensionCount = 2, 880 .dimensions = inputDimensions, 881 .scale = 0.0f, 882 .zeroPoint = 0}; 883 884 ANeuralNetworksOperandType input = hash; 885 input.type = operandCode; 886 if (operandCode == ANEURALNETWORKS_TENSOR_QUANT8_ASYMM) { 887 input.scale = 0.5f; 888 } 889 890 uint32_t weightDimensions[1] = {5}; 891 ANeuralNetworksOperandType weight = {.type = ANEURALNETWORKS_TENSOR_FLOAT32, 892 .dimensionCount = 1, 893 .dimensions = weightDimensions, 894 .scale = 0.0f, 895 .zeroPoint = 0}; 896 897 ANeuralNetworksOperandType type = {.type = ANEURALNETWORKS_INT32, 898 .dimensionCount = 0, 899 .dimensions = nullptr, 900 .scale = 0.0f, 901 .zeroPoint = 0}; 902 903 ANeuralNetworksOperandType output = weight; 904 output.type = ANEURALNETWORKS_TENSOR_INT32; 905 906 OperationTestBase lshProjTest(ANEURALNETWORKS_LSH_PROJECTION, 907 {hash, input, weight, type}, {output}); 908 909 EXPECT_TRUE(lshProjTest.testMutatingInputOperandCode()); 910 EXPECT_TRUE(lshProjTest.testMutatingInputOperandCounts()); 911 EXPECT_TRUE(lshProjTest.testMutatingOutputOperandCode()); 912 EXPECT_TRUE(lshProjTest.testMutatingOutputOperandCounts()); 913} 914 915TEST(OperationValidationTest, LSH_PROJECTION_float32) { 916 lshProjectionTest(ANEURALNETWORKS_TENSOR_FLOAT32); 917} 918 919TEST(OperationValidationTest, LSH_PROJECTION_quant8) { 920 lshProjectionTest(ANEURALNETWORKS_TENSOR_QUANT8_ASYMM); 921} 922 923TEST(OperationValidationTest, LSTM_float32) { 924 uint32_t oneDimensional[1] = {5}; 925 uint32_t twoDimensional[2] = {5, 5}; 926 ANeuralNetworksOperandType floatTensor1D = {.type = ANEURALNETWORKS_TENSOR_FLOAT32, 927 .dimensionCount = 1, 928 .dimensions = oneDimensional, 929 .scale = 0.0f, 930 .zeroPoint = 0}; 931 ANeuralNetworksOperandType floatTensor2D = {.type = ANEURALNETWORKS_TENSOR_FLOAT32, 932 .dimensionCount = 2, 933 .dimensions = twoDimensional, 934 .scale = 0.0f, 935 .zeroPoint = 0}; 936 ANeuralNetworksOperandType intScalar = {.type = ANEURALNETWORKS_INT32, 937 .dimensionCount = 0, 938 .dimensions = nullptr, 939 .scale = 0.0f, 940 .zeroPoint = 0}; 941 ANeuralNetworksOperandType floatScalar = {.type = ANEURALNETWORKS_FLOAT32, 942 .dimensionCount = 0, 943 .dimensions = nullptr, 944 .scale = 0.0f, 945 .zeroPoint = 0}; 946 947 ANeuralNetworksOperandType input = floatTensor2D; 948 ANeuralNetworksOperandType inputToInput = floatTensor2D; 949 ANeuralNetworksOperandType inputToForget = floatTensor2D; 950 ANeuralNetworksOperandType inputToCell = floatTensor2D; 951 ANeuralNetworksOperandType inputToOutput = floatTensor2D; 952 ANeuralNetworksOperandType recurrentToInput = floatTensor2D; 953 ANeuralNetworksOperandType recurrentToForget = floatTensor2D; 954 ANeuralNetworksOperandType recurrentToCell = floatTensor2D; 955 ANeuralNetworksOperandType recurrentToOutput = floatTensor2D; 956 ANeuralNetworksOperandType cellToInput = floatTensor1D; 957 ANeuralNetworksOperandType cellToForget = floatTensor1D; 958 ANeuralNetworksOperandType cellToOutput = floatTensor1D; 959 ANeuralNetworksOperandType inputGateBias = floatTensor1D; 960 ANeuralNetworksOperandType forgetGateBias = floatTensor1D; 961 ANeuralNetworksOperandType cellBias = floatTensor1D; 962 ANeuralNetworksOperandType outputGateBias = floatTensor1D; 963 ANeuralNetworksOperandType projWeights = floatTensor2D; 964 ANeuralNetworksOperandType projBias = floatTensor1D; 965 ANeuralNetworksOperandType outputStateIn = floatTensor2D; 966 ANeuralNetworksOperandType cellStateIn = floatTensor2D; 967 ANeuralNetworksOperandType activation = intScalar; 968 ANeuralNetworksOperandType clipCellState = floatScalar; 969 ANeuralNetworksOperandType clipProjLayer = floatScalar; 970 971 ANeuralNetworksOperandType scratch = floatTensor2D; 972 ANeuralNetworksOperandType outputStateOut = floatTensor2D; 973 ANeuralNetworksOperandType cellStateOut = floatTensor2D; 974 ANeuralNetworksOperandType output = floatTensor2D; 975 976 OperationTestBase lstmTest(ANEURALNETWORKS_LSTM, 977 {input, inputToInput, inputToForget, inputToCell, inputToOutput, recurrentToInput, 978 recurrentToForget, recurrentToCell, recurrentToOutput, cellToInput, cellToForget, 979 cellToOutput, inputGateBias, forgetGateBias, cellBias, outputGateBias, projWeights, 980 projBias, outputStateIn, cellStateIn, activation, clipCellState, clipProjLayer}, 981 {scratch, outputStateOut, cellStateOut, output}); 982 983 EXPECT_TRUE(lstmTest.testMutatingInputOperandCode()); 984 EXPECT_TRUE(lstmTest.testMutatingInputOperandCounts()); 985 EXPECT_TRUE(lstmTest.testMutatingOutputOperandCode()); 986 EXPECT_TRUE(lstmTest.testMutatingOutputOperandCounts()); 987} 988 989TEST(OperationValidationTest, RNN_float32) { 990 uint32_t oneDimensional[1] = {5}; 991 uint32_t twoDimensional[2] = {5, 5}; 992 ANeuralNetworksOperandType floatTensor1D = {.type = ANEURALNETWORKS_TENSOR_FLOAT32, 993 .dimensionCount = 1, 994 .dimensions = oneDimensional, 995 .scale = 0.0f, 996 .zeroPoint = 0}; 997 ANeuralNetworksOperandType floatTensor2D = {.type = ANEURALNETWORKS_TENSOR_FLOAT32, 998 .dimensionCount = 2, 999 .dimensions = twoDimensional, 1000 .scale = 0.0f, 1001 .zeroPoint = 0}; 1002 ANeuralNetworksOperandType intScalar = {.type = ANEURALNETWORKS_INT32, 1003 .dimensionCount = 0, 1004 .dimensions = nullptr, 1005 .scale = 0.0f, 1006 .zeroPoint = 0}; 1007 1008 ANeuralNetworksOperandType input = floatTensor2D; 1009 ANeuralNetworksOperandType weights = floatTensor2D; 1010 ANeuralNetworksOperandType recurrentWeights = floatTensor2D; 1011 ANeuralNetworksOperandType bias = floatTensor1D; 1012 ANeuralNetworksOperandType hiddenStateIn = floatTensor2D; 1013 ANeuralNetworksOperandType activation = intScalar; 1014 1015 ANeuralNetworksOperandType hiddenStateOut = floatTensor2D; 1016 ANeuralNetworksOperandType output = floatTensor2D; 1017 1018 OperationTestBase rnnTest(ANEURALNETWORKS_RNN, 1019 {input, weights, recurrentWeights, bias, hiddenStateIn, activation}, 1020 {hiddenStateOut, output}); 1021 1022 EXPECT_TRUE(rnnTest.testMutatingInputOperandCode()); 1023 EXPECT_TRUE(rnnTest.testMutatingInputOperandCounts()); 1024 EXPECT_TRUE(rnnTest.testMutatingOutputOperandCode()); 1025 EXPECT_TRUE(rnnTest.testMutatingOutputOperandCounts()); 1026} 1027 1028TEST(OperationValidationTest, SVDF_float32) { 1029 uint32_t oneDimensional[1] = {5}; 1030 uint32_t twoDimensional[2] = {5, 5}; 1031 ANeuralNetworksOperandType floatTensor1D = {.type = ANEURALNETWORKS_TENSOR_FLOAT32, 1032 .dimensionCount = 1, 1033 .dimensions = oneDimensional, 1034 .scale = 0.0f, 1035 .zeroPoint = 0}; 1036 ANeuralNetworksOperandType floatTensor2D = {.type = ANEURALNETWORKS_TENSOR_FLOAT32, 1037 .dimensionCount = 2, 1038 .dimensions = twoDimensional, 1039 .scale = 0.0f, 1040 .zeroPoint = 0}; 1041 ANeuralNetworksOperandType intScalar = {.type = ANEURALNETWORKS_INT32, 1042 .dimensionCount = 0, 1043 .dimensions = nullptr, 1044 .scale = 0.0f, 1045 .zeroPoint = 0}; 1046 1047 ANeuralNetworksOperandType input = floatTensor2D; 1048 ANeuralNetworksOperandType weightsFeature = floatTensor2D; 1049 ANeuralNetworksOperandType weightsTime = floatTensor2D; 1050 ANeuralNetworksOperandType bias = floatTensor1D; 1051 ANeuralNetworksOperandType stateIn = floatTensor2D; 1052 ANeuralNetworksOperandType rank = intScalar; 1053 ANeuralNetworksOperandType activation = intScalar; 1054 1055 ANeuralNetworksOperandType stateOut = floatTensor2D; 1056 ANeuralNetworksOperandType output = floatTensor2D; 1057 1058 OperationTestBase svdfTest(ANEURALNETWORKS_SVDF, 1059 {input, weightsFeature, weightsTime, bias, stateIn, rank, activation}, 1060 {stateOut, output}); 1061 1062 EXPECT_TRUE(svdfTest.testMutatingInputOperandCode()); 1063 EXPECT_TRUE(svdfTest.testMutatingInputOperandCounts()); 1064 EXPECT_TRUE(svdfTest.testMutatingOutputOperandCode()); 1065 EXPECT_TRUE(svdfTest.testMutatingOutputOperandCounts()); 1066} 1067 1068void stridedSliceOpTest(int32_t operandCode) { 1069 uint32_t inputDimensions[2] = {5, 5}; 1070 ANeuralNetworksOperandType input = {.type = operandCode, 1071 .dimensionCount = 2, 1072 .dimensions = inputDimensions, 1073 .scale = 0.0f, 1074 .zeroPoint = 0}; 1075 if (operandCode == ANEURALNETWORKS_TENSOR_QUANT8_ASYMM) { 1076 input.scale = 0.5f; 1077 } 1078 ANeuralNetworksOperandType output = input; 1079 1080 uint32_t beginsDimensions[1] = {2}; 1081 ANeuralNetworksOperandType begins = {.type = ANEURALNETWORKS_TENSOR_INT32, 1082 .dimensionCount = 1, 1083 .dimensions = beginsDimensions, 1084 .scale = 0.0f, 1085 .zeroPoint = 0}; 1086 1087 ANeuralNetworksOperandType ends = begins; 1088 ANeuralNetworksOperandType strides = begins; 1089 1090 ANeuralNetworksOperandType beginMask = {.type = ANEURALNETWORKS_INT32, 1091 .dimensionCount = 0, 1092 .dimensions = nullptr, 1093 .scale = 0.0f, 1094 .zeroPoint = 0}; 1095 ANeuralNetworksOperandType endMask = beginMask; 1096 ANeuralNetworksOperandType shrinkAxisMask = beginMask; 1097 1098 OperationTestBase stridedSliceTest(ANEURALNETWORKS_STRIDED_SLICE, 1099 {input, begins, ends, strides, 1100 beginMask, endMask, shrinkAxisMask}, 1101 {output}); 1102 1103 EXPECT_TRUE(stridedSliceTest.testMutatingInputOperandCode()); 1104 EXPECT_TRUE(stridedSliceTest.testMutatingInputOperandCounts()); 1105 EXPECT_TRUE(stridedSliceTest.testMutatingOutputOperandCode()); 1106 EXPECT_TRUE(stridedSliceTest.testMutatingOutputOperandCounts()); 1107} 1108 1109TEST(OperationValidationTest, STRIDED_SLICE_float32) { 1110 stridedSliceOpTest(ANEURALNETWORKS_TENSOR_FLOAT32); 1111} 1112 1113TEST(OperationValidationTest, STRIDED_SLICE_quant8) { 1114 stridedSliceOpTest(ANEURALNETWORKS_TENSOR_QUANT8_ASYMM); 1115} 1116 1117} // end namespace 1118