From 340a16ac5466dbe6c49ca1f6ca686594c9e8aecf Mon Sep 17 00:00:00 2001 From: yair_ehrenwald Date: Fri, 4 Sep 2020 11:48:33 +0300 Subject: [PATCH] Some style changes to splitV. Changed tests to use a single function template. --- tensorflow/lite/micro/kernels/split_v.cc | 270 ++++----- tensorflow/lite/micro/kernels/split_v_test.cc | 544 +++++++----------- 2 files changed, 345 insertions(+), 469 deletions(-) diff --git a/tensorflow/lite/micro/kernels/split_v.cc b/tensorflow/lite/micro/kernels/split_v.cc index 00bf83645d0..600523aba21 100755 --- a/tensorflow/lite/micro/kernels/split_v.cc +++ b/tensorflow/lite/micro/kernels/split_v.cc @@ -1,135 +1,135 @@ -/* Copyright 2018 The TensorFlow Authors. All Rights Reserved. - -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. -==============================================================================*/ - -#include "tensorflow/lite/c/builtin_op_data.h" -#include "tensorflow/lite/c/common.h" -#include "tensorflow/lite/kernels/internal/tensor_ctypes.h" -#include "tensorflow/lite/kernels/kernel_util.h" -#include "tensorflow/lite/kernels/op_macros.h" -#include "tensorflow/lite/micro/kernels/kernel_util.h" - -namespace tflite { -namespace ops { -namespace micro { -namespace split_v { - -template -TfLiteStatus SplitImpl(TfLiteContext* context, TfLiteNode* node, - const TfLiteEvalTensor* input, int axis_value) { - const int output_count = NumOutputs(node); - const TfLiteIntArray* input_dims = input->dims; - const TfLiteEvalTensor* output0 = - tflite::micro::GetEvalOutput(context, node, 0); - const TfLiteIntArray* output_dims = output0->dims; - - const int split_dimensions = input_dims->size; - - TFLITE_DCHECK_LT(axis_value, split_dimensions); - TFLITE_DCHECK_EQ(output_dims->size, split_dimensions); - - int64_t split_size = 0; - for (int i = 0; i < output_count; i++) { - split_size += - tflite::micro::GetEvalOutput(context, node, i)->dims->data[axis_value]; - } - TFLITE_DCHECK_EQ(split_size, input_dims->data[axis_value]); - int64_t outer_size = 1; - for (int i = 0; i < axis_value; ++i) { - outer_size *= input_dims->data[i]; - } - - int64_t base_inner_size = 1; - for (int i = axis_value + 1; i < split_dimensions; ++i) { - base_inner_size *= input_dims->data[i]; - } - - const T* input_ptr = tflite::micro::GetTensorData(input); - for (int k = 0; k < outer_size; ++k) { - for (int i = 0; i < output_count; ++i) { - TfLiteEvalTensor* t = tflite::micro::GetEvalOutput(context, node, i); - T* output_data = tflite::micro::GetTensorData(t); - output_dims = t->dims; - const int copy_size = output_dims->data[axis_value] * base_inner_size; - T* output_ptr = output_data + k * copy_size; - for (int j = 0; j < copy_size; ++j) output_ptr[j] = input_ptr[j]; - input_ptr += copy_size; - } - } - - return kTfLiteOk; -} - -TfLiteStatus Prepare(TfLiteContext* context, TfLiteNode* node) { - TF_LITE_ENSURE_EQ(context, NumInputs(node), 3); - - // Dynamic output tensors are needed if axis tensor is not constant. - // But Micro doesn't support dynamic memory allocation, so we only support - // constant axis tensor for now. - const TfLiteTensor* axis = GetInput(context, node, 2); - TF_LITE_ENSURE_MSG(context, IsConstantTensor(axis), - "Non constant axis tensor not supported"); - - return kTfLiteOk; -} - -TfLiteStatus Eval(TfLiteContext* context, TfLiteNode* node) { - const TfLiteEvalTensor* input = tflite::micro::GetEvalInput(context, node, 0); - const TfLiteEvalTensor* axis = tflite::micro::GetEvalInput(context, node, 2); - - int axis_value = tflite::micro::GetTensorData(axis)[0]; - if (axis_value < 0) { - axis_value += input->dims->size; - } - - TF_LITE_ENSURE(context, axis_value >= 0); - TF_LITE_ENSURE(context, axis_value < input->dims->size); - - switch (input->type) { - case kTfLiteFloat32: { - return SplitImpl(context, node, input, axis_value); - } - case kTfLiteInt8: { - return SplitImpl(context, node, input, axis_value); - } - case kTfLiteInt16: { - return SplitImpl(context, node, input, axis_value); - } - case kTfLiteInt32: { - return SplitImpl(context, node, input, axis_value); - } - default: - TF_LITE_KERNEL_LOG(context, "Type %s currently not supported.", - TfLiteTypeGetName(input->type)); - return kTfLiteError; - } - return kTfLiteOk; -} - -} // namespace split_v - -TfLiteRegistration Register_SPLIT_V() { - return {/*init=*/nullptr, - /*free=*/nullptr, - /*prepare=*/split_v::Prepare, - /*invoke=*/split_v::Eval, - /*profiling_string=*/nullptr, - /*builtin_code=*/0, - /*custom_name=*/nullptr, - /*version=*/0}; -} - -} // namespace micro -} // namespace ops -} // namespace tflite +/* Copyright 2018 The TensorFlow Authors. All Rights Reserved. + +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. +==============================================================================*/ + +#include "tensorflow/lite/c/builtin_op_data.h" +#include "tensorflow/lite/c/common.h" +#include "tensorflow/lite/kernels/internal/tensor_ctypes.h" +#include "tensorflow/lite/kernels/kernel_util.h" +#include "tensorflow/lite/kernels/op_macros.h" +#include "tensorflow/lite/micro/kernels/kernel_util.h" + +namespace tflite { +namespace ops { +namespace micro { +namespace split_v { + +template +TfLiteStatus SplitImpl(TfLiteContext* context, TfLiteNode* node, + const TfLiteEvalTensor* input, int axis_value) { + const TfLiteIntArray* input_dims = input->dims; + const TfLiteEvalTensor* output0 = + tflite::micro::GetEvalOutput(context, node, 0); + + const int split_dimensions = input_dims->size; + + TFLITE_DCHECK_LT(axis_value, split_dimensions); + TFLITE_DCHECK_EQ(output0->dims->size, split_dimensions); + + int64_t split_size = 0; + const int output_count = NumOutputs(node); + for (int i = 0; i < output_count; i++) { + split_size += + tflite::micro::GetEvalOutput(context, node, i)->dims->data[axis_value]; + } + TFLITE_DCHECK_EQ(split_size, input_dims->data[axis_value]); + int64_t outer_size = 1; + for (int i = 0; i < axis_value; ++i) { + outer_size *= input_dims->data[i]; + } + + int64_t base_inner_size = 1; + for (int i = axis_value + 1; i < split_dimensions; ++i) { + base_inner_size *= input_dims->data[i]; + } + + const T* input_ptr = tflite::micro::GetTensorData(input); + for (int k = 0; k < outer_size; ++k) { + for (int i = 0; i < output_count; ++i) { + TfLiteEvalTensor* output_tensor = + tflite::micro::GetEvalOutput(context, node, i); + T* output_data = tflite::micro::GetTensorData(output_tensor); + const int copy_size = + output_tensor->dims->data[axis_value] * base_inner_size; + T* output_ptr = output_data + k * copy_size; + for (int j = 0; j < copy_size; ++j) output_ptr[j] = input_ptr[j]; + input_ptr += copy_size; + } + } + + return kTfLiteOk; +} + +TfLiteStatus Prepare(TfLiteContext* context, TfLiteNode* node) { + TF_LITE_ENSURE_EQ(context, NumInputs(node), 3); + + // Dynamic output tensors are needed if axis tensor is not constant. + // But Micro doesn't support dynamic memory allocation, so we only support + // constant axis tensor for now. + const TfLiteTensor* axis = GetInput(context, node, 2); + TF_LITE_ENSURE_MSG(context, IsConstantTensor(axis), + "Non constant axis tensor not supported"); + + return kTfLiteOk; +} + +TfLiteStatus Eval(TfLiteContext* context, TfLiteNode* node) { + const TfLiteEvalTensor* input = tflite::micro::GetEvalInput(context, node, 0); + const TfLiteEvalTensor* axis = tflite::micro::GetEvalInput(context, node, 2); + + int axis_value = tflite::micro::GetTensorData(axis)[0]; + if (axis_value < 0) { + axis_value += input->dims->size; + } + + TF_LITE_ENSURE(context, axis_value >= 0); + TF_LITE_ENSURE(context, axis_value < input->dims->size); + + switch (input->type) { + case kTfLiteFloat32: { + return SplitImpl(context, node, input, axis_value); + } + case kTfLiteInt8: { + return SplitImpl(context, node, input, axis_value); + } + case kTfLiteInt16: { + return SplitImpl(context, node, input, axis_value); + } + case kTfLiteInt32: { + return SplitImpl(context, node, input, axis_value); + } + default: + TF_LITE_KERNEL_LOG(context, "Type %s currently not supported.", + TfLiteTypeGetName(input->type)); + return kTfLiteError; + } + return kTfLiteOk; +} + +} // namespace split_v + +TfLiteRegistration Register_SPLIT_V() { + return {/*init=*/nullptr, + /*free=*/nullptr, + /*prepare=*/split_v::Prepare, + /*invoke=*/split_v::Eval, + /*profiling_string=*/nullptr, + /*builtin_code=*/0, + /*custom_name=*/nullptr, + /*version=*/0}; +} + +} // namespace micro +} // namespace ops +} // namespace tflite diff --git a/tensorflow/lite/micro/kernels/split_v_test.cc b/tensorflow/lite/micro/kernels/split_v_test.cc index fb7382f2232..1cd6642d60c 100755 --- a/tensorflow/lite/micro/kernels/split_v_test.cc +++ b/tensorflow/lite/micro/kernels/split_v_test.cc @@ -24,42 +24,36 @@ limitations under the License. namespace tflite { namespace testing { -void TestSplitVThreeOutputsFloat( - const int* input_dims_data, const float* input_data, - const int* axis_dims_data, const int* axis_data, const int* split_dims_data, - const int* split_data, const int* output1_dims_data, - const float* expected_output1_data, const int* output2_dims_data, - const float* expected_output2_data, const int* output3_dims_data, - const float* expected_output3_data, float* output1_data, - float* output2_data, float* output3_data) { +template +struct OutputTensors { + float* data[N]; + int* dims[N]; + float* expected_output_data[N]; +}; +template +void TestSplitVFloat(const int* input_dims_data, const float* input_data, + const int* axis_dims_data, const int* axis_data, + const int* split_dims_data, const int* split_data, + const OutputTensors& output_tensors) { TfLiteIntArray* input_dims = IntArrayFromInts(input_dims_data); TfLiteIntArray* axis_dims = IntArrayFromInts(axis_dims_data); TfLiteIntArray* split_dims = IntArrayFromInts(split_dims_data); - TfLiteIntArray* output1_dims = IntArrayFromInts(output1_dims_data); - TfLiteIntArray* output2_dims = IntArrayFromInts(output2_dims_data); - TfLiteIntArray* output3_dims = IntArrayFromInts(output3_dims_data); - - const int output1_dims_count = ElementCount(*output1_dims); - const int output2_dims_count = ElementCount(*output2_dims); - const int output3_dims_count = ElementCount(*output3_dims); + TfLiteIntArray* output_dims[N]; + for (int i = 0; i < N; i++) + output_dims[i] = IntArrayFromInts(output_tensors.dims[i]); // Place a unique value in the uninitialized output buffer. - for (int i = 0; i < output1_dims_count; ++i) { - output1_data[i] = 23; + for (int i = 0; i < N; i++) { + int dim_count = ElementCount(*output_dims[i]); + for (int j = 0; j < dim_count; j++) { + (output_tensors.data[i])[j] = 23; + } } - for (int i = 0; i < output2_dims_count; ++i) { - output2_data[i] = 23; - } - for (int i = 0; i < output3_dims_count; ++i) { - output3_data[i] = 23; - } - constexpr int input_size = 1; constexpr int axis_size = 1; constexpr int split_size = 1; - constexpr int output_size = 3; + constexpr int output_size = N; - TfLiteContext context; constexpr int tensors_size = input_size + output_size + axis_size + split_size; @@ -68,27 +62,26 @@ void TestSplitVThreeOutputsFloat( // third is axis // then come outputs - TfLiteTensor tensors[tensors_size] = { + TfLiteTensor tensors[tensors_size]; + tensors[0] = CreateFloatTensor(input_data, input_dims); + tensors[1] = CreateQuantized32Tensor(split_data, split_dims, 1.0); + tensors[2] = CreateQuantized32Tensor(axis_data, axis_dims, 1.0); - CreateFloatTensor(input_data, input_dims), - CreateQuantized32Tensor(split_data, split_dims, 1.0), - CreateQuantized32Tensor(axis_data, axis_dims, 1.0), + // add output tensors + for (int i = 0; i < N; i++) + tensors[3 + i] = CreateFloatTensor(output_tensors.data[i], output_dims[i]); - // outputs - CreateFloatTensor(output1_data, output1_dims), - CreateFloatTensor(output2_data, output2_dims), - CreateFloatTensor(output3_data, output3_dims) - - }; tensors[2].allocation_type = kTfLiteMmapRo; tensors[1].allocation_type = kTfLiteMmapRo; void* user_data = nullptr; TfLiteSplitVParams builtin; - builtin.num_splits = 3; + builtin.num_splits = N; int inputs_array_data[] = {3, 0, 1, 2}; TfLiteIntArray* inputs_array = IntArrayFromInts(inputs_array_data); - int outputs_array_data[] = {3, 3, 4, 5}; + int outputs_array_data[N + 1]; + outputs_array_data[0] = N; + for (int i = 0; i < N; i++) outputs_array_data[i + 1] = i + 3; TfLiteIntArray* outputs_array = IntArrayFromInts(outputs_array_data); TfLiteIntArray* temporaries_array = IntArrayFromInts({0}); @@ -109,242 +102,12 @@ void TestSplitVThreeOutputsFloat( TF_LITE_MICRO_EXPECT_EQ(kTfLiteOk, runner.InitAndPrepare()); TF_LITE_MICRO_EXPECT_EQ(kTfLiteOk, runner.Invoke()); - for (int i = 0; i < output1_dims_count; ++i) { - TF_LITE_MICRO_EXPECT_NEAR(expected_output1_data[i], output1_data[i], 1e-5f); - } - for (int i = 0; i < output2_dims_count; ++i) { - TF_LITE_MICRO_EXPECT_NEAR(expected_output2_data[i], output2_data[i], 1e-5f); - } - for (int i = 0; i < output3_dims_count; ++i) { - TF_LITE_MICRO_EXPECT_NEAR(expected_output3_data[i], output3_data[i], 1e-5f); - } -} - -void TestSplitVTwoOutputsFloat( - const int* input_dims_data, const float* input_data, - const int* axis_dims_data, const int* axis_data, const int* split_dims_data, - const int* size_splits_data, const int* output1_dims_data, - const float* expected_output1_data, const int* output2_dims_data, - const float* expected_output2_data, float* output1_data, - float* output2_data) { - TfLiteIntArray* input_dims = IntArrayFromInts(input_dims_data); - TfLiteIntArray* axis_dims = IntArrayFromInts(axis_dims_data); - TfLiteIntArray* output1_dims = IntArrayFromInts(output1_dims_data); - TfLiteIntArray* output2_dims = IntArrayFromInts(output2_dims_data); - TfLiteIntArray* size_splits_dims = IntArrayFromInts(split_dims_data); - - const int output1_dims_count = ElementCount(*output1_dims); - const int output2_dims_count = ElementCount(*output2_dims); - - constexpr int input_size = 1; - constexpr int output_size = 2; - constexpr int axis_size = 1; - constexpr int split_size = 1; - constexpr int tensors_size = - input_size + output_size + axis_size + split_size; - TfLiteTensor tensors[tensors_size] = { - CreateFloatTensor(input_data, input_dims), - CreateQuantized32Tensor(size_splits_data, size_splits_dims, 1.0), - CreateQuantized32Tensor(axis_data, axis_dims, 1.0), - CreateFloatTensor(output1_data, output1_dims), - CreateFloatTensor(output2_data, output2_dims)}; - - // Currently only support constant axis tensor. - - tensors[1].allocation_type = kTfLiteMmapRo; - tensors[2].allocation_type = kTfLiteMmapRo; - - // Place a unique value in the uninitialized output buffer. - for (int i = 0; i < output1_dims_count; ++i) { - output1_data[i] = 23; - } - - for (int i = 0; i < output2_dims_count; ++i) { - output2_data[i] = 23; - } - - TfLiteSplitVParams builtin_data; - builtin_data.num_splits = 2; - - void* user_data = nullptr; - - int inputs_array_data[] = {3, 0, 1, 2}; - TfLiteIntArray* inputs_array = IntArrayFromInts(inputs_array_data); - int outputs_array_data[] = {2, 3, 4}; - TfLiteIntArray* outputs_array = IntArrayFromInts(outputs_array_data); - TfLiteIntArray* temporaries_array = IntArrayFromInts({0}); - - TfLiteNode node; - node.inputs = inputs_array; - node.outputs = outputs_array; - // node.temporaries = temporaries_array; - node.user_data = user_data; - node.builtin_data = reinterpret_cast(&builtin_data); - node.custom_initial_data = nullptr; - node.custom_initial_data_size = 0; - - const TfLiteRegistration registration = - tflite::ops::micro::Register_SPLIT_V(); - micro::KernelRunner runner(registration, tensors, tensors_size, inputs_array, - outputs_array, nullptr, micro_test::reporter); - - TF_LITE_MICRO_EXPECT_EQ(kTfLiteOk, runner.InitAndPrepare()); - TF_LITE_MICRO_EXPECT_EQ(kTfLiteOk, runner.Invoke()); - - for (int i = 0; i < output1_dims_count; ++i) { - TF_LITE_MICRO_EXPECT_NEAR(expected_output1_data[i], output1_data[i], 1e-5f); - } - - for (int i = 0; i < output2_dims_count; ++i) { - TF_LITE_MICRO_EXPECT_NEAR(expected_output2_data[i], output2_data[i], 1e-5f); - } -} -void TestSplitVEightOutputsFloat( - - const int* input_dims_data, const float* input_data, - const int* axis_dims_data, const int* axis_data, const int* split_dims_data, - const int* size_splits_data, const int* output1_dims_data, - const float* expected_output1_data, const int* output2_dims_data, - const float* expected_output2_data, const int* output3_dims_data, - const float* expected_output3_data, const int* output4_dims_data, - const float* expected_output4_data, const int* output5_dims_data, - const float* expected_output5_data, const int* output6_dims_data, - const float* expected_output6_data, const int* output7_dims_data, - const float* expected_output7_data, const int* output8_dims_data, - const float* expected_output8_data, - - float* output1_data, float* output2_data, float* output3_data, - float* output4_data, float* output5_data, float* output6_data, - float* output7_data, float* output8_data) { - TfLiteIntArray* input_dims = IntArrayFromInts(input_dims_data); - TfLiteIntArray* axis_dims = IntArrayFromInts(axis_dims_data); - TfLiteIntArray* output1_dims = IntArrayFromInts(output1_dims_data); - TfLiteIntArray* output2_dims = IntArrayFromInts(output2_dims_data); - TfLiteIntArray* output3_dims = IntArrayFromInts(output3_dims_data); - TfLiteIntArray* output4_dims = IntArrayFromInts(output4_dims_data); - TfLiteIntArray* output5_dims = IntArrayFromInts(output5_dims_data); - TfLiteIntArray* output6_dims = IntArrayFromInts(output6_dims_data); - TfLiteIntArray* output7_dims = IntArrayFromInts(output7_dims_data); - TfLiteIntArray* output8_dims = IntArrayFromInts(output8_dims_data); - - TfLiteIntArray* size_splits_dims = IntArrayFromInts(split_dims_data); - - const int output1_dims_count = ElementCount(*output1_dims); - const int output2_dims_count = ElementCount(*output2_dims); - const int output3_dims_count = ElementCount(*output3_dims); - const int output4_dims_count = ElementCount(*output4_dims); - const int output5_dims_count = ElementCount(*output5_dims); - const int output6_dims_count = ElementCount(*output6_dims); - const int output7_dims_count = ElementCount(*output7_dims); - const int output8_dims_count = ElementCount(*output8_dims); - - constexpr int input_size = 1; - constexpr int output_size = 8; - constexpr int axis_size = 1; - constexpr int split_size = 1; - constexpr int tensors_size = - input_size + output_size + axis_size + split_size; - TfLiteTensor tensors[tensors_size] = { - - CreateFloatTensor(input_data, input_dims), - CreateQuantized32Tensor(size_splits_data, size_splits_dims, 1.0), - CreateQuantized32Tensor(axis_data, axis_dims, 1.0), - CreateFloatTensor(output1_data, output1_dims), - CreateFloatTensor(output2_data, output2_dims), - CreateFloatTensor(output3_data, output3_dims), - CreateFloatTensor(output4_data, output4_dims), - CreateFloatTensor(output5_data, output5_dims), - CreateFloatTensor(output6_data, output6_dims), - CreateFloatTensor(output7_data, output7_dims), - CreateFloatTensor(output8_data, output8_dims)}; - - // Currently only support constant axis tensor. - tensors[1].allocation_type = kTfLiteMmapRo; - tensors[2].allocation_type = kTfLiteMmapRo; - - // Place a unique value in the uninitialized output buffer. - for (int i = 0; i < output1_dims_count; ++i) { - output1_data[i] = 23; - } - - for (int i = 0; i < output2_dims_count; ++i) { - output2_data[i] = 23; - } - for (int i = 0; i < output3_dims_count; ++i) { - output3_data[i] = 23; - } - - for (int i = 0; i < output4_dims_count; ++i) { - output4_data[i] = 23; - } - for (int i = 0; i < output5_dims_count; ++i) { - output5_data[i] = 23; - } - - for (int i = 0; i < output6_dims_count; ++i) { - output6_data[i] = 23; - } - for (int i = 0; i < output7_dims_count; ++i) { - output7_data[i] = 23; - } - - for (int i = 0; i < output8_dims_count; ++i) { - output8_data[i] = 23; - } - - TfLiteSplitVParams builtin_data; - builtin_data.num_splits = 8; - - int inputs_array_data[] = {3, 0, 1, 2}; - TfLiteIntArray* inputs_array = IntArrayFromInts(inputs_array_data); - int outputs_array_data[] = {8, 3, 4, 5, 6, 7, 8, 9, 10}; - TfLiteIntArray* outputs_array = IntArrayFromInts(outputs_array_data); - TfLiteIntArray* temporaries_array = IntArrayFromInts({0}); - void* user_data = nullptr; - TfLiteNode node; - node.inputs = inputs_array; - node.outputs = outputs_array; - - node.user_data = user_data; - node.builtin_data = reinterpret_cast(&builtin_data); - node.custom_initial_data = nullptr; - node.custom_initial_data_size = 0; - - const TfLiteRegistration registration = - tflite::ops::micro::Register_SPLIT_V(); - micro::KernelRunner runner(registration, tensors, tensors_size, inputs_array, - outputs_array, nullptr, micro_test::reporter); - - TF_LITE_MICRO_EXPECT_EQ(kTfLiteOk, runner.InitAndPrepare()); - TF_LITE_MICRO_EXPECT_EQ(kTfLiteOk, runner.Invoke()); - - for (int i = 0; i < output1_dims_count; ++i) { - TF_LITE_MICRO_EXPECT_NEAR(expected_output1_data[i], output1_data[i], 1e-5f); - } - - for (int i = 0; i < output2_dims_count; ++i) { - TF_LITE_MICRO_EXPECT_NEAR(expected_output2_data[i], output2_data[i], 1e-5f); - } - for (int i = 0; i < output3_dims_count; ++i) { - TF_LITE_MICRO_EXPECT_NEAR(expected_output3_data[i], output3_data[i], 1e-5f); - } - - for (int i = 0; i < output4_dims_count; ++i) { - TF_LITE_MICRO_EXPECT_NEAR(expected_output4_data[i], output4_data[i], 1e-5f); - } - for (int i = 0; i < output5_dims_count; ++i) { - TF_LITE_MICRO_EXPECT_NEAR(expected_output5_data[i], output5_data[i], 1e-5f); - } - - for (int i = 0; i < output6_dims_count; ++i) { - TF_LITE_MICRO_EXPECT_NEAR(expected_output6_data[i], output6_data[i], 1e-5f); - } - for (int i = 0; i < output7_dims_count; ++i) { - TF_LITE_MICRO_EXPECT_NEAR(expected_output7_data[i], output7_data[i], 1e-5f); - } - - for (int i = 0; i < output8_dims_count; ++i) { - TF_LITE_MICRO_EXPECT_NEAR(expected_output8_data[i], output8_data[i], 1e-5f); + for (int i = 0; i < N; i++) { + int dim_count = ElementCount(*output_dims[i]); + for (int j = 0; j < dim_count; j++) { + TF_LITE_MICRO_EXPECT_NEAR((output_tensors.expected_output_data[i])[j], + (output_tensors.data[i])[j], 1e-5f); + } } } @@ -372,11 +135,23 @@ TF_LITE_MICRO_TEST(SPLIT_V_ThreeOutputs) { float output2_values[] = {4, 5, 6}; int output3_shape[] = {2, 2, 3}; float output3_values[] = {7, 8, 9, 10, 11, 12}; - tflite::testing::TestSplitVThreeOutputsFloat( - input_shape, input_values, axis_shape, axis_values, split_shape, - split_values, output1_shape, output1_values, output2_shape, - output2_values, output3_shape, output3_values, output1_data, output2_data, - output3_data); + + tflite::testing::OutputTensors<3> output_tensors; + output_tensors.data[0] = output1_data; + output_tensors.data[1] = output2_data; + output_tensors.data[2] = output3_data; + + output_tensors.dims[0] = output1_shape; + output_tensors.dims[1] = output2_shape; + output_tensors.dims[2] = output3_shape; + + output_tensors.expected_output_data[0] = output1_values; + output_tensors.expected_output_data[1] = output2_values; + output_tensors.expected_output_data[2] = output3_values; + + tflite::testing::TestSplitVFloat(input_shape, input_values, axis_shape, + axis_values, split_shape, split_values, + output_tensors); } TF_LITE_MICRO_TEST(SPLIT_V_FourDimensionalFloatAxis0) { @@ -389,17 +164,28 @@ TF_LITE_MICRO_TEST(SPLIT_V_FourDimensionalFloatAxis0) { float input_values[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16}; int axis_shape[] = {1, 1}; - int axis_value[] = {0}; - int split_size_shape[] = {1, 2}; - int split_data[] = {1, 1}; + int axis_values[] = {0}; + int split_shape[] = {1, 2}; + int split_values[] = {1, 1}; int output1_shape[] = {4, 1, 2, 2, 2}; float output1_values[] = {1, 2, 3, 4, 5, 6, 7, 8}; int output2_shape[] = {4, 1, 2, 2, 2}; float output2_values[] = {9, 10, 11, 12, 13, 14, 15, 16}; - tflite::testing::TestSplitVTwoOutputsFloat( - input_shape, input_values, axis_shape, axis_value, split_size_shape, - split_data, output1_shape, output1_values, output2_shape, output2_values, - output1_data, output2_data); + + tflite::testing::OutputTensors<2> output_tensors; + + output_tensors.data[0] = output1_data; + output_tensors.data[1] = output2_data; + + output_tensors.dims[0] = output1_shape; + output_tensors.dims[1] = output2_shape; + + output_tensors.expected_output_data[0] = output1_values; + output_tensors.expected_output_data[1] = output2_values; + + tflite::testing::TestSplitVFloat(input_shape, input_values, axis_shape, + axis_values, split_shape, split_values, + output_tensors); } TF_LITE_MICRO_TEST(SPLIT_V_FourDimensionalFloatAxis1) { @@ -412,17 +198,28 @@ TF_LITE_MICRO_TEST(SPLIT_V_FourDimensionalFloatAxis1) { float input_values[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16}; int axis_shape[] = {1, 1}; - int axis_value[] = {1}; - int split_size_shape[] = {1, 2}; - int split_data[] = {1, 1}; + int axis_values[] = {1}; + int split_shape[] = {1, 2}; + int split_values[] = {1, 1}; int output1_shape[] = {4, 2, 1, 2, 2}; float output1_values[] = {1, 2, 3, 4, 9, 10, 11, 12}; int output2_shape[] = {4, 2, 1, 2, 2}; float output2_values[] = {5, 6, 7, 8, 13, 14, 15, 16}; - tflite::testing::TestSplitVTwoOutputsFloat( - input_shape, input_values, axis_shape, axis_value, split_size_shape, - split_data, output1_shape, output1_values, output2_shape, output2_values, - output1_data, output2_data); + + tflite::testing::OutputTensors<2> output_tensors; + + output_tensors.data[0] = output1_data; + output_tensors.data[1] = output2_data; + + output_tensors.dims[0] = output1_shape; + output_tensors.dims[1] = output2_shape; + + output_tensors.expected_output_data[0] = output1_values; + output_tensors.expected_output_data[1] = output2_values; + + tflite::testing::TestSplitVFloat(input_shape, input_values, axis_shape, + axis_values, split_shape, split_values, + output_tensors); } TF_LITE_MICRO_TEST(SPLIT_VFourDimensionalFloatAxis2) { @@ -435,17 +232,28 @@ TF_LITE_MICRO_TEST(SPLIT_VFourDimensionalFloatAxis2) { float input_values[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16}; int axis_shape[] = {1, 1}; - int axis_value[] = {2}; - int split_size_shape[] = {1, 2}; - int split_data[] = {1, 1}; + int axis_values[] = {2}; + int split_shape[] = {1, 2}; + int split_values[] = {1, 1}; int output1_shape[] = {4, 2, 2, 1, 2}; float output1_values[] = {1, 2, 5, 6, 9, 10, 13, 14}; int output2_shape[] = {4, 2, 2, 1, 2}; float output2_values[] = {3, 4, 7, 8, 11, 12, 15, 16}; - tflite::testing::TestSplitVTwoOutputsFloat( - input_shape, input_values, axis_shape, axis_value, split_size_shape, - split_data, output1_shape, output1_values, output2_shape, output2_values, - output1_data, output2_data); + + tflite::testing::OutputTensors<2> output_tensors; + + output_tensors.data[0] = output1_data; + output_tensors.data[1] = output2_data; + + output_tensors.dims[0] = output1_shape; + output_tensors.dims[1] = output2_shape; + + output_tensors.expected_output_data[0] = output1_values; + output_tensors.expected_output_data[1] = output2_values; + + tflite::testing::TestSplitVFloat(input_shape, input_values, axis_shape, + axis_values, split_shape, split_values, + output_tensors); } TF_LITE_MICRO_TEST(SPLIT_V_FourDimensionalFloatAxis3) { @@ -457,17 +265,28 @@ TF_LITE_MICRO_TEST(SPLIT_V_FourDimensionalFloatAxis3) { float input_values[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16}; int axis_shape[] = {1, 1}; - int axis_value[] = {3}; - int split_size_shape[] = {1, 2}; - int split_data[] = {1, 1}; + int axis_values[] = {3}; + int split_shape[] = {1, 2}; + int split_values[] = {1, 1}; int output1_shape[] = {4, 2, 2, 2, 1}; float output1_values[] = {1, 3, 5, 7, 9, 11, 13, 15}; int output2_shape[] = {4, 2, 2, 2, 1}; float output2_values[] = {2, 4, 6, 8, 10, 12, 14, 16}; - tflite::testing::TestSplitVTwoOutputsFloat( - input_shape, input_values, axis_shape, axis_value, split_size_shape, - split_data, output1_shape, output1_values, output2_shape, output2_values, - output1_data, output2_data); + + tflite::testing::OutputTensors<2> output_tensors; + + output_tensors.data[0] = output1_data; + output_tensors.data[1] = output2_data; + + output_tensors.dims[0] = output1_shape; + output_tensors.dims[1] = output2_shape; + + output_tensors.expected_output_data[0] = output1_values; + output_tensors.expected_output_data[1] = output2_values; + + tflite::testing::TestSplitVFloat(input_shape, input_values, axis_shape, + axis_values, split_shape, split_values, + output_tensors); } TF_LITE_MICRO_TEST(SPLIT_V_FourDimensionalFloatNegativeAxis) { @@ -480,17 +299,28 @@ TF_LITE_MICRO_TEST(SPLIT_V_FourDimensionalFloatNegativeAxis) { float input_values[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16}; int axis_shape[] = {1, 1}; - int axis_value[] = {-4}; - int split_size_shape[] = {1, 2}; - int split_data[] = {1, 1}; + int axis_values[] = {-4}; + int split_shape[] = {1, 2}; + int split_values[] = {1, 1}; int output1_shape[] = {4, 1, 2, 2, 2}; float output1_values[] = {1, 2, 3, 4, 5, 6, 7, 8}; int output2_shape[] = {4, 1, 2, 2, 2}; float output2_values[] = {9, 10, 11, 12, 13, 14, 15, 16}; - tflite::testing::TestSplitVTwoOutputsFloat( - input_shape, input_values, axis_shape, axis_value, split_size_shape, - split_data, output1_shape, output1_values, output2_shape, output2_values, - output1_data, output2_data); + + tflite::testing::OutputTensors<2> output_tensors; + + output_tensors.data[0] = output1_data; + output_tensors.data[1] = output2_data; + + output_tensors.dims[0] = output1_shape; + output_tensors.dims[1] = output2_shape; + + output_tensors.expected_output_data[0] = output1_values; + output_tensors.expected_output_data[1] = output2_values; + + tflite::testing::TestSplitVFloat(input_shape, input_values, axis_shape, + axis_values, split_shape, split_values, + output_tensors); } TF_LITE_MICRO_TEST(SPLIT_V_OneDimensionalFloatAxis0) { @@ -536,16 +366,39 @@ TF_LITE_MICRO_TEST(SPLIT_V_OneDimensionalFloatAxis0) { float output7_values[] = {7}; int output8_shape[] = {1, 1}; float output8_values[] = {8}; - tflite::testing::TestSplitVEightOutputsFloat( - input_shape, input_values, axis_shape, axis_value, split_size_shape, - split, output1_shape, output1_values, output2_shape, output2_values, - output3_shape, output3_values, output4_shape, output4_values, - output5_shape, output5_values, output6_shape, output6_values, - output7_shape, output7_values, output8_shape, output8_values, - output1_data, - output2_data, // locally allocated output buffers - output3_data, output4_data, output5_data, output6_data, output7_data, - output8_data); + + tflite::testing::OutputTensors<8> output_tensors; + + output_tensors.data[0] = output1_data; + output_tensors.data[1] = output2_data; + output_tensors.data[2] = output3_data; + output_tensors.data[3] = output4_data; + output_tensors.data[4] = output5_data; + output_tensors.data[5] = output6_data; + output_tensors.data[6] = output7_data; + output_tensors.data[7] = output8_data; + + output_tensors.dims[0] = output1_shape; + output_tensors.dims[1] = output2_shape; + output_tensors.dims[2] = output3_shape; + output_tensors.dims[3] = output4_shape; + output_tensors.dims[4] = output5_shape; + output_tensors.dims[5] = output6_shape; + output_tensors.dims[6] = output7_shape; + output_tensors.dims[7] = output8_shape; + + output_tensors.expected_output_data[0] = output1_values; + output_tensors.expected_output_data[1] = output2_values; + output_tensors.expected_output_data[2] = output3_values; + output_tensors.expected_output_data[3] = output4_values; + output_tensors.expected_output_data[4] = output5_values; + output_tensors.expected_output_data[5] = output6_values; + output_tensors.expected_output_data[6] = output7_values; + output_tensors.expected_output_data[7] = output8_values; + + tflite::testing::TestSplitVFloat(input_shape, input_values, axis_shape, + axis_value, split_size_shape, split, + output_tensors); } TF_LITE_MICRO_TEST(SPLIT_V_OneDimensionalFloatTest2) { @@ -591,16 +444,39 @@ TF_LITE_MICRO_TEST(SPLIT_V_OneDimensionalFloatTest2) { float output7_values[] = {7, 8}; int output8_shape[] = {1, 0}; float output8_values[1] = {}; - tflite::testing::TestSplitVEightOutputsFloat( - input_shape, input_values, axis_shape, axis_value, split_size_shape, - split, output1_shape, output1_values, output2_shape, output2_values, - output3_shape, output3_values, output4_shape, output4_values, - output5_shape, output5_values, output6_shape, output6_values, - output7_shape, output7_values, output8_shape, output8_values, - output1_data, - output2_data, // locally allocated output buffers - output3_data, output4_data, output5_data, output6_data, output7_data, - nullptr); + + tflite::testing::OutputTensors<8> output_tensors; + + output_tensors.data[0] = output1_data; + output_tensors.data[1] = output2_data; + output_tensors.data[2] = output3_data; + output_tensors.data[3] = output4_data; + output_tensors.data[4] = output5_data; + output_tensors.data[5] = output6_data; + output_tensors.data[6] = output7_data; + output_tensors.data[7] = NULL; + + output_tensors.dims[0] = output1_shape; + output_tensors.dims[1] = output2_shape; + output_tensors.dims[2] = output3_shape; + output_tensors.dims[3] = output4_shape; + output_tensors.dims[4] = output5_shape; + output_tensors.dims[5] = output6_shape; + output_tensors.dims[6] = output7_shape; + output_tensors.dims[7] = output8_shape; + + output_tensors.expected_output_data[0] = output1_values; + output_tensors.expected_output_data[1] = output2_values; + output_tensors.expected_output_data[2] = output3_values; + output_tensors.expected_output_data[3] = output4_values; + output_tensors.expected_output_data[4] = output5_values; + output_tensors.expected_output_data[5] = output6_values; + output_tensors.expected_output_data[6] = output7_values; + output_tensors.expected_output_data[7] = output8_values; + + tflite::testing::TestSplitVFloat(input_shape, input_values, axis_shape, + axis_value, split_size_shape, split, + output_tensors); } TF_LITE_MICRO_TESTS_END