split.cc 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128
  1. /* Copyright 2019 The TensorFlow Authors. All Rights Reserved.
  2. Licensed under the Apache License, Version 2.0 (the "License");
  3. you may not use this file except in compliance with the License.
  4. You may obtain a copy of the License at
  5. http://www.apache.org/licenses/LICENSE-2.0
  6. Unless required by applicable law or agreed to in writing, software
  7. distributed under the License is distributed on an "AS IS" BASIS,
  8. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  9. See the License for the specific language governing permissions and
  10. limitations under the License.
  11. ==============================================================================*/
  12. #include "packages/TensorflowLiteMicro/tensorflow/lite/c/builtin_op_data.h"
  13. #include "packages/TensorflowLiteMicro/tensorflow/lite/c/common.h"
  14. #include "packages/TensorflowLiteMicro/tensorflow/lite/kernels/internal/tensor_ctypes.h"
  15. #include "packages/TensorflowLiteMicro/tensorflow/lite/kernels/kernel_util.h"
  16. namespace tflite {
  17. namespace ops {
  18. namespace micro {
  19. namespace split {
  20. template <typename T>
  21. TfLiteStatus SplitImpl(TfLiteContext* context, TfLiteNode* node,
  22. const TfLiteTensor* input, int axis_value) {
  23. const int output_count = NumOutputs(node);
  24. const TfLiteIntArray* input_dims = input->dims;
  25. const TfLiteTensor* output0 = GetOutput(context, node, 0);
  26. const TfLiteIntArray* output_dims = output0->dims;
  27. const int split_dimensions = input_dims->size;
  28. int axis = axis_value < 0 ? axis_value + split_dimensions : axis_value;
  29. TFLITE_DCHECK_LT(axis, split_dimensions);
  30. TFLITE_DCHECK_EQ(output_dims->size, split_dimensions);
  31. int64_t split_size = output_dims->data[axis] * output_count;
  32. TFLITE_DCHECK_EQ(split_size, input_dims->data[axis]);
  33. int64_t outer_size = 1;
  34. for (int i = 0; i < axis; ++i) {
  35. outer_size *= input_dims->data[i];
  36. }
  37. int64_t base_inner_size = 1;
  38. for (int i = axis + 1; i < split_dimensions; ++i) {
  39. base_inner_size *= input_dims->data[i];
  40. }
  41. const T* input_ptr = GetTensorData<T>(input);
  42. for (int k = 0; k < outer_size; ++k) {
  43. for (int i = 0; i < output_count; ++i) {
  44. TfLiteTensor* t = GetOutput(context, node, i);
  45. T* output_data = GetTensorData<T>(t);
  46. const int copy_size = output_dims->data[axis] * base_inner_size;
  47. T* output_ptr = output_data + k * copy_size;
  48. for (int j = 0; j < copy_size; ++j) output_ptr[j] = input_ptr[j];
  49. input_ptr += copy_size;
  50. }
  51. }
  52. return kTfLiteOk;
  53. }
  54. TfLiteStatus Eval(TfLiteContext* context, TfLiteNode* node) {
  55. const TfLiteTensor* axis = GetInput(context, node, 0);
  56. const TfLiteTensor* input = GetInput(context, node, 1);
  57. // Dynamic output tensors are needed if axis tensor is not constant.
  58. // But Micro doesn't support dynamic memory allocation, so we only support
  59. // constant axis tensor for now.
  60. TF_LITE_ENSURE_MSG(context, IsConstantTensor(axis),
  61. "Non constant axis tensor not supported");
  62. int axis_value = GetTensorData<int32_t>(axis)[0];
  63. if (axis_value < 0) {
  64. axis_value += NumDimensions(input);
  65. }
  66. TF_LITE_ENSURE(context, axis_value >= 0);
  67. TF_LITE_ENSURE(context, axis_value < NumDimensions(input));
  68. switch (input->type) {
  69. case kTfLiteFloat32: {
  70. return SplitImpl<float>(context, node, input, axis_value);
  71. }
  72. case kTfLiteUInt8: {
  73. return SplitImpl<uint8_t>(context, node, input, axis_value);
  74. }
  75. case kTfLiteInt8: {
  76. return SplitImpl<int8_t>(context, node, input, axis_value);
  77. }
  78. case kTfLiteInt16: {
  79. return SplitImpl<int16_t>(context, node, input, axis_value);
  80. }
  81. case kTfLiteInt32: {
  82. return SplitImpl<int32_t>(context, node, input, axis_value);
  83. }
  84. default:
  85. TF_LITE_KERNEL_LOG(context, "Type %s currently not supported.",
  86. TfLiteTypeGetName(input->type));
  87. return kTfLiteError;
  88. }
  89. #undef TF_LITE_SPLIT
  90. return kTfLiteOk;
  91. }
  92. } // namespace split
  93. TfLiteRegistration* Register_SPLIT() {
  94. static TfLiteRegistration r = {/*init=*/nullptr,
  95. /*free=*/nullptr,
  96. /*prepare=*/nullptr,
  97. /*invoke=*/split::Eval,
  98. /*profiling_string=*/nullptr,
  99. /*builtin_code=*/0,
  100. /*custom_name=*/nullptr,
  101. /*version=*/0};
  102. return &r;
  103. }
  104. } // namespace micro
  105. } // namespace ops
  106. } // namespace tflite