diff options
-rw-r--r-- | nn/common/operations/L2Normalization.cpp | 3 | ||||
-rw-r--r-- | nn/runtime/include/NeuralNetworks.h | 4 | ||||
-rw-r--r-- | nn/runtime/test/fuzzing/TestRandomGraph.cpp | 5 | ||||
-rw-r--r-- | nn/runtime/test/generated/spec_V1_2/l2_normalization_axis.example.cpp | 888 | ||||
-rw-r--r-- | nn/runtime/test/generated/spec_V1_3/l2_normalization_zeros.example.cpp | 746 | ||||
-rw-r--r-- | nn/runtime/test/specs/V1_2/l2_normalization_axis.mod.py | 13 | ||||
-rw-r--r-- | nn/runtime/test/specs/V1_3/l2_normalization_zeros.mod.py | 41 | ||||
-rw-r--r-- | nn/tools/api/types.spec | 18 |
8 files changed, 1710 insertions, 8 deletions
diff --git a/nn/common/operations/L2Normalization.cpp b/nn/common/operations/L2Normalization.cpp index 31206e236..1925d5471 100644 --- a/nn/common/operations/L2Normalization.cpp +++ b/nn/common/operations/L2Normalization.cpp @@ -47,6 +47,7 @@ using namespace hal; inline bool l2normFloat32Impl(const float* inputData, const Shape& inputShape, int32_t axis, float* outputData, const Shape& outputShape) { NNTRACE_TRANS("l2normFloat32"); + constexpr float kEpsilon = 1e-6f; const uint32_t outerSize = getNumberOfElements(inputShape, 0, axis); const uint32_t axisSize = getSizeOfDimension(inputShape, axis); const uint32_t innerSize = @@ -61,7 +62,7 @@ inline bool l2normFloat32Impl(const float* inputData, const Shape& inputShape, i float val = *p; sum += val * val; } - float l2_norm = std::sqrt(sum); + float l2_norm = std::max(std::sqrt(sum), kEpsilon); float* pOut = outputBeg; for (const float* p = inputBeg; p < inputEnd; p += innerSize, pOut += innerSize) { *pOut = *p / l2_norm; diff --git a/nn/runtime/include/NeuralNetworks.h b/nn/runtime/include/NeuralNetworks.h index 923531b3e..79008daf4 100644 --- a/nn/runtime/include/NeuralNetworks.h +++ b/nn/runtime/include/NeuralNetworks.h @@ -1013,6 +1013,10 @@ typedef enum { * For {@link ANEURALNETWORKS_TENSOR_QUANT8_ASYMM_SIGNED}, * the scale must be 1.f / 128 and the zeroPoint must be 0. * + * NOTE: Before API level 30, if the elements along an axis are all zeros, + * the result is undefined. Since API level 30, if the elements along an axis + * are all zeros, the result is logical zero. + * * Available since API level 27. */ ANEURALNETWORKS_L2_NORMALIZATION = 11, diff --git a/nn/runtime/test/fuzzing/TestRandomGraph.cpp b/nn/runtime/test/fuzzing/TestRandomGraph.cpp index 25cf86a40..7facc363a 100644 --- a/nn/runtime/test/fuzzing/TestRandomGraph.cpp +++ b/nn/runtime/test/fuzzing/TestRandomGraph.cpp @@ -205,6 +205,11 @@ class RandomGraphTest : public ::testing::TestWithParam<uint32_t> { featureLevel <= __ANDROID_API_Q__) { return true; } + // L2_NORMALIZATION on axis of all zeros is undefined before R. + if (op.type == TestOperationType::L2_NORMALIZATION && + featureLevel <= __ANDROID_API_Q__) { + return true; + } // TODO(xusongw): Remove after b/151328024 is resolved. if (op.type == TestOperationType::ROI_ALIGN) { return true; diff --git a/nn/runtime/test/generated/spec_V1_2/l2_normalization_axis.example.cpp b/nn/runtime/test/generated/spec_V1_2/l2_normalization_axis.example.cpp index 88ad5574b..ad15c7d04 100644 --- a/nn/runtime/test/generated/spec_V1_2/l2_normalization_axis.example.cpp +++ b/nn/runtime/test/generated/spec_V1_2/l2_normalization_axis.example.cpp @@ -11844,3 +11844,891 @@ const auto dummy_test_model_dim1_axis0_neg_quant8_all_inputs_as_internal = TestM } // namespace generated_tests::l2_normalization_axis +namespace generated_tests::l2_normalization_axis { + +const TestModel& get_test_model_corner_case_dim2_axis0() { + static TestModel model = { + .expectFailure = false, + .expectedMultinomialDistributionTolerance = 0, + .isRelaxed = false, + .main = { + .inputIndexes = {0}, + .operands = {{ + .channelQuant = {}, + .data = TestBuffer::createFromVector<uint8_t>({245, 247}), + .dimensions = {1, 2}, + .isIgnored = false, + .lifetime = TestOperandLifeTime::SUBGRAPH_INPUT, + .numberOfConsumers = 1, + .scale = 0.904414f, + .type = TestOperandType::TENSOR_QUANT8_ASYMM, + .zeroPoint = 246 + }, { + .channelQuant = {}, + .data = TestBuffer::createFromVector<int32_t>({0}), + .dimensions = {}, + .isIgnored = false, + .lifetime = TestOperandLifeTime::CONSTANT_COPY, + .numberOfConsumers = 1, + .scale = 0.0f, + .type = TestOperandType::INT32, + .zeroPoint = 0 + }, { + .channelQuant = {}, + .data = TestBuffer::createFromVector<uint8_t>({0, 255}), + .dimensions = {1, 2}, + .isIgnored = false, + .lifetime = TestOperandLifeTime::SUBGRAPH_OUTPUT, + .numberOfConsumers = 0, + .scale = 0.0078125f, + .type = TestOperandType::TENSOR_QUANT8_ASYMM, + .zeroPoint = 128 + }}, + .operations = {{ + .inputs = {0, 1}, + .outputs = {2}, + .type = TestOperationType::L2_NORMALIZATION + }}, + .outputIndexes = {2} + }, + .minSupportedVersion = TestHalVersion::V1_2, + .referenced = {} + }; + return model; +} + +const auto dummy_test_model_corner_case_dim2_axis0 = TestModelManager::get().add("l2_normalization_axis_corner_case_dim2_axis0", get_test_model_corner_case_dim2_axis0()); + +} // namespace generated_tests::l2_normalization_axis + +namespace generated_tests::l2_normalization_axis { + +const TestModel& get_test_model_corner_case_dim2_axis0_all_inputs_as_internal() { + static TestModel model = { + .expectFailure = false, + .expectedMultinomialDistributionTolerance = 0, + .isRelaxed = false, + .main = { + .inputIndexes = {3}, + .operands = {{ + .channelQuant = {}, + .data = TestBuffer::createFromVector<uint8_t>({}), + .dimensions = {1, 2}, + .isIgnored = false, + .lifetime = TestOperandLifeTime::TEMPORARY_VARIABLE, + .numberOfConsumers = 1, + .scale = 0.904414f, + .type = TestOperandType::TENSOR_QUANT8_ASYMM, + .zeroPoint = 246 + }, { + .channelQuant = {}, + .data = TestBuffer::createFromVector<int32_t>({0}), + .dimensions = {}, + .isIgnored = false, + .lifetime = TestOperandLifeTime::CONSTANT_COPY, + .numberOfConsumers = 1, + .scale = 0.0f, + .type = TestOperandType::INT32, + .zeroPoint = 0 + }, { + .channelQuant = {}, + .data = TestBuffer::createFromVector<uint8_t>({0, 255}), + .dimensions = {1, 2}, + .isIgnored = false, + .lifetime = TestOperandLifeTime::SUBGRAPH_OUTPUT, + .numberOfConsumers = 0, + .scale = 0.0078125f, + .type = TestOperandType::TENSOR_QUANT8_ASYMM, + .zeroPoint = 128 + }, { + .channelQuant = {}, + .data = TestBuffer::createFromVector<uint8_t>({245, 247}), + .dimensions = {1, 2}, + .isIgnored = false, + .lifetime = TestOperandLifeTime::SUBGRAPH_INPUT, + .numberOfConsumers = 1, + .scale = 0.904414f, + .type = TestOperandType::TENSOR_QUANT8_ASYMM, + .zeroPoint = 246 + }, { + .channelQuant = {}, + .data = TestBuffer::createFromVector<uint8_t>({246}), + .dimensions = {1}, + .isIgnored = false, + .lifetime = TestOperandLifeTime::CONSTANT_COPY, + .numberOfConsumers = 1, + .scale = 0.904414f, + .type = TestOperandType::TENSOR_QUANT8_ASYMM, + .zeroPoint = 246 + }, { + .channelQuant = {}, + .data = TestBuffer::createFromVector<int32_t>({0}), + .dimensions = {}, + .isIgnored = false, + .lifetime = TestOperandLifeTime::CONSTANT_COPY, + .numberOfConsumers = 1, + .scale = 0.0f, + .type = TestOperandType::INT32, + .zeroPoint = 0 + }}, + .operations = {{ + .inputs = {3, 4, 5}, + .outputs = {0}, + .type = TestOperationType::ADD + }, { + .inputs = {0, 1}, + .outputs = {2}, + .type = TestOperationType::L2_NORMALIZATION + }}, + .outputIndexes = {2} + }, + .minSupportedVersion = TestHalVersion::V1_2, + .referenced = {} + }; + return model; +} + +const auto dummy_test_model_corner_case_dim2_axis0_all_inputs_as_internal = TestModelManager::get().add("l2_normalization_axis_corner_case_dim2_axis0_all_inputs_as_internal", get_test_model_corner_case_dim2_axis0_all_inputs_as_internal()); + +} // namespace generated_tests::l2_normalization_axis + +namespace generated_tests::l2_normalization_axis { + +const TestModel& get_test_model_corner_case_dim2_axis0_neg() { + static TestModel model = { + .expectFailure = false, + .expectedMultinomialDistributionTolerance = 0, + .isRelaxed = false, + .main = { + .inputIndexes = {0}, + .operands = {{ + .channelQuant = {}, + .data = TestBuffer::createFromVector<uint8_t>({245, 247}), + .dimensions = {1, 2}, + .isIgnored = false, + .lifetime = TestOperandLifeTime::SUBGRAPH_INPUT, + .numberOfConsumers = 1, + .scale = 0.904414f, + .type = TestOperandType::TENSOR_QUANT8_ASYMM, + .zeroPoint = 246 + }, { + .channelQuant = {}, + .data = TestBuffer::createFromVector<int32_t>({-2}), + .dimensions = {}, + .isIgnored = false, + .lifetime = TestOperandLifeTime::CONSTANT_COPY, + .numberOfConsumers = 1, + .scale = 0.0f, + .type = TestOperandType::INT32, + .zeroPoint = 0 + }, { + .channelQuant = {}, + .data = TestBuffer::createFromVector<uint8_t>({0, 255}), + .dimensions = {1, 2}, + .isIgnored = false, + .lifetime = TestOperandLifeTime::SUBGRAPH_OUTPUT, + .numberOfConsumers = 0, + .scale = 0.0078125f, + .type = TestOperandType::TENSOR_QUANT8_ASYMM, + .zeroPoint = 128 + }}, + .operations = {{ + .inputs = {0, 1}, + .outputs = {2}, + .type = TestOperationType::L2_NORMALIZATION + }}, + .outputIndexes = {2} + }, + .minSupportedVersion = TestHalVersion::V1_2, + .referenced = {} + }; + return model; +} + +const auto dummy_test_model_corner_case_dim2_axis0_neg = TestModelManager::get().add("l2_normalization_axis_corner_case_dim2_axis0_neg", get_test_model_corner_case_dim2_axis0_neg()); + +} // namespace generated_tests::l2_normalization_axis + +namespace generated_tests::l2_normalization_axis { + +const TestModel& get_test_model_corner_case_dim2_axis0_neg_all_inputs_as_internal() { + static TestModel model = { + .expectFailure = false, + .expectedMultinomialDistributionTolerance = 0, + .isRelaxed = false, + .main = { + .inputIndexes = {3}, + .operands = {{ + .channelQuant = {}, + .data = TestBuffer::createFromVector<uint8_t>({}), + .dimensions = {1, 2}, + .isIgnored = false, + .lifetime = TestOperandLifeTime::TEMPORARY_VARIABLE, + .numberOfConsumers = 1, + .scale = 0.904414f, + .type = TestOperandType::TENSOR_QUANT8_ASYMM, + .zeroPoint = 246 + }, { + .channelQuant = {}, + .data = TestBuffer::createFromVector<int32_t>({-2}), + .dimensions = {}, + .isIgnored = false, + .lifetime = TestOperandLifeTime::CONSTANT_COPY, + .numberOfConsumers = 1, + .scale = 0.0f, + .type = TestOperandType::INT32, + .zeroPoint = 0 + }, { + .channelQuant = {}, + .data = TestBuffer::createFromVector<uint8_t>({0, 255}), + .dimensions = {1, 2}, + .isIgnored = false, + .lifetime = TestOperandLifeTime::SUBGRAPH_OUTPUT, + .numberOfConsumers = 0, + .scale = 0.0078125f, + .type = TestOperandType::TENSOR_QUANT8_ASYMM, + .zeroPoint = 128 + }, { + .channelQuant = {}, + .data = TestBuffer::createFromVector<uint8_t>({245, 247}), + .dimensions = {1, 2}, + .isIgnored = false, + .lifetime = TestOperandLifeTime::SUBGRAPH_INPUT, + .numberOfConsumers = 1, + .scale = 0.904414f, + .type = TestOperandType::TENSOR_QUANT8_ASYMM, + .zeroPoint = 246 + }, { + .channelQuant = {}, + .data = TestBuffer::createFromVector<uint8_t>({246}), + .dimensions = {1}, + .isIgnored = false, + .lifetime = TestOperandLifeTime::CONSTANT_COPY, + .numberOfConsumers = 1, + .scale = 0.904414f, + .type = TestOperandType::TENSOR_QUANT8_ASYMM, + .zeroPoint = 246 + }, { + .channelQuant = {}, + .data = TestBuffer::createFromVector<int32_t>({0}), + .dimensions = {}, + .isIgnored = false, + .lifetime = TestOperandLifeTime::CONSTANT_COPY, + .numberOfConsumers = 1, + .scale = 0.0f, + .type = TestOperandType::INT32, + .zeroPoint = 0 + }}, + .operations = {{ + .inputs = {3, 4, 5}, + .outputs = {0}, + .type = TestOperationType::ADD + }, { + .inputs = {0, 1}, + .outputs = {2}, + .type = TestOperationType::L2_NORMALIZATION + }}, + .outputIndexes = {2} + }, + .minSupportedVersion = TestHalVersion::V1_2, + .referenced = {} + }; + return model; +} + +const auto dummy_test_model_corner_case_dim2_axis0_neg_all_inputs_as_internal = TestModelManager::get().add("l2_normalization_axis_corner_case_dim2_axis0_neg_all_inputs_as_internal", get_test_model_corner_case_dim2_axis0_neg_all_inputs_as_internal()); + +} // namespace generated_tests::l2_normalization_axis + +namespace generated_tests::l2_normalization_axis { + +const TestModel& get_test_model_corner_case_dim2_axis1() { + static TestModel model = { + .expectFailure = false, + .expectedMultinomialDistributionTolerance = 0, + .isRelaxed = false, + .main = { + .inputIndexes = {0}, + .operands = {{ + .channelQuant = {}, + .data = TestBuffer::createFromVector<uint8_t>({245, 247}), + .dimensions = {2, 1}, + .isIgnored = false, + .lifetime = TestOperandLifeTime::SUBGRAPH_INPUT, + .numberOfConsumers = 1, + .scale = 0.904414f, + .type = TestOperandType::TENSOR_QUANT8_ASYMM, + .zeroPoint = 246 + }, { + .channelQuant = {}, + .data = TestBuffer::createFromVector<int32_t>({1}), + .dimensions = {}, + .isIgnored = false, + .lifetime = TestOperandLifeTime::CONSTANT_COPY, + .numberOfConsumers = 1, + .scale = 0.0f, + .type = TestOperandType::INT32, + .zeroPoint = 0 + }, { + .channelQuant = {}, + .data = TestBuffer::createFromVector<uint8_t>({0, 255}), + .dimensions = {2, 1}, + .isIgnored = false, + .lifetime = TestOperandLifeTime::SUBGRAPH_OUTPUT, + .numberOfConsumers = 0, + .scale = 0.0078125f, + .type = TestOperandType::TENSOR_QUANT8_ASYMM, + .zeroPoint = 128 + }}, + .operations = {{ + .inputs = {0, 1}, + .outputs = {2}, + .type = TestOperationType::L2_NORMALIZATION + }}, + .outputIndexes = {2} + }, + .minSupportedVersion = TestHalVersion::V1_2, + .referenced = {} + }; + return model; +} + +const auto dummy_test_model_corner_case_dim2_axis1 = TestModelManager::get().add("l2_normalization_axis_corner_case_dim2_axis1", get_test_model_corner_case_dim2_axis1()); + +} // namespace generated_tests::l2_normalization_axis + +namespace generated_tests::l2_normalization_axis { + +const TestModel& get_test_model_corner_case_dim2_axis1_all_inputs_as_internal() { + static TestModel model = { + .expectFailure = false, + .expectedMultinomialDistributionTolerance = 0, + .isRelaxed = false, + .main = { + .inputIndexes = {3}, + .operands = {{ + .channelQuant = {}, + .data = TestBuffer::createFromVector<uint8_t>({}), + .dimensions = {2, 1}, + .isIgnored = false, + .lifetime = TestOperandLifeTime::TEMPORARY_VARIABLE, + .numberOfConsumers = 1, + .scale = 0.904414f, + .type = TestOperandType::TENSOR_QUANT8_ASYMM, + .zeroPoint = 246 + }, { + .channelQuant = {}, + .data = TestBuffer::createFromVector<int32_t>({1}), + .dimensions = {}, + .isIgnored = false, + .lifetime = TestOperandLifeTime::CONSTANT_COPY, + .numberOfConsumers = 1, + .scale = 0.0f, + .type = TestOperandType::INT32, + .zeroPoint = 0 + }, { + .channelQuant = {}, + .data = TestBuffer::createFromVector<uint8_t>({0, 255}), + .dimensions = {2, 1}, + .isIgnored = false, + .lifetime = TestOperandLifeTime::SUBGRAPH_OUTPUT, + .numberOfConsumers = 0, + .scale = 0.0078125f, + .type = TestOperandType::TENSOR_QUANT8_ASYMM, + .zeroPoint = 128 + }, { + .channelQuant = {}, + .data = TestBuffer::createFromVector<uint8_t>({245, 247}), + .dimensions = {2, 1}, + .isIgnored = false, + .lifetime = TestOperandLifeTime::SUBGRAPH_INPUT, + .numberOfConsumers = 1, + .scale = 0.904414f, + .type = TestOperandType::TENSOR_QUANT8_ASYMM, + .zeroPoint = 246 + }, { + .channelQuant = {}, + .data = TestBuffer::createFromVector<uint8_t>({246}), + .dimensions = {1}, + .isIgnored = false, + .lifetime = TestOperandLifeTime::CONSTANT_COPY, + .numberOfConsumers = 1, + .scale = 0.904414f, + .type = TestOperandType::TENSOR_QUANT8_ASYMM, + .zeroPoint = 246 + }, { + .channelQuant = {}, + .data = TestBuffer::createFromVector<int32_t>({0}), + .dimensions = {}, + .isIgnored = false, + .lifetime = TestOperandLifeTime::CONSTANT_COPY, + .numberOfConsumers = 1, + .scale = 0.0f, + .type = TestOperandType::INT32, + .zeroPoint = 0 + }}, + .operations = {{ + .inputs = {3, 4, 5}, + .outputs = {0}, + .type = TestOperationType::ADD + }, { + .inputs = {0, 1}, + .outputs = {2}, + .type = TestOperationType::L2_NORMALIZATION + }}, + .outputIndexes = {2} + }, + .minSupportedVersion = TestHalVersion::V1_2, + .referenced = {} + }; + return model; +} + +const auto dummy_test_model_corner_case_dim2_axis1_all_inputs_as_internal = TestModelManager::get().add("l2_normalization_axis_corner_case_dim2_axis1_all_inputs_as_internal", get_test_model_corner_case_dim2_axis1_all_inputs_as_internal()); + +} // namespace generated_tests::l2_normalization_axis + +namespace generated_tests::l2_normalization_axis { + +const TestModel& get_test_model_corner_case_dim2_axis1_neg() { + static TestModel model = { + .expectFailure = false, + .expectedMultinomialDistributionTolerance = 0, + .isRelaxed = false, + .main = { + .inputIndexes = {0}, + .operands = {{ + .channelQuant = {}, + .data = TestBuffer::createFromVector<uint8_t>({245, 247}), + .dimensions = {2, 1}, + .isIgnored = false, + .lifetime = TestOperandLifeTime::SUBGRAPH_INPUT, + .numberOfConsumers = 1, + .scale = 0.904414f, + .type = TestOperandType::TENSOR_QUANT8_ASYMM, + .zeroPoint = 246 + }, { + .channelQuant = {}, + .data = TestBuffer::createFromVector<int32_t>({-1}), + .dimensions = {}, + .isIgnored = false, + .lifetime = TestOperandLifeTime::CONSTANT_COPY, + .numberOfConsumers = 1, + .scale = 0.0f, + .type = TestOperandType::INT32, + .zeroPoint = 0 + }, { + .channelQuant = {}, + .data = TestBuffer::createFromVector<uint8_t>({0, 255}), + .dimensions = {2, 1}, + .isIgnored = false, + .lifetime = TestOperandLifeTime::SUBGRAPH_OUTPUT, + .numberOfConsumers = 0, + .scale = 0.0078125f, + .type = TestOperandType::TENSOR_QUANT8_ASYMM, + .zeroPoint = 128 + }}, + .operations = {{ + .inputs = {0, 1}, + .outputs = {2}, + .type = TestOperationType::L2_NORMALIZATION + }}, + .outputIndexes = {2} + }, + .minSupportedVersion = TestHalVersion::V1_2, + .referenced = {} + }; + return model; +} + +const auto dummy_test_model_corner_case_dim2_axis1_neg = TestModelManager::get().add("l2_normalization_axis_corner_case_dim2_axis1_neg", get_test_model_corner_case_dim2_axis1_neg()); + +} // namespace generated_tests::l2_normalization_axis + +namespace generated_tests::l2_normalization_axis { + +const TestModel& get_test_model_corner_case_dim2_axis1_neg_all_inputs_as_internal() { + static TestModel model = { + .expectFailure = false, + .expectedMultinomialDistributionTolerance = 0, + .isRelaxed = false, + .main = { + .inputIndexes = {3}, + .operands = {{ + .channelQuant = {}, + .data = TestBuffer::createFromVector<uint8_t>({}), + .dimensions = {2, 1}, + .isIgnored = false, + .lifetime = TestOperandLifeTime::TEMPORARY_VARIABLE, + .numberOfConsumers = 1, + .scale = 0.904414f, + .type = TestOperandType::TENSOR_QUANT8_ASYMM, + .zeroPoint = 246 + }, { + .channelQuant = {}, + .data = TestBuffer::createFromVector<int32_t>({-1}), + .dimensions = {}, + .isIgnored = false, + .lifetime = TestOperandLifeTime::CONSTANT_COPY, + .numberOfConsumers = 1, + .scale = 0.0f, + .type = TestOperandType::INT32, + .zeroPoint = 0 + }, { + .channelQuant = {}, + .data = TestBuffer::createFromVector<uint8_t>({0, 255}), + .dimensions = {2, 1}, + .isIgnored = false, + .lifetime = TestOperandLifeTime::SUBGRAPH_OUTPUT, + .numberOfConsumers = 0, + .scale = 0.0078125f, + .type = TestOperandType::TENSOR_QUANT8_ASYMM, + .zeroPoint = 128 + }, { + .channelQuant = {}, + .data = TestBuffer::createFromVector<uint8_t>({245, 247}), + .dimensions = {2, 1}, + .isIgnored = false, + .lifetime = TestOperandLifeTime::SUBGRAPH_INPUT, + .numberOfConsumers = 1, + .scale = 0.904414f, + .type = TestOperandType::TENSOR_QUANT8_ASYMM, + .zeroPoint = 246 + }, { + .channelQuant = {}, + .data = TestBuffer::createFromVector<uint8_t>({246}), + .dimensions = {1}, + .isIgnored = false, + .lifetime = TestOperandLifeTime::CONSTANT_COPY, + .numberOfConsumers = 1, + .scale = 0.904414f, + .type = TestOperandType::TENSOR_QUANT8_ASYMM, + .zeroPoint = 246 + }, { + .channelQuant = {}, + .data = TestBuffer::createFromVector<int32_t>({0}), + .dimensions = {}, + .isIgnored = false, + .lifetime = TestOperandLifeTime::CONSTANT_COPY, + .numberOfConsumers = 1, + .scale = 0.0f, + .type = TestOperandType::INT32, + .zeroPoint = 0 + }}, + .operations = {{ + .inputs = {3, 4, 5}, + .outputs = {0}, + .type = TestOperationType::ADD + }, { + .inputs = {0, 1}, + .outputs = {2}, + .type = TestOperationType::L2_NORMALIZATION + }}, + .outputIndexes = {2} + }, + .minSupportedVersion = TestHalVersion::V1_2, + .referenced = {} + }; + return model; +} + +const auto dummy_test_model_corner_case_dim2_axis1_neg_all_inputs_as_internal = TestModelManager::get().add("l2_normalization_axis_corner_case_dim2_axis1_neg_all_inputs_as_internal", get_test_model_corner_case_dim2_axis1_neg_all_inputs_as_internal()); + +} // namespace generated_tests::l2_normalization_axis + +namespace generated_tests::l2_normalization_axis { + +const TestModel& get_test_model_corner_case_dim1_axis0() { + static TestModel model = { + .expectFailure = false, + .expectedMultinomialDistributionTolerance = 0, + .isRelaxed = false, + .main = { + .inputIndexes = {0}, + .operands = {{ + .channelQuant = {}, + .data = TestBuffer::createFromVector<uint8_t>({245}), + .dimensions = {1}, + .isIgnored = false, + .lifetime = TestOperandLifeTime::SUBGRAPH_INPUT, + .numberOfConsumers = 1, + .scale = 0.904414f, + .type = TestOperandType::TENSOR_QUANT8_ASYMM, + .zeroPoint = 246 + }, { + .channelQuant = {}, + .data = TestBuffer::createFromVector<int32_t>({0}), + .dimensions = {}, + .isIgnored = false, + .lifetime = TestOperandLifeTime::CONSTANT_COPY, + .numberOfConsumers = 1, + .scale = 0.0f, + .type = TestOperandType::INT32, + .zeroPoint = 0 + }, { + .channelQuant = {}, + .data = TestBuffer::createFromVector<uint8_t>({0}), + .dimensions = {1}, + .isIgnored = false, + .lifetime = TestOperandLifeTime::SUBGRAPH_OUTPUT, + .numberOfConsumers = 0, + .scale = 0.0078125f, + .type = TestOperandType::TENSOR_QUANT8_ASYMM, + .zeroPoint = 128 + }}, + .operations = {{ + .inputs = {0, 1}, + .outputs = {2}, + .type = TestOperationType::L2_NORMALIZATION + }}, + .outputIndexes = {2} + }, + .minSupportedVersion = TestHalVersion::V1_2, + .referenced = {} + }; + return model; +} + +const auto dummy_test_model_corner_case_dim1_axis0 = TestModelManager::get().add("l2_normalization_axis_corner_case_dim1_axis0", get_test_model_corner_case_dim1_axis0()); + +} // namespace generated_tests::l2_normalization_axis + +namespace generated_tests::l2_normalization_axis { + +const TestModel& get_test_model_corner_case_dim1_axis0_all_inputs_as_internal() { + static TestModel model = { + .expectFailure = false, + .expectedMultinomialDistributionTolerance = 0, + .isRelaxed = false, + .main = { + .inputIndexes = {3}, + .operands = {{ + .channelQuant = {}, + .data = TestBuffer::createFromVector<uint8_t>({}), + .dimensions = {1}, + .isIgnored = false, + .lifetime = TestOperandLifeTime::TEMPORARY_VARIABLE, + .numberOfConsumers = 1, + .scale = 0.904414f, + .type = TestOperandType::TENSOR_QUANT8_ASYMM, + .zeroPoint = 246 + }, { + .channelQuant = {}, + .data = TestBuffer::createFromVector<int32_t>({0}), + .dimensions = {}, + .isIgnored = false, + .lifetime = TestOperandLifeTime::CONSTANT_COPY, + .numberOfConsumers = 1, + .scale = 0.0f, + .type = TestOperandType::INT32, + .zeroPoint = 0 + }, { + .channelQuant = {}, + .data = TestBuffer::createFromVector<uint8_t>({0}), + .dimensions = {1}, + .isIgnored = false, + .lifetime = TestOperandLifeTime::SUBGRAPH_OUTPUT, + .numberOfConsumers = 0, + .scale = 0.0078125f, + .type = TestOperandType::TENSOR_QUANT8_ASYMM, + .zeroPoint = 128 + }, { + .channelQuant = {}, + .data = TestBuffer::createFromVector<uint8_t>({245}), + .dimensions = {1}, + .isIgnored = false, + .lifetime = TestOperandLifeTime::SUBGRAPH_INPUT, + .numberOfConsumers = 1, + .scale = 0.904414f, + .type = TestOperandType::TENSOR_QUANT8_ASYMM, + .zeroPoint = 246 + }, { + .channelQuant = {}, + .data = TestBuffer::createFromVector<uint8_t>({246}), + .dimensions = {1}, + .isIgnored = false, + .lifetime = TestOperandLifeTime::CONSTANT_COPY, + .numberOfConsumers = 1, + .scale = 0.904414f, + .type = TestOperandType::TENSOR_QUANT8_ASYMM, + .zeroPoint = 246 + }, { + .channelQuant = {}, + .data = TestBuffer::createFromVector<int32_t>({0}), + .dimensions = {}, + .isIgnored = false, + .lifetime = TestOperandLifeTime::CONSTANT_COPY, + .numberOfConsumers = 1, + .scale = 0.0f, + .type = TestOperandType::INT32, + .zeroPoint = 0 + }}, + .operations = {{ + .inputs = {3, 4, 5}, + .outputs = {0}, + .type = TestOperationType::ADD + }, { + .inputs = {0, 1}, + .outputs = {2}, + .type = TestOperationType::L2_NORMALIZATION + }}, + .outputIndexes = {2} + }, + .minSupportedVersion = TestHalVersion::V1_2, + .referenced = {} + }; + return model; +} + +const auto dummy_test_model_corner_case_dim1_axis0_all_inputs_as_internal = TestModelManager::get().add("l2_normalization_axis_corner_case_dim1_axis0_all_inputs_as_internal", get_test_model_corner_case_dim1_axis0_all_inputs_as_internal()); + +} // namespace generated_tests::l2_normalization_axis + +namespace generated_tests::l2_normalization_axis { + +const TestModel& get_test_model_corner_case_dim1_axis0_neg() { + static TestModel model = { + .expectFailure = false, + .expectedMultinomialDistributionTolerance = 0, + .isRelaxed = false, + .main = { + .inputIndexes = {0}, + .operands = {{ + .channelQuant = {}, + .data = TestBuffer::createFromVector<uint8_t>({245}), + .dimensions = {1}, + .isIgnored = false, + .lifetime = TestOperandLifeTime::SUBGRAPH_INPUT, + .numberOfConsumers = 1, + .scale = 0.904414f, + .type = TestOperandType::TENSOR_QUANT8_ASYMM, + .zeroPoint = 246 + }, { + .channelQuant = {}, + .data = TestBuffer::createFromVector<int32_t>({-1}), + .dimensions = {}, + .isIgnored = false, + .lifetime = TestOperandLifeTime::CONSTANT_COPY, + .numberOfConsumers = 1, + .scale = 0.0f, + .type = TestOperandType::INT32, + .zeroPoint = 0 + }, { + .channelQuant = {}, + .data = TestBuffer::createFromVector<uint8_t>({0}), + .dimensions = {1}, + .isIgnored = false, + .lifetime = TestOperandLifeTime::SUBGRAPH_OUTPUT, + .numberOfConsumers = 0, + .scale = 0.0078125f, + .type = TestOperandType::TENSOR_QUANT8_ASYMM, + .zeroPoint = 128 + }}, + .operations = {{ + .inputs = {0, 1}, + .outputs = {2}, + .type = TestOperationType::L2_NORMALIZATION + }}, + .outputIndexes = {2} + }, + .minSupportedVersion = TestHalVersion::V1_2, + .referenced = {} + }; + return model; +} + +const auto dummy_test_model_corner_case_dim1_axis0_neg = TestModelManager::get().add("l2_normalization_axis_corner_case_dim1_axis0_neg", get_test_model_corner_case_dim1_axis0_neg()); + +} // namespace generated_tests::l2_normalization_axis + +namespace generated_tests::l2_normalization_axis { + +const TestModel& get_test_model_corner_case_dim1_axis0_neg_all_inputs_as_internal() { + static TestModel model = { + .expectFailure = false, + .expectedMultinomialDistributionTolerance = 0, + .isRelaxed = false, + .main = { + .inputIndexes = {3}, + .operands = {{ + .channelQuant = {}, + .data = TestBuffer::createFromVector<uint8_t>({}), + .dimensions = {1}, + .isIgnored = false, + .lifetime = TestOperandLifeTime::TEMPORARY_VARIABLE, + .numberOfConsumers = 1, + .scale = 0.904414f, + .type = TestOperandType::TENSOR_QUANT8_ASYMM, + .zeroPoint = 246 + }, { + .channelQuant = {}, + .data = TestBuffer::createFromVector<int32_t>({-1}), + .dimensions = {}, + .isIgnored = false, + .lifetime = TestOperandLifeTime::CONSTANT_COPY, + .numberOfConsumers = 1, + .scale = 0.0f, + .type = TestOperandType::INT32, + .zeroPoint = 0 + }, { + .channelQuant = {}, + .data = TestBuffer::createFromVector<uint8_t>({0}), + .dimensions = {1}, + .isIgnored = false, + .lifetime = TestOperandLifeTime::SUBGRAPH_OUTPUT, + .numberOfConsumers = 0, + .scale = 0.0078125f, + .type = TestOperandType::TENSOR_QUANT8_ASYMM, + .zeroPoint = 128 + }, { + .channelQuant = {}, + .data = TestBuffer::createFromVector<uint8_t>({245}), + .dimensions = {1}, + .isIgnored = false, + .lifetime = TestOperandLifeTime::SUBGRAPH_INPUT, + .numberOfConsumers = 1, + .scale = 0.904414f, + .type = TestOperandType::TENSOR_QUANT8_ASYMM, + .zeroPoint = 246 + }, { + .channelQuant = {}, + .data = TestBuffer::createFromVector<uint8_t>({246}), + .dimensions = {1}, + .isIgnored = false, + .lifetime = TestOperandLifeTime::CONSTANT_COPY, + .numberOfConsumers = 1, + .scale = 0.904414f, + .type = TestOperandType::TENSOR_QUANT8_ASYMM, + .zeroPoint = 246 + }, { + .channelQuant = {}, + .data = TestBuffer::createFromVector<int32_t>({0}), + .dimensions = {}, + .isIgnored = false, + .lifetime = TestOperandLifeTime::CONSTANT_COPY, + .numberOfConsumers = 1, + .scale = 0.0f, + .type = TestOperandType::INT32, + .zeroPoint = 0 + }}, + .operations = {{ + .inputs = {3, 4, 5}, + .outputs = {0}, + .type = TestOperationType::ADD + }, { + .inputs = {0, 1}, + .outputs = {2}, + .type = TestOperationType::L2_NORMALIZATION + }}, + .outputIndexes = {2} + }, + .minSupportedVersion = TestHalVersion::V1_2, + .referenced = {} + }; + return model; +} + +const auto dummy_test_model_corner_case_dim1_axis0_neg_all_inputs_as_internal = TestModelManager::get().add("l2_normalization_axis_corner_case_dim1_axis0_neg_all_inputs_as_internal", get_test_model_corner_case_dim1_axis0_neg_all_inputs_as_internal()); + +} // namespace generated_tests::l2_normalization_axis + diff --git a/nn/runtime/test/generated/spec_V1_3/l2_normalization_zeros.example.cpp b/nn/runtime/test/generated/spec_V1_3/l2_normalization_zeros.example.cpp new file mode 100644 index 000000000..72734f615 --- /dev/null +++ b/nn/runtime/test/generated/spec_V1_3/l2_normalization_zeros.example.cpp @@ -0,0 +1,746 @@ +// Generated from l2_normalization_zeros.mod.py +// DO NOT EDIT +// clang-format off +#include "TestHarness.h" +using namespace test_helper; + +namespace generated_tests::l2_normalization_zeros { + +const TestModel& get_test_model() { + static TestModel model = { + .expectFailure = false, + .expectedMultinomialDistributionTolerance = 0, + .isRelaxed = false, + .main = { + .inputIndexes = {0}, + .operands = {{ + .channelQuant = {}, + .data = TestBuffer::createFromVector<float>({0.0f, 0.0f}), + .dimensions = {2}, + .isIgnored = false, + .lifetime = TestOperandLifeTime::SUBGRAPH_INPUT, + .numberOfConsumers = 1, + .scale = 0.0f, + .type = TestOperandType::TENSOR_FLOAT32, + .zeroPoint = 0 + }, { + .channelQuant = {}, + .data = TestBuffer::createFromVector<int32_t>({-1}), + .dimensions = {}, + .isIgnored = false, + .lifetime = TestOperandLifeTime::CONSTANT_COPY, + .numberOfConsumers = 1, + .scale = 0.0f, + .type = TestOperandType::INT32, + .zeroPoint = 0 + }, { + .channelQuant = {}, + .data = TestBuffer::createFromVector<float>({0.0f, 0.0f}), + .dimensions = {2}, + .isIgnored = false, + .lifetime = TestOperandLifeTime::SUBGRAPH_OUTPUT, + .numberOfConsumers = 0, + .scale = 0.0f, + .type = TestOperandType::TENSOR_FLOAT32, + .zeroPoint = 0 + }}, + .operations = {{ + .inputs = {0, 1}, + .outputs = {2}, + .type = TestOperationType::L2_NORMALIZATION + }}, + .outputIndexes = {2} + }, + .minSupportedVersion = TestHalVersion::V1_2, + .referenced = {} + }; + return model; +} + +const auto dummy_test_model = TestModelManager::get().add("l2_normalization_zeros", get_test_model()); + +} // namespace generated_tests::l2_normalization_zeros + +namespace generated_tests::l2_normalization_zeros { + +const TestModel& get_test_model_all_inputs_as_internal() { + static TestModel model = { + .expectFailure = false, + .expectedMultinomialDistributionTolerance = 0, + .isRelaxed = false, + .main = { + .inputIndexes = {3}, + .operands = {{ + .channelQuant = {}, + .data = TestBuffer::createFromVector<float>({}), + .dimensions = {2}, + .isIgnored = false, + .lifetime = TestOperandLifeTime::TEMPORARY_VARIABLE, + .numberOfConsumers = 1, + .scale = 0.0f, + .type = TestOperandType::TENSOR_FLOAT32, + .zeroPoint = 0 + }, { + .channelQuant = {}, + .data = TestBuffer::createFromVector<int32_t>({-1}), + .dimensions = {}, + .isIgnored = false, + .lifetime = TestOperandLifeTime::CONSTANT_COPY, + .numberOfConsumers = 1, + .scale = 0.0f, + .type = TestOperandType::INT32, + .zeroPoint = 0 + }, { + .channelQuant = {}, + .data = TestBuffer::createFromVector<float>({0.0f, 0.0f}), + .dimensions = {2}, + .isIgnored = false, + .lifetime = TestOperandLifeTime::SUBGRAPH_OUTPUT, + .numberOfConsumers = 0, + .scale = 0.0f, + .type = TestOperandType::TENSOR_FLOAT32, + .zeroPoint = 0 + }, { + .channelQuant = {}, + .data = TestBuffer::createFromVector<float>({0.0f, 0.0f}), + .dimensions = {2}, + .isIgnored = false, + .lifetime = TestOperandLifeTime::SUBGRAPH_INPUT, + .numberOfConsumers = 1, + .scale = 0.0f, + .type = TestOperandType::TENSOR_FLOAT32, + .zeroPoint = 0 + }, { + .channelQuant = {}, + .data = TestBuffer::createFromVector<float>({0.0f}), + .dimensions = {1}, + .isIgnored = false, + .lifetime = TestOperandLifeTime::CONSTANT_COPY, + .numberOfConsumers = 1, + .scale = 0.0f, + .type = TestOperandType::TENSOR_FLOAT32, + .zeroPoint = 0 + }, { + .channelQuant = {}, + .data = TestBuffer::createFromVector<int32_t>({0}), + .dimensions = {}, + .isIgnored = false, + .lifetime = TestOperandLifeTime::CONSTANT_COPY, + .numberOfConsumers = 1, + .scale = 0.0f, + .type = TestOperandType::INT32, + .zeroPoint = 0 + }}, + .operations = {{ + .inputs = {3, 4, 5}, + .outputs = {0}, + .type = TestOperationType::ADD + }, { + .inputs = {0, 1}, + .outputs = {2}, + .type = TestOperationType::L2_NORMALIZATION + }}, + .outputIndexes = {2} + }, + .minSupportedVersion = TestHalVersion::V1_2, + .referenced = {} + }; + return model; +} + +const auto dummy_test_model_all_inputs_as_internal = TestModelManager::get().add("l2_normalization_zeros_all_inputs_as_internal", get_test_model_all_inputs_as_internal()); + +} // namespace generated_tests::l2_normalization_zeros + +namespace generated_tests::l2_normalization_zeros { + +const TestModel& get_test_model_relaxed() { + static TestModel model = { + .expectFailure = false, + .expectedMultinomialDistributionTolerance = 0, + .isRelaxed = true, + .main = { + .inputIndexes = {0}, + .operands = {{ + .channelQuant = {}, + .data = TestBuffer::createFromVector<float>({0.0f, 0.0f}), + .dimensions = {2}, + .isIgnored = false, + .lifetime = TestOperandLifeTime::SUBGRAPH_INPUT, + .numberOfConsumers = 1, + .scale = 0.0f, + .type = TestOperandType::TENSOR_FLOAT32, + .zeroPoint = 0 + }, { + .channelQuant = {}, + .data = TestBuffer::createFromVector<int32_t>({-1}), + .dimensions = {}, + .isIgnored = false, + .lifetime = TestOperandLifeTime::CONSTANT_COPY, + .numberOfConsumers = 1, + .scale = 0.0f, + .type = TestOperandType::INT32, + .zeroPoint = 0 + }, { + .channelQuant = {}, + .data = TestBuffer::createFromVector<float>({0.0f, 0.0f}), + .dimensions = {2}, + .isIgnored = false, + .lifetime = TestOperandLifeTime::SUBGRAPH_OUTPUT, + .numberOfConsumers = 0, + .scale = 0.0f, + .type = TestOperandType::TENSOR_FLOAT32, + .zeroPoint = 0 + }}, + .operations = {{ + .inputs = {0, 1}, + .outputs = {2}, + .type = TestOperationType::L2_NORMALIZATION + }}, + .outputIndexes = {2} + }, + .minSupportedVersion = TestHalVersion::UNKNOWN, + .referenced = {} + }; + return model; +} + +const auto dummy_test_model_relaxed = TestModelManager::get().add("l2_normalization_zeros_relaxed", get_test_model_relaxed()); + +} // namespace generated_tests::l2_normalization_zeros + +namespace generated_tests::l2_normalization_zeros { + +const TestModel& get_test_model_relaxed_all_inputs_as_internal() { + static TestModel model = { + .expectFailure = false, + .expectedMultinomialDistributionTolerance = 0, + .isRelaxed = true, + .main = { + .inputIndexes = {3}, + .operands = {{ + .channelQuant = {}, + .data = TestBuffer::createFromVector<float>({}), + .dimensions = {2}, + .isIgnored = false, + .lifetime = TestOperandLifeTime::TEMPORARY_VARIABLE, + .numberOfConsumers = 1, + .scale = 0.0f, + .type = TestOperandType::TENSOR_FLOAT32, + .zeroPoint = 0 + }, { + .channelQuant = {}, + .data = TestBuffer::createFromVector<int32_t>({-1}), + .dimensions = {}, + .isIgnored = false, + .lifetime = TestOperandLifeTime::CONSTANT_COPY, + .numberOfConsumers = 1, + .scale = 0.0f, + .type = TestOperandType::INT32, + .zeroPoint = 0 + }, { + .channelQuant = {}, + .data = TestBuffer::createFromVector<float>({0.0f, 0.0f}), + .dimensions = {2}, + .isIgnored = false, + .lifetime = TestOperandLifeTime::SUBGRAPH_OUTPUT, + .numberOfConsumers = 0, + .scale = 0.0f, + .type = TestOperandType::TENSOR_FLOAT32, + .zeroPoint = 0 + }, { + .channelQuant = {}, + .data = TestBuffer::createFromVector<float>({0.0f, 0.0f}), + .dimensions = {2}, + .isIgnored = false, + .lifetime = TestOperandLifeTime::SUBGRAPH_INPUT, + .numberOfConsumers = 1, + .scale = 0.0f, + .type = TestOperandType::TENSOR_FLOAT32, + .zeroPoint = 0 + }, { + .channelQuant = {}, + .data = TestBuffer::createFromVector<float>({0.0f}), + .dimensions = {1}, + .isIgnored = false, + .lifetime = TestOperandLifeTime::CONSTANT_COPY, + .numberOfConsumers = 1, + .scale = 0.0f, + .type = TestOperandType::TENSOR_FLOAT32, + .zeroPoint = 0 + }, { + .channelQuant = {}, + .data = TestBuffer::createFromVector<int32_t>({0}), + .dimensions = {}, + .isIgnored = false, + .lifetime = TestOperandLifeTime::CONSTANT_COPY, + .numberOfConsumers = 1, + .scale = 0.0f, + .type = TestOperandType::INT32, + .zeroPoint = 0 + }}, + .operations = {{ + .inputs = {3, 4, 5}, + .outputs = {0}, + .type = TestOperationType::ADD + }, { + .inputs = {0, 1}, + .outputs = {2}, + .type = TestOperationType::L2_NORMALIZATION + }}, + .outputIndexes = {2} + }, + .minSupportedVersion = TestHalVersion::UNKNOWN, + .referenced = {} + }; + return model; +} + +const auto dummy_test_model_relaxed_all_inputs_as_internal = TestModelManager::get().add("l2_normalization_zeros_relaxed_all_inputs_as_internal", get_test_model_relaxed_all_inputs_as_internal()); + +} // namespace generated_tests::l2_normalization_zeros + +namespace generated_tests::l2_normalization_zeros { + +const TestModel& get_test_model_float16() { + static TestModel model = { + .expectFailure = false, + .expectedMultinomialDistributionTolerance = 0, + .isRelaxed = false, + .main = { + .inputIndexes = {0}, + .operands = {{ + .channelQuant = {}, + .data = TestBuffer::createFromVector<_Float16>({0.0f, 0.0f}), + .dimensions = {2}, + .isIgnored = false, + .lifetime = TestOperandLifeTime::SUBGRAPH_INPUT, + .numberOfConsumers = 1, + .scale = 0.0f, + .type = TestOperandType::TENSOR_FLOAT16, + .zeroPoint = 0 + }, { + .channelQuant = {}, + .data = TestBuffer::createFromVector<int32_t>({-1}), + .dimensions = {}, + .isIgnored = false, + .lifetime = TestOperandLifeTime::CONSTANT_COPY, + .numberOfConsumers = 1, + .scale = 0.0f, + .type = TestOperandType::INT32, + .zeroPoint = 0 + }, { + .channelQuant = {}, + .data = TestBuffer::createFromVector<_Float16>({0.0f, 0.0f}), + .dimensions = {2}, + .isIgnored = false, + .lifetime = TestOperandLifeTime::SUBGRAPH_OUTPUT, + .numberOfConsumers = 0, + .scale = 0.0f, + .type = TestOperandType::TENSOR_FLOAT16, + .zeroPoint = 0 + }}, + .operations = {{ + .inputs = {0, 1}, + .outputs = {2}, + .type = TestOperationType::L2_NORMALIZATION + }}, + .outputIndexes = {2} + }, + .minSupportedVersion = TestHalVersion::V1_2, + .referenced = {} + }; + return model; +} + +const auto dummy_test_model_float16 = TestModelManager::get().add("l2_normalization_zeros_float16", get_test_model_float16()); + +} // namespace generated_tests::l2_normalization_zeros + +namespace generated_tests::l2_normalization_zeros { + +const TestModel& get_test_model_float16_all_inputs_as_internal() { + static TestModel model = { + .expectFailure = false, + .expectedMultinomialDistributionTolerance = 0, + .isRelaxed = false, + .main = { + .inputIndexes = {3}, + .operands = {{ + .channelQuant = {}, + .data = TestBuffer::createFromVector<_Float16>({}), + .dimensions = {2}, + .isIgnored = false, + .lifetime = TestOperandLifeTime::TEMPORARY_VARIABLE, + .numberOfConsumers = 1, + .scale = 0.0f, + .type = TestOperandType::TENSOR_FLOAT16, + .zeroPoint = 0 + }, { + .channelQuant = {}, + .data = TestBuffer::createFromVector<int32_t>({-1}), + .dimensions = {}, + .isIgnored = false, + .lifetime = TestOperandLifeTime::CONSTANT_COPY, + .numberOfConsumers = 1, + .scale = 0.0f, + .type = TestOperandType::INT32, + .zeroPoint = 0 + }, { + .channelQuant = {}, + .data = TestBuffer::createFromVector<_Float16>({0.0f, 0.0f}), + .dimensions = {2}, + .isIgnored = false, + .lifetime = TestOperandLifeTime::SUBGRAPH_OUTPUT, + .numberOfConsumers = 0, + .scale = 0.0f, + .type = TestOperandType::TENSOR_FLOAT16, + .zeroPoint = 0 + }, { + .channelQuant = {}, + .data = TestBuffer::createFromVector<_Float16>({0.0f, 0.0f}), + .dimensions = {2}, + .isIgnored = false, + .lifetime = TestOperandLifeTime::SUBGRAPH_INPUT, + .numberOfConsumers = 1, + .scale = 0.0f, + .type = TestOperandType::TENSOR_FLOAT16, + .zeroPoint = 0 + }, { + .channelQuant = {}, + .data = TestBuffer::createFromVector<_Float16>({0.0f}), + .dimensions = {1}, + .isIgnored = false, + .lifetime = TestOperandLifeTime::CONSTANT_COPY, + .numberOfConsumers = 1, + .scale = 0.0f, + .type = TestOperandType::TENSOR_FLOAT16, + .zeroPoint = 0 + }, { + .channelQuant = {}, + .data = TestBuffer::createFromVector<int32_t>({0}), + .dimensions = {}, + .isIgnored = false, + .lifetime = TestOperandLifeTime::CONSTANT_COPY, + .numberOfConsumers = 1, + .scale = 0.0f, + .type = TestOperandType::INT32, + .zeroPoint = 0 + }}, + .operations = {{ + .inputs = {3, 4, 5}, + .outputs = {0}, + .type = TestOperationType::ADD + }, { + .inputs = {0, 1}, + .outputs = {2}, + .type = TestOperationType::L2_NORMALIZATION + }}, + .outputIndexes = {2} + }, + .minSupportedVersion = TestHalVersion::V1_2, + .referenced = {} + }; + return model; +} + +const auto dummy_test_model_float16_all_inputs_as_internal = TestModelManager::get().add("l2_normalization_zeros_float16_all_inputs_as_internal", get_test_model_float16_all_inputs_as_internal()); + +} // namespace generated_tests::l2_normalization_zeros + +namespace generated_tests::l2_normalization_zeros { + +const TestModel& get_test_model_quant8() { + static TestModel model = { + .expectFailure = false, + .expectedMultinomialDistributionTolerance = 0, + .isRelaxed = false, + .main = { + .inputIndexes = {0}, + .operands = {{ + .channelQuant = {}, + .data = TestBuffer::createFromVector<uint8_t>({32, 32}), + .dimensions = {2}, + .isIgnored = false, + .lifetime = TestOperandLifeTime::SUBGRAPH_INPUT, + .numberOfConsumers = 1, + .scale = 0.1f, + .type = TestOperandType::TENSOR_QUANT8_ASYMM, + .zeroPoint = 32 + }, { + .channelQuant = {}, + .data = TestBuffer::createFromVector<int32_t>({-1}), + .dimensions = {}, + .isIgnored = false, + .lifetime = TestOperandLifeTime::CONSTANT_COPY, + .numberOfConsumers = 1, + .scale = 0.0f, + .type = TestOperandType::INT32, + .zeroPoint = 0 + }, { + .channelQuant = {}, + .data = TestBuffer::createFromVector<uint8_t>({128, 128}), + .dimensions = {2}, + .isIgnored = false, + .lifetime = TestOperandLifeTime::SUBGRAPH_OUTPUT, + .numberOfConsumers = 0, + .scale = 0.0078125f, + .type = TestOperandType::TENSOR_QUANT8_ASYMM, + .zeroPoint = 128 + }}, + .operations = {{ + .inputs = {0, 1}, + .outputs = {2}, + .type = TestOperationType::L2_NORMALIZATION + }}, + .outputIndexes = {2} + }, + .minSupportedVersion = TestHalVersion::V1_2, + .referenced = {} + }; + return model; +} + +const auto dummy_test_model_quant8 = TestModelManager::get().add("l2_normalization_zeros_quant8", get_test_model_quant8()); + +} // namespace generated_tests::l2_normalization_zeros + +namespace generated_tests::l2_normalization_zeros { + +const TestModel& get_test_model_quant8_all_inputs_as_internal() { + static TestModel model = { + .expectFailure = false, + .expectedMultinomialDistributionTolerance = 0, + .isRelaxed = false, + .main = { + .inputIndexes = {3}, + .operands = {{ + .channelQuant = {}, + .data = TestBuffer::createFromVector<uint8_t>({}), + .dimensions = {2}, + .isIgnored = false, + .lifetime = TestOperandLifeTime::TEMPORARY_VARIABLE, + .numberOfConsumers = 1, + .scale = 0.1f, + .type = TestOperandType::TENSOR_QUANT8_ASYMM, + .zeroPoint = 32 + }, { + .channelQuant = {}, + .data = TestBuffer::createFromVector<int32_t>({-1}), + .dimensions = {}, + .isIgnored = false, + .lifetime = TestOperandLifeTime::CONSTANT_COPY, + .numberOfConsumers = 1, + .scale = 0.0f, + .type = TestOperandType::INT32, + .zeroPoint = 0 + }, { + .channelQuant = {}, + .data = TestBuffer::createFromVector<uint8_t>({128, 128}), + .dimensions = {2}, + .isIgnored = false, + .lifetime = TestOperandLifeTime::SUBGRAPH_OUTPUT, + .numberOfConsumers = 0, + .scale = 0.0078125f, + .type = TestOperandType::TENSOR_QUANT8_ASYMM, + .zeroPoint = 128 + }, { + .channelQuant = {}, + .data = TestBuffer::createFromVector<uint8_t>({32, 32}), + .dimensions = {2}, + .isIgnored = false, + .lifetime = TestOperandLifeTime::SUBGRAPH_INPUT, + .numberOfConsumers = 1, + .scale = 0.1f, + .type = TestOperandType::TENSOR_QUANT8_ASYMM, + .zeroPoint = 32 + }, { + .channelQuant = {}, + .data = TestBuffer::createFromVector<uint8_t>({32}), + .dimensions = {1}, + .isIgnored = false, + .lifetime = TestOperandLifeTime::CONSTANT_COPY, + .numberOfConsumers = 1, + .scale = 0.1f, + .type = TestOperandType::TENSOR_QUANT8_ASYMM, + .zeroPoint = 32 + }, { + .channelQuant = {}, + .data = TestBuffer::createFromVector<int32_t>({0}), + .dimensions = {}, + .isIgnored = false, + .lifetime = TestOperandLifeTime::CONSTANT_COPY, + .numberOfConsumers = 1, + .scale = 0.0f, + .type = TestOperandType::INT32, + .zeroPoint = 0 + }}, + .operations = {{ + .inputs = {3, 4, 5}, + .outputs = {0}, + .type = TestOperationType::ADD + }, { + .inputs = {0, 1}, + .outputs = {2}, + .type = TestOperationType::L2_NORMALIZATION + }}, + .outputIndexes = {2} + }, + .minSupportedVersion = TestHalVersion::V1_2, + .referenced = {} + }; + return model; +} + +const auto dummy_test_model_quant8_all_inputs_as_internal = TestModelManager::get().add("l2_normalization_zeros_quant8_all_inputs_as_internal", get_test_model_quant8_all_inputs_as_internal()); + +} // namespace generated_tests::l2_normalization_zeros + +namespace generated_tests::l2_normalization_zeros { + +const TestModel& get_test_model_quant8_signed() { + static TestModel model = { + .expectFailure = false, + .expectedMultinomialDistributionTolerance = 0, + .isRelaxed = false, + .main = { + .inputIndexes = {0}, + .operands = {{ + .channelQuant = {}, + .data = TestBuffer::createFromVector<int8_t>({-96, -96}), + .dimensions = {2}, + .isIgnored = false, + .lifetime = TestOperandLifeTime::SUBGRAPH_INPUT, + .numberOfConsumers = 1, + .scale = 0.1f, + .type = TestOperandType::TENSOR_QUANT8_ASYMM_SIGNED, + .zeroPoint = -96 + }, { + .channelQuant = {}, + .data = TestBuffer::createFromVector<int32_t>({-1}), + .dimensions = {}, + .isIgnored = false, + .lifetime = TestOperandLifeTime::CONSTANT_COPY, + .numberOfConsumers = 1, + .scale = 0.0f, + .type = TestOperandType::INT32, + .zeroPoint = 0 + }, { + .channelQuant = {}, + .data = TestBuffer::createFromVector<int8_t>({0, 0}), + .dimensions = {2}, + .isIgnored = false, + .lifetime = TestOperandLifeTime::SUBGRAPH_OUTPUT, + .numberOfConsumers = 0, + .scale = 0.0078125f, + .type = TestOperandType::TENSOR_QUANT8_ASYMM_SIGNED, + .zeroPoint = 0 + }}, + .operations = {{ + .inputs = {0, 1}, + .outputs = {2}, + .type = TestOperationType::L2_NORMALIZATION + }}, + .outputIndexes = {2} + }, + .minSupportedVersion = TestHalVersion::V1_3, + .referenced = {} + }; + return model; +} + +const auto dummy_test_model_quant8_signed = TestModelManager::get().add("l2_normalization_zeros_quant8_signed", get_test_model_quant8_signed()); + +} // namespace generated_tests::l2_normalization_zeros + +namespace generated_tests::l2_normalization_zeros { + +const TestModel& get_test_model_quant8_signed_all_inputs_as_internal() { + static TestModel model = { + .expectFailure = false, + .expectedMultinomialDistributionTolerance = 0, + .isRelaxed = false, + .main = { + .inputIndexes = {3}, + .operands = {{ + .channelQuant = {}, + .data = TestBuffer::createFromVector<int8_t>({}), + .dimensions = {2}, + .isIgnored = false, + .lifetime = TestOperandLifeTime::TEMPORARY_VARIABLE, + .numberOfConsumers = 1, + .scale = 0.1f, + .type = TestOperandType::TENSOR_QUANT8_ASYMM_SIGNED, + .zeroPoint = -96 + }, { + .channelQuant = {}, + .data = TestBuffer::createFromVector<int32_t>({-1}), + .dimensions = {}, + .isIgnored = false, + .lifetime = TestOperandLifeTime::CONSTANT_COPY, + .numberOfConsumers = 1, + .scale = 0.0f, + .type = TestOperandType::INT32, + .zeroPoint = 0 + }, { + .channelQuant = {}, + .data = TestBuffer::createFromVector<int8_t>({0, 0}), + .dimensions = {2}, + .isIgnored = false, + .lifetime = TestOperandLifeTime::SUBGRAPH_OUTPUT, + .numberOfConsumers = 0, + .scale = 0.0078125f, + .type = TestOperandType::TENSOR_QUANT8_ASYMM_SIGNED, + .zeroPoint = 0 + }, { + .channelQuant = {}, + .data = TestBuffer::createFromVector<int8_t>({-96, -96}), + .dimensions = {2}, + .isIgnored = false, + .lifetime = TestOperandLifeTime::SUBGRAPH_INPUT, + .numberOfConsumers = 1, + .scale = 0.1f, + .type = TestOperandType::TENSOR_QUANT8_ASYMM_SIGNED, + .zeroPoint = -96 + }, { + .channelQuant = {}, + .data = TestBuffer::createFromVector<int8_t>({-96}), + .dimensions = {1}, + .isIgnored = false, + .lifetime = TestOperandLifeTime::CONSTANT_COPY, + .numberOfConsumers = 1, + .scale = 0.1f, + .type = TestOperandType::TENSOR_QUANT8_ASYMM_SIGNED, + .zeroPoint = -96 + }, { + .channelQuant = {}, + .data = TestBuffer::createFromVector<int32_t>({0}), + .dimensions = {}, + .isIgnored = false, + .lifetime = TestOperandLifeTime::CONSTANT_COPY, + .numberOfConsumers = 1, + .scale = 0.0f, + .type = TestOperandType::INT32, + .zeroPoint = 0 + }}, + .operations = {{ + .inputs = {3, 4, 5}, + .outputs = {0}, + .type = TestOperationType::ADD + }, { + .inputs = {0, 1}, + .outputs = {2}, + .type = TestOperationType::L2_NORMALIZATION + }}, + .outputIndexes = {2} + }, + .minSupportedVersion = TestHalVersion::V1_3, + .referenced = {} + }; + return model; +} + +const auto dummy_test_model_quant8_signed_all_inputs_as_internal = TestModelManager::get().add("l2_normalization_zeros_quant8_signed_all_inputs_as_internal", get_test_model_quant8_signed_all_inputs_as_internal()); + +} // namespace generated_tests::l2_normalization_zeros + diff --git a/nn/runtime/test/specs/V1_2/l2_normalization_axis.mod.py b/nn/runtime/test/specs/V1_2/l2_normalization_axis.mod.py index ba8e24ad6..24852a697 100644 --- a/nn/runtime/test/specs/V1_2/l2_normalization_axis.mod.py +++ b/nn/runtime/test/specs/V1_2/l2_normalization_axis.mod.py @@ -14,6 +14,7 @@ # limitations under the License. # +# TEST 1: L2_NORMALIZATION with axis parameter i1 = Input("op1", "TENSOR_FLOAT32", "{2, 2, 2, 3}") # input 0 o1 = Output("op2", "TENSOR_FLOAT32", "{2, 2, 2, 3}") # output 0 axis = Int32Scalar("axis", -1) # last axis @@ -45,3 +46,15 @@ example0 = { # All dimensions, with all possible axis parameter Model().Operation("L2_NORMALIZATION", i1, axis).To(o1) Example(example0).AddAllDimsAndAxis(i1, o1, axis).AddVariations("relaxed", "float16", quant8) + + +# TEST 2: Corner cases for TENSOR_QUANT8_ASYMM data type. +i2 = Input("op1", "TENSOR_QUANT8_ASYMM", "{2, 1}, 0.904414f, 246") +o2 = Output("op2", "TENSOR_QUANT8_ASYMM", "{2, 1}, 0.0078125f, 128") +axis = Int32Scalar("axis", -1) # last axis + +Model("corner_case").Operation("L2_NORMALIZATION", i2, axis).To(o2) +Example({ + i2: [245, 247], + o2: [0, 255], +}).AddAllDimsAndAxis(i2, o2, axis) diff --git a/nn/runtime/test/specs/V1_3/l2_normalization_zeros.mod.py b/nn/runtime/test/specs/V1_3/l2_normalization_zeros.mod.py new file mode 100644 index 000000000..6af710795 --- /dev/null +++ b/nn/runtime/test/specs/V1_3/l2_normalization_zeros.mod.py @@ -0,0 +1,41 @@ +# +# Copyright (C) 2020 The Android Open Source Project +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +# Test L2_NORMALIZATION with inputs of all zeros. +i1 = Input("op1", "TENSOR_FLOAT32", "{2}") # input 0 +o1 = Output("op2", "TENSOR_FLOAT32", "{2}") # output 0 +axis = Int32Scalar("axis", -1) # last axis + +quant8 = DataTypeConverter().Identify({ + i1: ("TENSOR_QUANT8_ASYMM", 0.1, 32), + o1: ("TENSOR_QUANT8_ASYMM", 1.0 / 128, 128) +}) + +quant8_signed = DataTypeConverter().Identify({ + i1: ("TENSOR_QUANT8_ASYMM_SIGNED", 0.1, -96), + o1: ("TENSOR_QUANT8_ASYMM_SIGNED", 1.0 / 128, 0) +}) + +Model().IntroducedIn("V1_2").Operation("L2_NORMALIZATION", i1, axis).To(o1) +Example({ + i1: [0, 0], + o1: [0, 0] +}).AddVariations("relaxed", "float16", quant8, quant8_signed) + +# TENSOR_QUANT8_ASYMM_SIGNED is a new data type in V1_3. +Example.SetVersion("V1_3", + "l2_normalization_zeros_quant8_signed", + "l2_normalization_zeros_quant8_signed_all_inputs_as_internal") diff --git a/nn/tools/api/types.spec b/nn/tools/api/types.spec index 9fb72e2af..2c8a522bf 100644 --- a/nn/tools/api/types.spec +++ b/nn/tools/api/types.spec @@ -18,7 +18,7 @@ %define APILevel29 API level 29 %define APILevel30 API level 30 %define BeforeAPILevel29For Before API level 29, for -%define or_1.2 or {@link ANEURALNETWORKS_%{1}} +%define or_1.2 or {@link ANEURALNETWORKS_%{1}} %define-lines AVAIL27 * * Available since API level 27. @@ -97,7 +97,7 @@ %kind hal_1.2 hal_1.3 %define BeforeAPILevel29For Before HAL version 1.2, for -%define or_1.2 or {@link OperandType::%{1}} +%define or_1.2 or {@link OperandType::%{1}} %/kind %kind hal_1.2 @@ -132,7 +132,7 @@ %/kind %kind ndk hal_1.3 -%define AndQuant8Signed +%define AndQuant8Signed %/kind %kind hal_1.0 hal_1.1 hal_1.2 %define AndQuant8Signed @@ -522,7 +522,7 @@ %/kind * * 2: A 1-D tensor, of shape [depth_out], specifying the bias. For input * tensor of type {@link %{OperandTypeLinkPfx}TENSOR_FLOAT32} - * %{or_1.2 TENSOR_FLOAT16}the bias must be of the same type. + * %{or_1.2 TENSOR_FLOAT16} the bias must be of the same type. %kind ndk hal_1.3+ * For filter tensor of {@link %{OperandTypeLinkPfx}TENSOR_QUANT8_ASYMM} * and {@link %{OperandTypeLinkPfx}TENSOR_QUANT8_ASYMM_SIGNED}, @@ -582,7 +582,7 @@ %/kind * * 2: A 1-D tensor, of shape [depth_out], specifying the bias. For input * tensor of type {@link %{OperandTypeLinkPfx}TENSOR_FLOAT32} - * %{or_1.2 TENSOR_FLOAT16}the bias must be of the same + * %{or_1.2 TENSOR_FLOAT16} the bias must be of the same * type. %kind ndk hal_1.3+ * For filter tensor of {@link %{OperandTypeLinkPfx}TENSOR_QUANT8_ASYMM} @@ -706,7 +706,7 @@ %/kind * * 2: A 1-D tensor, of shape [depth_out], specifying the bias. For input * tensor of type {@link %{OperandTypeLinkPfx}TENSOR_FLOAT32} - * %{or_1.2 TENSOR_FLOAT16}the bias must be of the same type. + * %{or_1.2 TENSOR_FLOAT16} the bias must be of the same type. %kind ndk hal_1.3+ * For filter tensor of {@link %{OperandTypeLinkPfx}TENSOR_QUANT8_ASYMM} * and {@link %{OperandTypeLinkPfx}TENSOR_QUANT8_ASYMM_SIGNED}, @@ -761,7 +761,7 @@ * specifying the filter. * * 2: A 1-D tensor, of shape [depth_out], specifying the bias. For input * tensor of type {@link %{OperandTypeLinkPfx}TENSOR_FLOAT32} - * %{or_1.2 TENSOR_FLOAT16}the bias must be of the same type. + * %{or_1.2 TENSOR_FLOAT16} the bias must be of the same type. %kind ndk hal_1.3+ * For filter tensor of {@link %{OperandTypeLinkPfx}TENSOR_QUANT8_ASYMM} * and {@link %{OperandTypeLinkPfx}TENSOR_QUANT8_ASYMM_SIGNED}, @@ -1154,6 +1154,10 @@ %kind ndk hal_1.3+ * For {@link %{OperandTypeLinkPfx}TENSOR_QUANT8_ASYMM_SIGNED}, * the scale must be 1.f / 128 and the zeroPoint must be 0. + * + * NOTE: Before %{APILevel30}, if the elements along an axis are all zeros, + * the result is undefined. Since %{APILevel30}, if the elements along an axis + * are all zeros, the result is logical zero. %/kind %insert-lines AVAIL27 */ |