Add ceil op for micro
PiperOrigin-RevId: 262866402
This commit is contained in:
parent
d13df711d9
commit
f9233a5897
@ -15,6 +15,7 @@ cc_library(
|
||||
name = "micro_ops",
|
||||
srcs = [
|
||||
"arg_min_max.cc",
|
||||
"ceil.cc",
|
||||
"comparisons.cc",
|
||||
"conv.cc",
|
||||
"depthwise_conv.cc",
|
||||
@ -63,6 +64,7 @@ cc_library(
|
||||
name = "portable_optimized_micro_ops",
|
||||
srcs = [
|
||||
"arg_min_max.cc",
|
||||
"ceil.cc",
|
||||
"comparisons.cc",
|
||||
"conv.cc",
|
||||
"elementwise.cc",
|
||||
@ -276,6 +278,19 @@ tflite_micro_cc_test(
|
||||
],
|
||||
)
|
||||
|
||||
tflite_micro_cc_test(
|
||||
name = "ceil_test",
|
||||
srcs = [
|
||||
"ceil_test.cc",
|
||||
],
|
||||
deps = [
|
||||
":all_ops_resolver",
|
||||
"//tensorflow/lite/c:c_api_internal",
|
||||
"//tensorflow/lite/experimental/micro:micro_framework",
|
||||
"//tensorflow/lite/experimental/micro/testing:micro_test",
|
||||
],
|
||||
)
|
||||
|
||||
cc_library(
|
||||
name = "micro_utils",
|
||||
hdrs = ["micro_utils.h"],
|
||||
|
@ -45,6 +45,7 @@ TfLiteRegistration* Register_GREATER();
|
||||
TfLiteRegistration* Register_GREATER_EQUAL();
|
||||
TfLiteRegistration* Register_LESS();
|
||||
TfLiteRegistration* Register_LESS_EQUAL();
|
||||
TfLiteRegistration* Register_CEIL();
|
||||
|
||||
AllOpsResolver::AllOpsResolver() {
|
||||
AddBuiltin(BuiltinOperator_DEPTHWISE_CONV_2D, Register_DEPTHWISE_CONV_2D());
|
||||
@ -78,6 +79,7 @@ AllOpsResolver::AllOpsResolver() {
|
||||
AddBuiltin(BuiltinOperator_GREATER_EQUAL, Register_GREATER_EQUAL());
|
||||
AddBuiltin(BuiltinOperator_LESS, Register_LESS());
|
||||
AddBuiltin(BuiltinOperator_LESS_EQUAL, Register_LESS_EQUAL());
|
||||
AddBuiltin(BuiltinOperator_CEIL, Register_CEIL());
|
||||
}
|
||||
|
||||
} // namespace micro
|
||||
|
64
tensorflow/lite/experimental/micro/kernels/ceil.cc
Normal file
64
tensorflow/lite/experimental/micro/kernels/ceil.cc
Normal file
@ -0,0 +1,64 @@
|
||||
/* 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/kernels/internal/reference/ceil.h"
|
||||
|
||||
#include "tensorflow/lite/c/c_api_internal.h"
|
||||
#include "tensorflow/lite/kernels/internal/tensor_ctypes.h"
|
||||
#include "tensorflow/lite/kernels/kernel_util.h"
|
||||
|
||||
namespace tflite {
|
||||
namespace ops {
|
||||
namespace micro {
|
||||
namespace ceil {
|
||||
|
||||
constexpr int kInputTensor = 0;
|
||||
constexpr int kOutputTensor = 0;
|
||||
|
||||
TfLiteStatus Prepare(TfLiteContext* context, TfLiteNode* node) {
|
||||
const TfLiteTensor* input = GetInput(context, node, kInputTensor);
|
||||
TfLiteTensor* output = GetOutput(context, node, kOutputTensor);
|
||||
TF_LITE_ENSURE_EQ(context, NumInputs(node), 1);
|
||||
TF_LITE_ENSURE_EQ(context, NumOutputs(node), 1);
|
||||
TF_LITE_ENSURE_EQ(context, input->type, kTfLiteFloat32);
|
||||
TF_LITE_ENSURE_EQ(context, output->type, input->type);
|
||||
TF_LITE_ENSURE_EQ(context, output->bytes, input->bytes);
|
||||
TF_LITE_ENSURE_EQ(context, output->dims->size, input->dims->size);
|
||||
for (int i = 0; i < output->dims->size; ++i) {
|
||||
TF_LITE_ENSURE_EQ(context, output->dims->data[i], input->dims->data[i]);
|
||||
}
|
||||
return kTfLiteOk;
|
||||
}
|
||||
|
||||
TfLiteStatus Eval(TfLiteContext* context, TfLiteNode* node) {
|
||||
const TfLiteTensor* input = GetInput(context, node, kInputTensor);
|
||||
TfLiteTensor* output = GetOutput(context, node, kOutputTensor);
|
||||
|
||||
reference_ops::Ceil(GetTensorShape(input), GetTensorData<float>(input),
|
||||
GetTensorShape(output), GetTensorData<float>(output));
|
||||
|
||||
return kTfLiteOk;
|
||||
}
|
||||
} // namespace ceil
|
||||
|
||||
TfLiteRegistration* Register_CEIL() {
|
||||
static TfLiteRegistration r = {/*init=*/nullptr,
|
||||
/*free=*/nullptr, ceil::Prepare, ceil::Eval};
|
||||
return &r;
|
||||
}
|
||||
|
||||
} // namespace micro
|
||||
} // namespace ops
|
||||
} // namespace tflite
|
103
tensorflow/lite/experimental/micro/kernels/ceil_test.cc
Normal file
103
tensorflow/lite/experimental/micro/kernels/ceil_test.cc
Normal file
@ -0,0 +1,103 @@
|
||||
/* 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/c_api_internal.h"
|
||||
#include "tensorflow/lite/experimental/micro/kernels/all_ops_resolver.h"
|
||||
#include "tensorflow/lite/experimental/micro/testing/micro_test.h"
|
||||
#include "tensorflow/lite/experimental/micro/testing/test_utils.h"
|
||||
|
||||
namespace tflite {
|
||||
namespace testing {
|
||||
namespace {
|
||||
|
||||
void TestCeil(std::initializer_list<int> input_dims_data,
|
||||
std::initializer_list<float> input_data,
|
||||
std::initializer_list<float> expected_output_data,
|
||||
float* output_data) {
|
||||
TfLiteIntArray* input_dims = IntArrayFromInitializer(input_dims_data);
|
||||
TfLiteIntArray* output_dims = IntArrayFromInitializer(input_dims_data);
|
||||
const int output_dims_count = ElementCount(*output_dims);
|
||||
constexpr int inputs_size = 1;
|
||||
constexpr int outputs_size = 1;
|
||||
constexpr int tensors_size = inputs_size + outputs_size;
|
||||
TfLiteTensor tensors[tensors_size] = {
|
||||
CreateFloatTensor(input_data, input_dims, "input_tensor"),
|
||||
CreateFloatTensor(output_data, output_dims, "output_tensor"),
|
||||
};
|
||||
TfLiteContext context;
|
||||
PopulateContext(tensors, tensors_size, &context);
|
||||
::tflite::ops::micro::AllOpsResolver resolver;
|
||||
const TfLiteRegistration* registration =
|
||||
resolver.FindOp(tflite::BuiltinOperator_CEIL, 1);
|
||||
TF_LITE_MICRO_EXPECT_NE(nullptr, registration);
|
||||
|
||||
int inputs_array_data[] = {1, 0};
|
||||
TfLiteIntArray* inputs_array = IntArrayFromInts(inputs_array_data);
|
||||
int outputs_array_data[] = {1, 1};
|
||||
TfLiteIntArray* outputs_array = IntArrayFromInts(outputs_array_data);
|
||||
TfLiteIntArray* temporaries_array = IntArrayFromInitializer({0});
|
||||
TfLiteNode node;
|
||||
node.inputs = inputs_array;
|
||||
node.outputs = outputs_array;
|
||||
node.temporaries = temporaries_array;
|
||||
node.user_data = nullptr;
|
||||
node.builtin_data = nullptr;
|
||||
node.custom_initial_data = nullptr;
|
||||
node.custom_initial_data_size = 0;
|
||||
node.delegate = nullptr;
|
||||
TF_LITE_MICRO_EXPECT_NE(nullptr, registration->invoke);
|
||||
TF_LITE_MICRO_EXPECT_EQ(kTfLiteOk, registration->invoke(&context, &node));
|
||||
for (int i = 0; i < output_dims_count; ++i) {
|
||||
TF_LITE_MICRO_EXPECT_NEAR(expected_output_data.begin()[i], output_data[i],
|
||||
1e-5f);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace
|
||||
} // namespace testing
|
||||
} // namespace tflite
|
||||
|
||||
TF_LITE_MICRO_TESTS_BEGIN
|
||||
|
||||
TF_LITE_MICRO_TEST(SingleDim) {
|
||||
float output_data[2];
|
||||
tflite::testing::TestCeil({1, 2}, // input_dims_data
|
||||
{8.5, 0.0}, // input_data
|
||||
{9, 0}, // expected_output_data
|
||||
output_data);
|
||||
}
|
||||
|
||||
TF_LITE_MICRO_TEST(MultiDims) {
|
||||
float output_data[10];
|
||||
tflite::testing::TestCeil(
|
||||
{4, 2, 1, 1, 5}, // input_dims_data
|
||||
{
|
||||
0.0001,
|
||||
8.0001,
|
||||
0.9999,
|
||||
9.9999,
|
||||
0.5,
|
||||
-0.0001,
|
||||
-8.0001,
|
||||
-0.9999,
|
||||
-9.9999,
|
||||
-0.5,
|
||||
}, // input_data
|
||||
{1, 9, 1, 10, 1, 0, -8, 0, -9, 0}, // expected_output_data
|
||||
output_data);
|
||||
}
|
||||
|
||||
TF_LITE_MICRO_TESTS_END
|
@ -109,6 +109,7 @@ tensorflow/lite/kernels/internal/compatibility.h \
|
||||
tensorflow/lite/kernels/internal/optimized/neon_check.h \
|
||||
tensorflow/lite/kernels/internal/reference/binary_function.h \
|
||||
tensorflow/lite/kernels/internal/reference/comparisons.h \
|
||||
tensorflow/lite/kernels/internal/reference/ceil.h \
|
||||
tensorflow/lite/kernels/internal/reference/conv.h \
|
||||
tensorflow/lite/kernels/internal/reference/depthwiseconv_float.h \
|
||||
tensorflow/lite/kernels/internal/reference/depthwiseconv_uint8.h \
|
||||
|
@ -361,6 +361,7 @@ cc_library(
|
||||
"reference/add.h",
|
||||
"reference/arg_min_max.h",
|
||||
"reference/binary_function.h",
|
||||
"reference/ceil.h",
|
||||
"reference/comparisons.h",
|
||||
"reference/conv.h",
|
||||
"reference/depthwiseconv_float.h",
|
||||
@ -423,6 +424,7 @@ cc_library(
|
||||
"reference/add.h",
|
||||
"reference/arg_min_max.h",
|
||||
"reference/binary_function.h",
|
||||
"reference/ceil.h",
|
||||
"reference/comparisons.h",
|
||||
"reference/conv.h",
|
||||
"reference/depthwiseconv_float.h",
|
||||
|
37
tensorflow/lite/kernels/internal/reference/ceil.h
Normal file
37
tensorflow/lite/kernels/internal/reference/ceil.h
Normal file
@ -0,0 +1,37 @@
|
||||
/* 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.
|
||||
==============================================================================*/
|
||||
#ifndef TENSORFLOW_LITE_KERNELS_INTERNAL_REFERENCE_CEIL_H_
|
||||
#define TENSORFLOW_LITE_KERNELS_INTERNAL_REFERENCE_CEIL_H_
|
||||
|
||||
#include <cmath>
|
||||
|
||||
#include "tensorflow/lite/kernels/internal/types.h"
|
||||
|
||||
namespace tflite {
|
||||
|
||||
namespace reference_ops {
|
||||
|
||||
inline void Ceil(const RuntimeShape& input_shape, const float* input_data,
|
||||
const RuntimeShape& output_shape, float* output_data) {
|
||||
const int flat_size = MatchingFlatSize(input_shape, output_shape);
|
||||
|
||||
for (int i = 0; i < flat_size; ++i) {
|
||||
output_data[i] = std::ceil(input_data[i]);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace reference_ops
|
||||
} // namespace tflite
|
||||
#endif // TENSORFLOW_LITE_KERNELS_INTERNAL_REFERENCE_CEIL_H_
|
@ -35,6 +35,7 @@ limitations under the License.
|
||||
#include "tensorflow/lite/kernels/internal/reference/add.h"
|
||||
#include "tensorflow/lite/kernels/internal/reference/arg_min_max.h"
|
||||
#include "tensorflow/lite/kernels/internal/reference/binary_function.h"
|
||||
#include "tensorflow/lite/kernels/internal/reference/ceil.h"
|
||||
#include "tensorflow/lite/kernels/internal/reference/comparisons.h"
|
||||
#include "tensorflow/lite/kernels/internal/reference/conv.h"
|
||||
#include "tensorflow/lite/kernels/internal/reference/floor.h"
|
||||
@ -2158,16 +2159,6 @@ T FloorMod(T input1, T input2) {
|
||||
: trunc_mod;
|
||||
}
|
||||
|
||||
inline void Ceil(const RuntimeShape& input_shape, const float* input_data,
|
||||
const RuntimeShape& output_shape, float* output_data) {
|
||||
const int flat_size = MatchingFlatSize(input_shape, output_shape);
|
||||
|
||||
for (int i = 0; i < flat_size; i++) {
|
||||
int offset = i;
|
||||
output_data[offset] = std::ceil(input_data[offset]);
|
||||
}
|
||||
}
|
||||
|
||||
inline float RoundToNearest(float value) {
|
||||
auto floor_val = std::floor(value);
|
||||
auto diff = value - floor_val;
|
||||
|
Loading…
x
Reference in New Issue
Block a user